async def userscore( self, ctx, *, user: typing.Optional[typing.Union[discord.Member, str]] = None ): logger.info("command: userscore") if user is not None: if isinstance(user, str): await ctx.send("Not a user!") return usera = user.id logger.info(usera) score = database.zscore("users:global", str(usera)) if score is not None: score = int(score) user = f"<@{usera}>" else: await ctx.send("This user does not exist on our records!") return else: user = f"<@{ctx.author.id}>" score = int(database.zscore("users:global", str(ctx.author.id))) embed = discord.Embed(type="rich", colour=discord.Color.blurple()) embed.set_author(name="Bird ID - An Ornithology Bot") embed.add_field( name="User Score:", value=f"{user} has answered correctly {score} times." ) await ctx.send(embed=embed)
def moderation_check(ctx): """Checks different moderation checks. Disallows: - Users that are banned from the bot, - Channels that are ignored """ logger.info("global check: checking banned") if database.zscore("ignore:global", str(ctx.channel.id)) is not None: raise GenericError(code=192) if database.zscore("banned:global", str(ctx.author.id)) is not None: raise GenericError(code=842) return True
async def user_setup(ctx): """Sets up a new discord user for score tracking. `ctx` - Discord context object or user id """ if isinstance(ctx, (str, int)): user_id = str(ctx) guild = None ctx = None else: user_id = str(ctx.author.id) guild = ctx.guild logger.info("checking user data") if database.zscore("users:global", user_id) is None: database.zadd("users:global", {user_id: 0}) logger.info("user global added") if ctx is not None: await ctx.send("Welcome <@" + user_id + ">!") date = str(datetime.datetime.now(datetime.timezone.utc).date()) if database.zscore(f"daily.score:{date}", user_id) is None: database.zadd(f"daily.score:{date}", {user_id: 0}) logger.info("user daily added") # Add streak if (database.zscore("streak:global", user_id) is None) or (database.zscore( "streak.max:global", user_id) is None): database.zadd("streak:global", {user_id: 0}) database.zadd("streak.max:global", {user_id: 0}) logger.info("added streak") if guild is not None: global_score = database.zscore("users:global", str(ctx.author.id)) database.zadd(f"users.server:{ctx.guild.id}", {str(ctx.author.id): global_score}) logger.info("synced scores") if not database.exists(f"custom.list:{ctx.author.id}"): role_ids = [role.id for role in ctx.author.roles] role_names = [role.name.lower() for role in ctx.author.roles] if set(role_names).intersection(set(states["CUSTOM"]["aliases"])): index = role_names.index( states["CUSTOM"]["aliases"][0].lower()) role = ctx.guild.get_role(role_ids[index]) await ctx.author.remove_roles( role, reason="Remove state role for bird list") logger.info("synced roles")
async def channel_setup(ctx): """Sets up a new discord channel. `ctx` - Discord context object """ logger.info("checking channel setup") if database.exists(f"channel:{ctx.channel.id}"): logger.info("channel data ok") else: database.hmset( f"channel:{ctx.channel.id}", { "bird": "", "answered": 1, "sBird": "", "sAnswered": 1, "goatsucker": "", "gsAnswered": 1, "prevJ": 20, "prevB": "", "prevS": "", "prevK": 20 }) # true = 1, false = 0, index 0 is last arg, prevJ is 20 to define as integer logger.info("channel data added") await ctx.send("Ok, setup! I'm all ready to use!") if database.zscore("score:global", str(ctx.channel.id)) is not None: logger.info("channel score ok") else: database.zadd("score:global", {str(ctx.channel.id): 0}) logger.info("channel score added")
async def channel_setup(ctx): """Sets up a new discord channel. `ctx` - Discord context object """ logger.info("checking channel setup") if database.exists(f"channel:{ctx.channel.id}"): logger.info("channel data ok") else: database.hset( f"channel:{ctx.channel.id}", mapping={"bird": "", "answered": 1, "prevB": "", "prevJ": 20}, ) # true = 1, false = 0, index 0 is last arg, prevJ is 20 to define as integer logger.info("channel data added") await ctx.send("Ok, setup! I'm all ready to use!") if database.zscore("score:global", str(ctx.channel.id)) is not None: logger.info("channel score ok") else: database.zadd("score:global", {str(ctx.channel.id): 0}) logger.info("channel score added") if ctx.guild is not None: if ( database.zadd("channels:global", {f"{ctx.guild.id}:{ctx.channel.id}": 0}) != 0 ): logger.info("server lookup ok") else: logger.info("server lookup added")
async def _send_stats(self, ctx, preamble): placings = 5 database_key = f"race.scores:{ctx.channel.id}" if database.zcard(database_key) == 0: logger.info(f"no users in {database_key}") await ctx.send("There are no users in the database.") return if placings > database.zcard(database_key): placings = database.zcard(database_key) leaderboard_list = database.zrevrangebyscore( database_key, "+inf", "-inf", 0, placings, True ) embed = discord.Embed( type="rich", colour=discord.Color.blurple(), title=preamble ) embed.set_author(name="Bird ID - An Ornithology Bot") leaderboard = "" for i, stats in enumerate(leaderboard_list): if ctx.guild is not None: user = await fetch_get_user(int(stats[0]), ctx=ctx, member=True) else: user = None if user is None: user = await fetch_get_user(int(stats[0]), ctx=ctx, member=False) if user is None: user_info = "**Deleted**" else: user_info = f"**{esc(user.name)}#{user.discriminator}**" else: user_info = f"**{esc(user.name)}#{user.discriminator}** ({user.mention})" leaderboard += f"{i+1}. {user_info} - {int(stats[1])}\n" start = int(database.hget(f"race.data:{ctx.channel.id}", "start")) elapsed = str(datetime.timedelta(seconds=round(time.time()) - start)) embed.add_field( name="Options", value=await self._get_options(ctx), inline=False ) embed.add_field( name="Stats", value=f"**Race Duration:** `{elapsed}`", inline=False ) embed.add_field(name="Leaderboard", value=leaderboard, inline=False) if ctx.author: if database.zscore(database_key, str(ctx.author.id)) is not None: placement = int(database.zrevrank(database_key, str(ctx.author.id))) + 1 embed.add_field( name="You:", value=f"You are #{placement}.", inline=False ) else: embed.add_field( name="You:", value="You haven't answered any correctly." ) await ctx.send(embed=embed)
def user_banned(ctx): """Disallows users that are banned from the bot.""" logger.info("global check: checking banned") if database.zscore("banned:global", str(ctx.author.id)) is None: return True else: raise GenericError(code=842)
async def ignore(self, ctx, channels: commands.Greedy[discord.TextChannel] = None): logger.info("command: invite") added = "" removed = "" if channels is not None: logger.info(f"ignored channels: {[c.name for c in channels]}") for channel in channels: if database.zscore("ignore:global", str(channel.id)) is None: added += f"`#{channel.name}` (`{channel.category.name if channel.category else 'No Category'}`)\n" database.zadd("ignore:global", {str(channel.id): ctx.guild.id}) else: removed += f"`#{channel.name}` (`{channel.category.name if channel.category else 'No Category'}`)\n" database.zrem("ignore:global", str(channel.id)) else: await ctx.send("**No valid channels were passed.**") ignored = "".join([ f"`#{channel.name}` (`{channel.category.name if channel.category else 'No Category'}`)\n" for channel in map( lambda c: ctx.guild.get_channel(int(c)), database.zrangebyscore("ignore:global", ctx.guild.id - 0.1, ctx.guild.id + 0.1), ) ]) await ctx.send( (f"**Ignoring:**\n{added}" if added else "") + (f"**Stopped ignoring:**\n{removed}" if removed else "") + (f"**Ignored Channels:**\n{ignored}" if ignored else "**No channels in this server are currently ignored.**"))
async def bird_setup(ctx, bird: str): """Sets up a new bird for incorrect tracking. `ctx` - Discord context object `bird` - bird to setup """ logger.info("checking bird data") if database.zscore("incorrect:global", string.capwords(bird)) is not None: logger.info("bird global ok") else: database.zadd("incorrect:global", {string.capwords(bird): 0}) logger.info("bird global added") if database.zscore(f"incorrect.user:{ctx.author.id}", string.capwords(bird)) is not None: logger.info("bird user ok") else: database.zadd(f"incorrect.user:{ctx.author.id}", {string.capwords(bird): 0}) logger.info("bird user added") if ctx.guild is not None: logger.info("no dm") if database.zscore(f"incorrect.server:{ctx.guild.id}", string.capwords(bird)) is not None: logger.info("bird server ok") else: database.zadd(f"incorrect.server:{ctx.guild.id}", {string.capwords(bird): 0}) logger.info("bird server added") else: logger.info("dm context") if database.exists(f"session.data:{ctx.author.id}"): logger.info("session in session") if database.zscore(f"session.incorrect:{ctx.author.id}", string.capwords(bird)) is not None: logger.info("bird session ok") else: database.zadd(f"session.incorrect:{ctx.author.id}", {string.capwords(bird): 0}) logger.info("bird session added") else: logger.info("no session")
async def streak(self, ctx): if ctx.invoked_subcommand is not None: return logger.info("command: streak") args = " ".join(ctx.message.content.split(" ")[1:]) if args: user = await commands.MemberConverter().convert(ctx, args) else: user = None if user is not None: if isinstance(user, str): await ctx.send("Not a user!") return usera = user.id logger.info(usera) streak = database.zscore("streak:global", str(usera)) max_streak = database.zscore("streak.max:global", str(usera)) if streak is not None and max_streak is not None: streak = int(streak) max_streak = int(max_streak) user = f"<@{usera}>" else: await ctx.send("This user does not exist on our records!") return else: user = f"<@{ctx.author.id}>" streak = int(database.zscore("streak:global", str(ctx.author.id))) max_streak = int( database.zscore("streak.max:global", str(ctx.author.id))) embed = discord.Embed(type="rich", colour=discord.Color.blurple(), title="**User Streaks**") embed.set_author(name="Bird ID - An Ornithology Bot") current_streak = f"{user} has answered `{streak}` in a row!" max_streak = f"{user}'s max was `{max_streak}` in a row!" embed.add_field(name="**Current Streak**", value=current_streak, inline=False) embed.add_field(name="**Max Streak**", value=max_streak, inline=False) await ctx.send(embed=embed)
async def prechecks(ctx): await ctx.trigger_typing() logger.info("global check: checking permissions") await commands.bot_has_permissions(send_messages=True, embed_links=True, attach_files=True).predicate(ctx) logger.info("global check: checking banned") if database.zscore("ignore:global", str(ctx.channel.id)) is not None: raise GenericError(code=192) if database.zscore("banned:global", str(ctx.author.id)) is not None: raise GenericError(code=842) logger.info("global check: logging command frequency") database.zincrby("frequency.command:global", 1, str(ctx.command)) logger.info("global check: database setup") await channel_setup(ctx) await user_setup(ctx) return True
def streak_increment(ctx, amount: int): """Increments the streak of a user by `amount`. `ctx` - Discord context object or user id\n `amount` (int) - amount to increment by, usually 1. If amount is None, the streak is ended. """ if isinstance(ctx, (str, int)): user_id = str(ctx) else: user_id = str(ctx.author.id) if amount is not None: # increment streak and update max database.zincrby("streak:global", amount, user_id) if database.zscore("streak:global", user_id) > database.zscore( "streak.max:global", user_id): database.zadd( "streak.max:global", {user_id: database.zscore("streak:global", user_id)}, ) else: database.zadd("streak:global", {user_id: 0})
async def score(self, ctx, scope=""): logger.info("command: score") if scope in ("server", "s"): total_correct = self._server_total(ctx) await ctx.send( f"Wow, looks like a total of `{total_correct}` birds have been answered correctly in this **server**!\n" + "Good job everyone!") else: total_correct = int( database.zscore("score:global", str(ctx.channel.id))) await ctx.send( f"Wow, looks like a total of `{total_correct}` birds have been answered correctly in this **channel**!\n" + "Good job everyone!")
async def user_setup(ctx): """Sets up a new discord user for score tracking. `ctx` - Discord context object """ logger.info("checking user data") if database.zscore("users:global", str(ctx.author.id)) is not None: logger.info("user global ok") else: database.zadd("users:global", {str(ctx.author.id): 0}) logger.info("user global added") await ctx.send("Welcome <@" + str(ctx.author.id) + ">!") #Add streak if (database.zscore("streak:global", str(ctx.author.id)) is not None) and (database.zscore("streak.max:global", str(ctx.author.id)) is not None): logger.info("user streak in already") else: database.zadd("streak:global", {str(ctx.author.id): 0}) database.zadd("streak.max:global", {str(ctx.author.id): 0}) logger.info("added streak") if ctx.guild is not None: logger.info("no dm") if database.zscore(f"users.server:{ctx.guild.id}", str(ctx.author.id)) is not None: server_score = database.zscore(f"users.server:{ctx.guild.id}", str(ctx.author.id)) global_score = database.zscore("users:global", str(ctx.author.id)) if server_score is global_score: logger.info("user server ok") else: database.zadd(f"users.server:{ctx.guild.id}", {str(ctx.author.id): global_score}) else: score = int(database.zscore("users:global", str(ctx.author.id))) database.zadd(f"users.server:{ctx.guild.id}", {str(ctx.author.id): score}) logger.info("user server added") else: logger.info("dm context")
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)
async def checkgoat(self, ctx, *, arg): logger.info("command: checkgoat") await channel_setup(ctx) await user_setup(ctx) currentBird = database.hget(f"channel:{ctx.channel.id}", "goatsucker").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 await bird_setup(ctx, currentBird) index = goatsuckers.index(currentBird) sciBird = sciGoat[index] database.hset(f"channel:{ctx.channel.id}", "gsAnswered", "1") database.hset(f"channel:{ctx.channel.id}", "goatsucker", "") if spellcheck(arg, currentBird) or spellcheck(arg, sciBird): logger.info("correct") if database.exists(f"session.data:{ctx.author.id}"): logger.info("session active") session_increment(ctx, "correct", 1) # increment streak and update max database.zincrby("streak:global", 1, str(ctx.author.id)) 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!") url = get_wiki_url(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")) 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) await ctx.send("Sorry, the bird was actually " + currentBird.lower() + ".") url = get_wiki_url(currentBird) await ctx.send(url) logger.info("currentBird: " + str(currentBird.lower().replace("-", " "))) logger.info("args: " + str(arg.lower().replace("-", " ")))
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)
async def user_lb(self, ctx, title, page, database_key=None, data=None): if database_key is None and data is None: raise GenericError("database_key and data are both NoneType", 990) if database_key is not None and data is not None: raise GenericError("database_key and data are both set", 990) if page < 1: page = 1 user_amount = ( int(database.zcard(database_key)) if database_key is not None else data.count() ) page = (page * 10) - 10 if user_amount == 0: logger.info(f"no users in {database_key}") await ctx.send("There are no users in the database.") return if page >= user_amount: page = user_amount - (user_amount % 10 if user_amount % 10 != 0 else 10) users_per_page = 10 leaderboard_list = ( database.zrevrangebyscore( database_key, "+inf", "-inf", page, users_per_page, True ) if database_key is not None else data.iloc[page : page + users_per_page - 1].items() ) embed = discord.Embed(type="rich", colour=discord.Color.blurple()) embed.set_author(name="Bird ID - An Ornithology Bot") leaderboard = "" for i, stats in enumerate(leaderboard_list): if ctx.guild is not None: user = ctx.guild.get_member(int(stats[0])) else: user = None if user is None: user = self.bot.get_user(int(stats[0])) if user is None: user = "******" else: user = f"**{user.name}#{user.discriminator}**" else: user = f"**{user.name}#{user.discriminator}** ({user.mention})" leaderboard += f"{i+1+page}. {user} - {int(stats[1])}\n" embed.add_field(name=title, value=leaderboard, inline=False) user_score = ( database.zscore(database_key, str(ctx.author.id)) if database_key is not None else data.get(str(ctx.author.id)) ) if user_score is not None: if database_key is not None: placement = int(database.zrevrank(database_key, str(ctx.author.id))) + 1 distance = int( database.zrevrange( database_key, placement - 2, placement - 2, True )[0][1] ) - int(user_score) else: placement = int(data.rank(ascending=False)[str(ctx.author.id)]) distance = int(data.iloc[placement - 2] - user_score) if placement == 1: embed.add_field( name="You:", value=f"You are #{placement} on the leaderboard.\nYou are in first place.", inline=False, ) elif distance == 0: embed.add_field( name="You:", value=f"You are #{placement} on the leaderboard.\nYou are tied with #{placement-1}", inline=False, ) else: embed.add_field( name="You:", value=f"You are #{placement} on the leaderboard.\nYou are {distance} away from #{placement-1}", inline=False, ) else: embed.add_field(name="You:", value="You haven't answered any correctly.") await ctx.send(embed=embed)
def bird_setup(ctx, bird: str): """Sets up a new bird for incorrect tracking. `ctx` - Discord context object or user id\n `bird` - bird to setup """ if isinstance(ctx, (str, int)): user_id = ctx guild = None else: user_id = ctx.author.id guild = ctx.guild logger.info("checking bird data") if database.zscore("incorrect:global", string.capwords(bird)) is not None: logger.info("bird global ok") else: database.zadd("incorrect:global", {string.capwords(bird): 0}) logger.info("bird global added") if database.zscore(f"incorrect.user:{user_id}", string.capwords(bird)) is not None: logger.info("bird user ok") else: database.zadd(f"incorrect.user:{user_id}", {string.capwords(bird): 0}) logger.info("bird user added") date = str(datetime.datetime.now(datetime.timezone.utc).date()) if database.zscore(f"daily.incorrect:{date}", string.capwords(bird)) is not None: logger.info("bird daily ok") else: database.zadd(f"daily.incorrect:{date}", {string.capwords(bird): 0}) logger.info("bird daily added") if database.zscore("frequency.bird:global", string.capwords(bird)) is not None: logger.info("bird freq global ok") else: database.zadd("frequency.bird:global", {string.capwords(bird): 0}) logger.info("bird freq global added") if guild is not None: logger.info("no dm") if ( database.zscore(f"incorrect.server:{ctx.guild.id}", string.capwords(bird)) is not None ): logger.info("bird server ok") else: database.zadd( f"incorrect.server:{ctx.guild.id}", {string.capwords(bird): 0} ) logger.info("bird server added") else: logger.info("dm context") if database.exists(f"session.data:{user_id}"): logger.info("session in session") if ( database.zscore(f"session.incorrect:{user_id}", string.capwords(bird)) is not None ): logger.info("bird session ok") else: database.zadd(f"session.incorrect:{user_id}", {string.capwords(bird): 0}) logger.info("bird session added") else: logger.info("no session")