Exemplo n.º 1
0
 async def _get_options(self, ctx):
     bw, addon, state, taxon = database.hmget(f"session.data:{ctx.author.id}", ["bw", "addon", "state", "taxon"])
     options = str(
         f"**Age/Sex:** {addon.decode('utf-8') if addon else 'default'}\n" + f"**Black & White:** {bw==b'bw'}\n" +
         f"**State bird list:** {state.decode('utf-8') if state else 'None'}\n" +
         f"**Bird taxon:** {taxon.decode('utf-8') if taxon else 'None'}\n"
     )
     return options
Exemplo n.º 2
0
 async def _get_options(self, ctx):
     bw, addon, state, media, limit, taxon = database.hmget(
         f"race.data:{ctx.channel.id}",
         ["bw", "addon", "state", "media", "limit", "taxon"])
     options = str(
         f"**Age/Sex:** {addon.decode('utf-8') if addon else 'default'}\n" +
         f"**Black & White:** {bw==b'bw'}\n" +
         f"**Special bird list:** {state.decode('utf-8') if state else 'None'}\n"
         + f"**Taxons:** {taxon.decode('utf-8') if taxon else 'None'}\n" +
         f"**Media Type:** {media.decode('utf-8')}\n" +
         f"**Amount to Win:** {limit.decode('utf-8')}\n")
     return options
Exemplo n.º 3
0
 async def _get_options(self, ctx):
     filter_int, state, taxon, wiki, strict = database.hmget(
         f"session.data:{ctx.author.id}",
         ["filter", "state", "taxon", "wiki", "strict"],
     )
     filters = Filter.from_int(int(filter_int))
     options = textwrap.dedent(f"""\
         **Active Filters:** `{'`, `'.join(filters.display())}`
         **State bird list:** {state.decode('utf-8') if state else 'None'}
         **Bird taxon:** {taxon.decode('utf-8') if taxon else 'None'}
         **Wiki Embeds**: {wiki==b'wiki'}
         **Strict Spelling**: {strict==b'strict'}
         """)
     return options
Exemplo n.º 4
0
    async def _get_stats(self, ctx):
        start, correct, incorrect, total = map(
            int, database.hmget(f"session.data:{ctx.author.id}", ["start", "correct", "incorrect", "total"])
        )
        elapsed = str(datetime.timedelta(seconds=round(time.time()) - start))
        try:
            accuracy = round(100 * (correct / (correct + incorrect)), 2)
        except ZeroDivisionError:
            accuracy = 0

        stats = str(
            f"**Duration:** `{elapsed}`\n" + f"**# Correct:** {correct}\n" + f"**# Incorrect:** {incorrect}\n" +
            f"**Total Birds:** {total}\n" + f"**Accuracy:** {accuracy}%\n"
        )
        return stats
Exemplo n.º 5
0
 async def _get_options(self, ctx):
     filter_int, state, media, limit, taxon, strict, alpha = database.hmget(
         f"race.data:{ctx.channel.id}",
         ["filter", "state", "media", "limit", "taxon", "strict", "alpha"],
     )
     filters = Filter.from_int(int(filter_int))
     options = (
         f"**Active Filters:** `{'`, `'.join(filters.display())}`\n"
         + f"**Special bird list:** {state.decode('utf-8') if state else 'None'}\n"
         + f"**Taxons:** {taxon.decode('utf-8') if taxon else 'None'}\n"
         + f"**Media Type:** {media.decode('utf-8')}\n"
         + f"**Amount to Win:** {limit.decode('utf-8')}\n"
         + f"**Strict Spelling:** {strict == b'strict'}\n"
         + f"**Alpha Codes:** {'Enabled' if alpha == b'alpha' else 'Disabled'}"
     )
     return options
Exemplo n.º 6
0
    async def skip(self, ctx):
        logger.info("command: skip")

        currentBird = database.hget(f"channel:{ctx.channel.id}",
                                    "bird").decode("utf-8")
        database.hset(f"channel:{ctx.channel.id}", "bird", "")
        database.hset(f"channel:{ctx.channel.id}", "answered", "1")
        if currentBird != "":  # check if there is bird
            url = get_wiki_url(ctx, currentBird)
            await ctx.send(f"Ok, skipping {currentBird.lower()}")
            await ctx.send(url)  # sends wiki page

            streak_increment(ctx, None)  # reset streak

            if database.exists(f"race.data:{ctx.channel.id}"):
                if Filter.from_int(
                        int(
                            database.hget(f"race.data:{ctx.channel.id}",
                                          "filter"))).vc:
                    await voice_functions.stop(ctx, silent=True)

                media = database.hget(f"race.data:{ctx.channel.id}",
                                      "media").decode("utf-8")

                limit = int(
                    database.hget(f"race.data:{ctx.channel.id}", "limit"))
                first = database.zrevrange(f"race.scores:{ctx.channel.id}", 0,
                                           0, True)[0]
                if int(first[1]) >= limit:
                    logger.info("race ending")
                    race = self.bot.get_cog("Race")
                    await race.stop_race_(ctx)
                else:
                    logger.info(f"auto sending next bird {media}")
                    filter_int, taxon, state = database.hmget(
                        f"race.data:{ctx.channel.id}",
                        ["filter", "taxon", "state"])
                    birds = self.bot.get_cog("Birds")
                    await birds.send_bird_(
                        ctx,
                        media,
                        Filter.from_int(int(filter_int)),
                        taxon.decode("utf-8"),
                        state.decode("utf-8"),
                    )
        else:
            await ctx.send("You need to ask for a bird first!")
Exemplo n.º 7
0
    async def skip(self, ctx):
        logger.info("command: skip")

        await channel_setup(ctx)
        await user_setup(ctx)

        currentBird = str(database.hget(f"channel:{ctx.channel.id}",
                                        "bird"))[2:-1]
        database.hset(f"channel:{ctx.channel.id}", "bird", "")
        database.hset(f"channel:{ctx.channel.id}", "answered", "1")
        if currentBird != "":  # check if there is bird
            url = get_wiki_url(currentBird)
            await ctx.send(f"Ok, skipping {currentBird.lower()}")
            await ctx.send(
                url if not database.exists(f"race.data:{ctx.channel.id}") else
                f"<{url}>")  # sends wiki page
            database.zadd("streak:global",
                          {str(ctx.author.id): 0})  # end streak
            if database.exists(
                    f"race.data:{ctx.channel.id}") and database.hget(
                        f"race.data:{ctx.channel.id}",
                        "media").decode("utf-8") == "image":

                limit = int(
                    database.hget(f"race.data:{ctx.channel.id}", "limit"))
                first = database.zrevrange(f"race.scores:{ctx.channel.id}", 0,
                                           0, True)[0]
                if int(first[1]) >= limit:
                    logger.info("race ending")
                    race = self.bot.get_cog("Race")
                    await race.stop_race_(ctx)
                else:
                    logger.info("auto sending next bird image")
                    addon, bw, taxon = database.hmget(
                        f"race.data:{ctx.channel.id}",
                        ["addon", "bw", "taxon"])
                    birds = self.bot.get_cog("Birds")
                    await birds.send_bird_(ctx, addon.decode("utf-8"),
                                           bw.decode("utf-8"),
                                           taxon.decode("utf-8"))
        else:
            await ctx.send("You need to ask for a bird first!")
Exemplo n.º 8
0
    async def _send_next_race_media(self, ctx):
        if database.exists(f"race.data:{ctx.channel.id}"):
            if Filter.from_int(
                    int(database.hget(f"race.data:{ctx.channel.id}",
                                      "filter"))).vc:
                await voice_functions.stop(ctx, silent=True)

            media = database.hget(f"race.data:{ctx.channel.id}",
                                  "media").decode("utf-8")

            logger.info(f"auto sending next bird {media}")
            filter_int, taxon, state = database.hmget(
                f"race.data:{ctx.channel.id}", ["filter", "taxon", "state"])

            await self.send_bird_(
                ctx,
                media,
                Filter.from_int(int(filter_int)),
                taxon.decode("utf-8"),
                state.decode("utf-8"),
            )
Exemplo n.º 9
0
    async def check(self, ctx, *, arg):
        logger.info("command: check")

        await channel_setup(ctx)
        await user_setup(ctx)

        currentBird = database.hget(f"channel:{ctx.channel.id}",
                                    "bird").decode("utf-8")
        if currentBird == "":  # no bird
            await ctx.send("You must ask for a bird first!")
        else:  # if there is a bird, it checks answer
            logger.info("currentBird: " +
                        str(currentBird.lower().replace("-", " ")))
            logger.info("args: " + str(arg.lower().replace("-", " ")))

            await bird_setup(ctx, currentBird)
            sciBird = await get_sciname(currentBird)
            if spellcheck(arg, currentBird) or spellcheck(arg, sciBird):
                logger.info("correct")

                database.hset(f"channel:{ctx.channel.id}", "bird", "")
                database.hset(f"channel:{ctx.channel.id}", "answered", "1")

                if database.exists(f"session.data:{ctx.author.id}"):
                    logger.info("session active")
                    session_increment(ctx, "correct", 1)

                database.zincrby("streak:global", 1, str(ctx.author.id))
                # check if streak is greater than max, if so, increases max
                if database.zscore("streak:global", str(
                        ctx.author.id)) > database.zscore(
                            "streak.max:global", str(ctx.author.id)):
                    database.zadd(
                        "streak.max:global", {
                            str(ctx.author.id):
                            database.zscore("streak:global", str(
                                ctx.author.id))
                        })

                await ctx.send("Correct! Good job!" if not database.
                               exists(f"race.data:{ctx.channel.id}") else
                               f"**{ctx.author.mention}**, you are correct!")
                url = get_wiki_url(currentBird)
                await ctx.send(url if not database.exists(
                    f"race.data:{ctx.channel.id}") else f"<{url}>")
                score_increment(ctx, 1)
                if int(database.zscore("users:global",
                                       str(ctx.author.id))) in achievement:
                    number = str(
                        int(database.zscore("users:global",
                                            str(ctx.author.id))))
                    await ctx.send(
                        f"Wow! You have answered {number} birds correctly!")
                    filename = f"bot/media/achievements/{number}.PNG"
                    with open(filename, 'rb') as img:
                        await ctx.send(
                            file=discord.File(img, filename="award.png"))

                if database.exists(f"race.data:{ctx.channel.id}") and str(
                        database.hget(f"race.data:{ctx.channel.id}",
                                      "media"))[2:-1] == "image":

                    limit = int(
                        database.hget(f"race.data:{ctx.channel.id}", "limit"))
                    first = database.zrevrange(f"race.scores:{ctx.channel.id}",
                                               0, 0, True)[0]
                    if int(first[1]) >= limit:
                        logger.info("race ending")
                        race = self.bot.get_cog("Race")
                        await race.stop_race_(ctx)
                    else:
                        logger.info("auto sending next bird image")
                        addon, bw, taxon = database.hmget(
                            f"race.data:{ctx.channel.id}",
                            ["addon", "bw", "taxon"])
                        birds = self.bot.get_cog("Birds")
                        await birds.send_bird_(ctx, addon.decode("utf-8"),
                                               bw.decode("utf-8"),
                                               taxon.decode("utf-8"))

            else:
                logger.info("incorrect")

                database.zadd("streak:global", {str(ctx.author.id): 0})

                if database.exists(f"session.data:{ctx.author.id}"):
                    logger.info("session active")
                    session_increment(ctx, "incorrect", 1)

                incorrect_increment(ctx, str(currentBird), 1)

                if database.exists(f"race.data:{ctx.channel.id}"):
                    await ctx.send("Sorry, that wasn't the right answer.")
                else:
                    database.hset(f"channel:{ctx.channel.id}", "bird", "")
                    database.hset(f"channel:{ctx.channel.id}", "answered", "1")
                    await ctx.send("Sorry, the bird was actually " +
                                   currentBird.lower() + ".")
                    url = get_wiki_url(currentBird)
                    await ctx.send(url)
Exemplo n.º 10
0
    async def check(self, ctx, *, arg):
        logger.info("command: check")

        currentBird = database.hget(f"channel:{ctx.channel.id}",
                                    "bird").decode("utf-8")
        if currentBird == "":  # no bird
            await ctx.send("You must ask for a bird first!")
            return
        # if there is a bird, it checks answer
        sciBird = (await get_sciname(currentBird)).lower().replace("-", " ")
        arg = arg.lower().replace("-", " ")
        currentBird = currentBird.lower().replace("-", " ")
        alpha_code = alpha_codes.get(string.capwords(currentBird))
        logger.info("currentBird: " + currentBird)
        logger.info("arg: " + arg)

        bird_setup(ctx, currentBird)

        race_in_session = bool(database.exists(f"race.data:{ctx.channel.id}"))
        if race_in_session:
            logger.info("race in session")
            if database.hget(f"race.data:{ctx.channel.id}", "strict"):
                logger.info("strict spelling")
                correct = arg in (currentBird, sciBird)
            else:
                logger.info("spelling leniency")
                correct = spellcheck(arg, currentBird) or spellcheck(
                    arg, sciBird)

            if not correct and database.hget(f"race.data:{ctx.channel.id}",
                                             "alpha"):
                logger.info("checking alpha codes")
                correct = arg.upper() == alpha_code
        else:
            logger.info("no race")
            if database.hget(f"session.data:{ctx.author.id}", "strict"):
                logger.info("strict spelling")
                correct = arg in (currentBird, sciBird)
            else:
                logger.info("spelling leniency")
                correct = (spellcheck(arg, currentBird)
                           or spellcheck(arg, sciBird)
                           or arg.upper() == alpha_code)

        if correct:
            logger.info("correct")

            database.hset(f"channel:{ctx.channel.id}", "bird", "")
            database.hset(f"channel:{ctx.channel.id}", "answered", "1")

            session_increment(ctx, "correct", 1)
            streak_increment(ctx, 1)
            database.zincrby(f"correct.user:{ctx.author.id}", 1,
                             string.capwords(str(currentBird)))

            if (race_in_session and Filter.from_int(
                    int(database.hget(f"race.data:{ctx.channel.id}",
                                      "filter"))).vc):
                await voice_functions.stop(ctx, silent=True)

            await ctx.send(
                f"Correct! Good job! The bird was **{currentBird}**."
                if not race_in_session else
                f"**{ctx.author.mention}**, you are correct! The bird was **{currentBird}**."
            )
            url = get_wiki_url(ctx, currentBird)
            await ctx.send(url)
            score_increment(ctx, 1)
            if int(database.zscore("users:global",
                                   str(ctx.author.id))) in achievement:
                number = str(
                    int(database.zscore("users:global", str(ctx.author.id))))
                await ctx.send(
                    f"Wow! You have answered {number} birds correctly!")
                filename = f"bot/media/achievements/{number}.PNG"
                with open(filename, "rb") as img:
                    await ctx.send(file=discord.File(img, filename="award.png")
                                   )

            if race_in_session:
                media = database.hget(f"race.data:{ctx.channel.id}",
                                      "media").decode("utf-8")

                limit = int(
                    database.hget(f"race.data:{ctx.channel.id}", "limit"))
                first = database.zrevrange(f"race.scores:{ctx.channel.id}", 0,
                                           0, True)[0]
                if int(first[1]) >= limit:
                    logger.info("race ending")
                    race = self.bot.get_cog("Race")
                    await race.stop_race_(ctx)
                else:
                    logger.info(f"auto sending next bird {media}")
                    filter_int, taxon, state = database.hmget(
                        f"race.data:{ctx.channel.id}",
                        ["filter", "taxon", "state"])
                    birds = self.bot.get_cog("Birds")
                    await birds.send_bird_(
                        ctx,
                        media,
                        Filter.from_int(int(filter_int)),
                        taxon.decode("utf-8"),
                        state.decode("utf-8"),
                    )

        else:
            logger.info("incorrect")

            streak_increment(ctx, None)  # reset streak
            session_increment(ctx, "incorrect", 1)
            incorrect_increment(ctx, str(currentBird), 1)

            if race_in_session:
                await ctx.send("Sorry, that wasn't the right answer.")
            else:
                database.hset(f"channel:{ctx.channel.id}", "bird", "")
                database.hset(f"channel:{ctx.channel.id}", "answered", "1")
                await ctx.send("Sorry, the bird was actually **" +
                               currentBird + "**.")
                url = get_wiki_url(ctx, currentBird)
                await ctx.send(url)
Exemplo n.º 11
0
    async def start(self, ctx, *, args_str: str = ""):
        logger.info("command: start race")

        if not str(ctx.channel.name).startswith("racing"):
            logger.info("not race channel")
            await ctx.send(
                "**Sorry, racing is not available in this channel.**\n"
                + "*Set the channel name to start with `racing` to enable it.*"
            )
            return

        if database.exists(f"race.data:{ctx.channel.id}"):
            logger.info("already race")
            await ctx.send(
                "**There is already a race in session.** *Change settings/view stats with `b!race view`*"
            )
            return

        filters = Filter.parse(args_str, use_numbers=False)
        if filters.vc:
            if database.get(f"voice.server:{ctx.guild.id}") is not None:
                logger.info("already vc race")
                await ctx.send(
                    "**There is already a VC race in session in this server!**"
                )
                return
            client = await voice_functions.get_voice_client(ctx, connect=True)
            if client is None:
                return
            database.set(f"voice.server:{ctx.guild.id}", str(ctx.channel.id))

        args = args_str.split(" ")
        logger.info(f"args: {args}")

        taxon_args = set(taxons.keys()).intersection({arg.lower() for arg in args})
        if taxon_args:
            taxon = " ".join(taxon_args).strip()
        else:
            taxon = ""

        if "strict" in args:
            strict = "strict"
        else:
            strict = ""

        if "alpha" in args:
            alpha = "alpha"
        else:
            alpha = ""

        states_args = set(states.keys()).intersection({arg.upper() for arg in args})
        if states_args:
            if {"CUSTOM"}.issubset(states_args):
                if database.exists(
                    f"custom.list:{ctx.author.id}"
                ) and not database.exists(f"custom.confirm:{ctx.author.id}"):
                    states_args.discard("CUSTOM")
                    states_args.add(f"CUSTOM:{ctx.author.id}")
                else:
                    states_args.discard("CUSTOM")
                    await ctx.send(
                        "**You don't have a custom list set.**\n*Ignoring the argument.*"
                    )
            state = " ".join(states_args).strip()
        else:
            state = ""

        song = "song" in args or "songs" in args or "s" in args or filters.vc
        image = (
            "image" in args
            or "images" in args
            or "i" in args
            or "picture" in args
            or "pictures" in args
            or "p" in args
        )
        if song and image:
            await ctx.send(
                "**Songs and images are not yet supported.**\n*Please try again*"
            )
            return
        if song:
            media = "song"
        elif image:
            media = "image"
        else:
            media = "image"

        ints = []
        for n in args:
            try:
                ints.append(int(n))
            except ValueError:
                continue
        if ints:
            limit = int(ints[0])
        else:
            limit = 10

        if limit > 1000000:
            await ctx.send("**Sorry, the maximum amount to win is 1 million.**")
            limit = 1000000

        logger.info(
            f"adding filters: {filters}; state: {state}; media: {media}; limit: {limit}"
        )

        database.hset(
            f"race.data:{ctx.channel.id}",
            mapping={
                "start": round(time.time()),
                "stop": 0,
                "limit": limit,
                "filter": str(filters.to_int()),
                "state": state,
                "media": media,
                "taxon": taxon,
                "strict": strict,
                "alpha": alpha,
            },
        )

        database.zadd(f"race.scores:{ctx.channel.id}", {str(ctx.author.id): 0})
        await ctx.send(
            f"**Race started with options:**\n{await self._get_options(ctx)}"
        )

        media = database.hget(f"race.data:{ctx.channel.id}", "media").decode("utf-8")
        logger.info("clearing previous bird")
        database.hset(f"channel:{ctx.channel.id}", "bird", "")
        database.hset(f"channel:{ctx.channel.id}", "answered", "1")

        logger.info(f"auto sending next bird {media}")
        filter_int, taxon, state = database.hmget(
            f"race.data:{ctx.channel.id}", ["filter", "taxon", "state"]
        )
        birds = self.bot.get_cog("Birds")
        await birds.send_bird_(
            ctx,
            media,
            Filter.from_int(int(filter_int)),  # type: ignore
            taxon.decode("utf-8"),  # type: ignore
            state.decode("utf-8"),  # type: ignore
        )
Exemplo n.º 12
0
    async def start(self, ctx, *, args_str: str = ""):
        logger.info("command: start race")

        await channel_setup(ctx)
        await user_setup(ctx)

        if ctx.guild is None:
            logger.info("dm context")
            await ctx.send("**Sorry, racing is not avaliable in DMs.**")
            return

        if not str(ctx.channel.name).startswith("racing"):
            logger.info("not race channel")
            await ctx.send(
                "**Sorry, racing is not availiable in this channel.**\n" +
                "*Set the channel name to start with `racing` to enable it.*")
            return

        if database.exists(f"race.data:{ctx.channel.id}"):
            logger.info("already race")
            await ctx.send(
                "**There is already a race in session.** *Change settings/view stats with `b!race view`*"
            )
            return
        else:
            args = args_str.split(" ")
            logger.info(f"args: {args}")
            if "bw" in args:
                bw = "bw"
            else:
                bw = ""

            taxon_args = set(taxons.keys()).intersection(
                {arg.lower()
                 for arg in args})
            if taxon_args:
                taxon = " ".join(taxon_args).strip()
            else:
                taxon = ""

            states_args = set(states.keys()).intersection(
                {arg.upper()
                 for arg in args})
            if states_args:
                state = " ".join(states_args).strip()
            else:
                state = " ".join(check_state_role(ctx))

            female = "female" in args or "f" in args
            juvenile = "juvenile" in args or "j" in args
            if female and juvenile:
                await ctx.send(
                    "**Juvenile females are not yet supported.**\n*Please try again*"
                )
                return
            elif female:
                addon = "female"
            elif juvenile:
                addon = "juvenile"
            else:
                addon = ""

            song = "song" in args or "s" in args
            image = "image" in args or "i" in args or "picture" in args or "p" in args
            if song and image:
                await ctx.send(
                    "**Songs and images are not yet supported.**\n*Please try again*"
                )
                return
            elif song:
                media = "song"
            elif image:
                media = "image"
            else:
                media = "image"

            ints = []
            for n in args:
                try:
                    ints.append(int(n))
                except ValueError:
                    continue
            if ints:
                limit = int(ints[0])
            else:
                limit = 10

            if limit > 1000000:
                await ctx.send(
                    "**Sorry, the maximum amount to win is 1 million.**")
                limit = 1000000

            logger.info(
                f"adding bw: {bw}; addon: {addon}; state: {state}; media: {media}; limit: {limit}"
            )

            database.hmset(
                f"race.data:{ctx.channel.id}", {
                    "start": round(time.time()),
                    "stop": 0,
                    "limit": limit,
                    "bw": bw,
                    "state": state,
                    "addon": addon,
                    "media": media,
                    "taxon": taxon
                })

            database.zadd(f"race.scores:{ctx.channel.id}",
                          {str(ctx.author.id): 0})
            await ctx.send(
                f"**Race started with options:**\n{await self._get_options(ctx)}"
            )

            if database.hget(f"race.data:{ctx.channel.id}",
                             "media").decode("utf-8") == "image":
                logger.info("clearing previous bird")
                database.hset(f"channel:{ctx.channel.id}", "bird", "")
                database.hset(f"channel:{ctx.channel.id}", "answered", "1")

                logger.info("auto sending next bird image")
                addon, bw, taxon = database.hmget(
                    f"race.data:{ctx.channel.id}", ["addon", "bw", "taxon"])
                birds = self.bot.get_cog("Birds")
                await birds.send_bird_(
                    ctx,
                    addon.decode("utf-8"),  # type: ignore
                    bw.decode("utf-8"),  # type: ignore
                    taxon.decode("utf-8")  # type: ignore
                )

            if database.hget(f"race.data:{ctx.channel.id}",
                             "media").decode("utf-8") == "song":
                logger.info("clearing previous bird")
                database.hset(f"channel:{ctx.channel.id}", "sBird", "")
                database.hset(f"channel:{ctx.channel.id}", "sAnswered", "1")

                logger.info("auto sending next bird song")
                birds = self.bot.get_cog("Birds")
                await birds.send_song_(ctx)