async def get_bird( request: Request, media: str = "images", addon: str = "", bw: int = 0, ): logger.info("endpoint: get bird") session_id = get_session_id(request) media_type = media filters = Filter.parse(addon) if bool(bw): filters.bw = True logger.info(f"args: media: {media_type}; filters: {filters};") logger.info( "bird: " + database.hget(f"web.session:{session_id}", "bird").decode("utf-8")) # tempScore = int(database.hget(f"web.session:{session_id}", "tempScore")) # if tempScore >= 10: # logger.info("trial maxed") # raise HTTPException(status_code=403, detail="Sign in to continue") if media_type not in ("images", "songs"): logger.error(f"invalid media type {media_type}") raise HTTPException(status_code=422, detail="Invalid media type") answered = int(database.hget(f"web.session:{session_id}", "answered")) logger.info(f"answered: {answered}") # check to see if previous bird was answered if answered: # if yes, give a new bird id_list = songBirds if media_type == "songs" else birdList currentBird = random.choice(id_list) user_id = int(database.hget(f"web.session:{session_id}", "user_id")) if user_id != 0: increment_bird_frequency(currentBird, user_id) prevB = database.hget(f"web.session:{session_id}", "prevB").decode("utf-8") while currentBird == prevB and len(id_list) > 1: currentBird = random.choice(id_list) database.hset(f"web.session:{session_id}", "prevB", str(currentBird)) database.hset(f"web.session:{session_id}", "bird", str(currentBird)) logger.info("currentBird: " + str(currentBird)) database.hset(f"web.session:{session_id}", "answered", "0") file_object, ext, content_type = await send_bird( request, currentBird, media_type, filters) else: # if no, give the same bird file_object, ext, content_type = await send_bird( request, database.hget(f"web.session:{session_id}", "bird").decode("utf-8"), media_type, filters, ) logger.info(f"file_object: {file_object}") logger.info(f"extension: {ext}") return send_file(file_object, media_type=content_type)
def get_bird(): logger.info("endpoint: get bird") session_id = get_session_id() media_type = flask.request.args.get("media", "images", str) filters = Filter.parse(flask.request.args.get("addon", "", str)) if bool(flask.request.args.get("bw", 0, int)): filters.bw = True logger.info(f"args: media: {media_type}; filters: {filters};") logger.info( "bird: " + database.hget(f"web.session:{session_id}", "bird").decode("utf-8") ) tempScore = int(database.hget(f"web.session:{session_id}", "tempScore")) if tempScore >= 10: logger.info("trial maxed") flask.abort(403, "Sign in to continue") if media_type not in ("images", "songs"): logger.error(f"invalid media type {media_type}") flask.abort(406, "Invalid media type") answered = int(database.hget(f"web.session:{session_id}", "answered")) logger.info(f"answered: {answered}") # check to see if previous bird was answered if answered: # if yes, give a new bird id_list = songBirds if media_type == "songs" else birdList currentBird = random.choice(id_list) user_id = int(database.hget(f"web.session:{session_id}", "user_id")) if user_id != 0: session_increment(user_id, "total", 1) increment_bird_frequency(currentBird, user_id) prevB = database.hget(f"web.session:{session_id}", "prevB").decode("utf-8") while currentBird == prevB and len(id_list) > 1: currentBird = random.choice(id_list) database.hset(f"web.session:{session_id}", "prevB", str(currentBird)) database.hset(f"web.session:{session_id}", "bird", str(currentBird)) database.hset(f"web.session:{session_id}", "media_type", str(media_type)) logger.info("currentBird: " + str(currentBird)) database.hset(f"web.session:{session_id}", "answered", "0") file_object, ext = asyncio.run(send_bird(currentBird, media_type, filters)) else: # if no, give the same bird file_object, ext = asyncio.run( send_bird( database.hget(f"web.session:{session_id}", "bird").decode("utf-8"), database.hget(f"web.session:{session_id}", "media_type").decode( "utf-8" ), filters, ) ) logger.info(f"file_object: {file_object}") logger.info(f"extension: {ext}") return flask.send_file(file_object, attachment_filename=f"bird.{ext}")
async def info(self, ctx, *, arg): logger.info("command: info") arg = arg.lower().strip() filters = Filter.parse(arg) if filters.vc: filters.vc = False await ctx.send("**The VC filter is not allowed here!**") options = filters.display() arg = arg.split(" ") bird = None if len(arg[0]) == 4: bird = alpha_codes.get(arg[0].upper()) if not bird: for i in reversed(range(1, 6)): # try the first 5 words, then first 4, etc. looking for a match matches = get_close_matches( string.capwords(" ".join(arg[:i]).replace("-", " ")), birdListMaster + sciListMaster, n=1, cutoff=0.8, ) if matches: bird = matches[0] break if not bird: await ctx.send("Bird not found. Are you sure it's on the list?") return delete = await ctx.send("Please wait a moment.") if options: await ctx.send(f"**Detected filters**: `{'`, `'.join(options)}`") an = "an" if bird.lower()[0] in ("a", "e", "i", "o", "u") else "a" await send_bird(ctx, bird, "images", filters, message=f"Here's {an} *{bird.lower()}* image!") await send_bird(ctx, bird, "songs", filters, message=f"Here's {an} *{bird.lower()}* song!") await delete.delete() return
async def info(self, ctx, *, arg): logger.info("command: info") arg = arg.lower().strip() filters = Filter.parse(arg) options = filters.display() arg = arg.split(" ") bird = None if len(arg[0]) == 4: bird = alpha_codes.get(arg[0].upper()) if not bird: for i in reversed(range(1, 6)): # try the first 6 words, then first 5, etc. looking for a match matches = get_close_matches(" ".join(arg[:i]), birdListMaster + sciListMaster, n=1) if matches: bird = matches[0] break if not bird: await ctx.send("Bird not found. Are you sure it's on the list?") return delete = await ctx.send("Please wait a moment.") if options: await ctx.send(f"**Detected filters**: `{'`, `'.join(options)}`") await send_bird(ctx, bird, "images", filters, message=f"Here's a *{bird.lower()}* image!") await send_bird(ctx, bird, "songs", filters, message=f"Here's a *{bird.lower()}* song!") await delete.delete() return
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 )
async def parse(ctx, args_str: str): """Parse arguments for options.""" args = args_str.split(" ") logger.info(f"args: {args}") if not database.exists(f"race.data:{ctx.channel.id}"): roles = check_state_role(ctx) taxon_args = set(taxons.keys()).intersection( {arg.lower() for arg in args}) if taxon_args: taxon = " ".join(taxon_args).strip() else: taxon = "" state_args = set(states.keys()).intersection( {arg.upper() for arg in args}) if state_args: state = " ".join(state_args).strip() else: state = "" if database.exists(f"session.data:{ctx.author.id}"): logger.info("session parameters") if taxon_args: current_taxons = set( database.hget(f"session.data:{ctx.author.id}", "taxon").decode("utf-8").split(" ")) logger.info(f"toggle taxons: {taxon_args}") logger.info(f"current taxons: {current_taxons}") taxon_args.symmetric_difference_update(current_taxons) taxon_args.discard("") logger.info(f"new taxons: {taxon_args}") taxon = " ".join(taxon_args).strip() else: taxon = database.hget(f"session.data:{ctx.author.id}", "taxon").decode("utf-8") roles = (database.hget(f"session.data:{ctx.author.id}", "state").decode("utf-8").split(" ")) if roles[0] == "": roles = [] if not roles: logger.info("no session lists") roles = check_state_role(ctx) session_filter = int( database.hget(f"session.data:{ctx.author.id}", "filter")) filters = Filter.parse(args_str, defaults=False) if filters.vc: filters.vc = False await ctx.send("**The VC filter is not allowed inline!**") default_quality = Filter().quality if (Filter.from_int(session_filter).quality == default_quality and filters.quality and filters.quality != default_quality): filters ^= Filter() # clear defaults filters ^= session_filter else: filters = Filter.parse(args_str) if filters.vc: filters.vc = False await ctx.send("**The VC filter is not allowed inline!**") if state_args: logger.info(f"toggle states: {state_args}") logger.info(f"current states: {roles}") state_args.symmetric_difference_update(set(roles)) state_args.discard("") logger.info(f"new states: {state_args}") state = " ".join(state_args).strip() else: state = " ".join(roles).strip() if "CUSTOM" in state.upper().split(" "): if not database.exists(f"custom.list:{ctx.author.id}"): await ctx.send("**You don't have a custom list set!**") state_list = state.split(" ") state_list.remove("CUSTOM") state = " ".join(state_list) elif database.exists(f"custom.confirm:{ctx.author.id}"): await ctx.send( "**Please verify or confirm your custom list before using!**" ) state_list = state.split(" ") state_list.remove("CUSTOM") state = " ".join(state_list) else: logger.info("race parameters") race_filter = int( database.hget(f"race.data:{ctx.channel.id}", "filter")) filters = Filter.parse(args_str, defaults=False) if filters.vc: filters.vc = False await ctx.send("**The VC filter is not allowed inline!**") default_quality = Filter().quality if (Filter.from_int(race_filter).quality == default_quality and filters.quality and filters.quality != default_quality): filters ^= Filter() # clear defaults filters ^= race_filter taxon = database.hget(f"race.data:{ctx.channel.id}", "taxon").decode("utf-8") state = database.hget(f"race.data:{ctx.channel.id}", "state").decode("utf-8") logger.info( f"args: filters: {filters}; taxon: {taxon}; state: {state}") return (filters, taxon, state)
async def edit(self, ctx, *, args_str: str = ""): logger.info("command: view session") if database.exists(f"session.data:{ctx.author.id}"): new_filter = Filter.parse(args_str, defaults=False) args = args_str.lower().split(" ") logger.info(f"args: {args}") new_filter ^= int( database.hget(f"session.data:{ctx.author.id}", "filter")) database.hset(f"session.data:{ctx.author.id}", "filter", str(new_filter.to_int())) if "wiki" in args: if database.hget(f"session.data:{ctx.author.id}", "wiki"): logger.info("enabling wiki embeds") database.hset(f"session.data:{ctx.author.id}", "wiki", "") else: logger.info("disabling wiki embeds") database.hset(f"session.data:{ctx.author.id}", "wiki", "wiki") if "strict" in args: if database.hget(f"session.data:{ctx.author.id}", "strict"): logger.info("disabling strict spelling") database.hset(f"session.data:{ctx.author.id}", "strict", "") else: logger.info("enabling strict spelling") database.hset(f"session.data:{ctx.author.id}", "strict", "strict") states_args = set(states.keys()).intersection( {arg.upper() for arg in args}) if states_args: current_states = set( database.hget(f"session.data:{ctx.author.id}", "state").decode("utf-8").split(" ")) logger.info(f"toggle states: {states_args}") logger.info(f"current states: {current_states}") states_args.symmetric_difference_update(current_states) logger.info(f"new states: {states_args}") database.hset( f"session.data:{ctx.author.id}", "state", " ".join(states_args).strip(), ) taxon_args = set(taxons.keys()).intersection( {arg.lower() for arg in args}) if taxon_args: current_taxons = set( database.hget(f"session.data:{ctx.author.id}", "taxon").decode("utf-8").split(" ")) logger.info(f"toggle taxons: {taxon_args}") logger.info(f"current taxons: {current_taxons}") taxon_args.symmetric_difference_update(current_taxons) logger.info(f"new taxons: {taxon_args}") database.hset( f"session.data:{ctx.author.id}", "taxon", " ".join(taxon_args).strip(), ) await self._send_stats(ctx, "**Session started previously.**\n") else: await ctx.send( "**There is no session running.** *You can start one with `b!session start`*" )
async def start(self, ctx, *, args_str: str = ""): logger.info("command: start session") if database.exists(f"session.data:{ctx.author.id}"): logger.info("already session") await ctx.send( "**There is already a session running.** *Change settings/view stats with `b!session edit`*" ) return filters = Filter.parse(args_str) args = args_str.lower().split(" ") logger.info(f"args: {args}") if "wiki" in args: wiki = "" else: wiki = "wiki" if "strict" in args: strict = "strict" else: strict = "" 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)) taxon_args = set(taxons.keys()).intersection( {arg.lower() for arg in args}) if taxon_args: taxon = " ".join(taxon_args).strip() else: taxon = "" logger.info( f"adding filters: {filters}; state: {state}; wiki: {wiki}; strict: {strict}" ) database.hset( f"session.data:{ctx.author.id}", mapping={ "start": round(time.time()), "stop": 0, "correct": 0, "incorrect": 0, "total": 0, "filter": str(filters.to_int()), "state": state, "taxon": taxon, "wiki": wiki, "strict": strict, }, ) await ctx.send( f"**Session started with options:**\n{await self._get_options(ctx)}" )
def parse(ctx, args_str: str): """Parse arguments for options.""" args = args_str.split(" ") logger.info(f"args: {args}") if not database.exists(f"race.data:{ctx.channel.id}"): roles = check_state_role(ctx) taxon_args = set(taxons.keys()).intersection( {arg.lower() for arg in args}) if taxon_args: taxon = " ".join(taxon_args).strip() else: taxon = "" state_args = set(states.keys()).intersection( {arg.upper() for arg in args}) if state_args: state = " ".join(state_args).strip() else: state = "" if database.exists(f"session.data:{ctx.author.id}"): logger.info("session parameters") if taxon_args: current_taxons = set( database.hget(f"session.data:{ctx.author.id}", "taxon").decode("utf-8").split(" ")) logger.info(f"toggle taxons: {taxon_args}") logger.info(f"current taxons: {current_taxons}") taxon_args.symmetric_difference_update(current_taxons) logger.info(f"new taxons: {taxon_args}") taxon = " ".join(taxon_args).strip() else: taxon = database.hget(f"session.data:{ctx.author.id}", "taxon").decode("utf-8") roles = (database.hget(f"session.data:{ctx.author.id}", "state").decode("utf-8").split(" ")) if roles[0] == "": roles = [] if not roles: logger.info("no session lists") roles = check_state_role(ctx) session_filter = int( database.hget(f"session.data:{ctx.author.id}", "filter")) filters = Filter.parse(args_str, defaults=False) default_quality = Filter().quality if (Filter.from_int(session_filter).quality == default_quality and filters.quality and filters.quality != default_quality): filters ^= Filter() # clear defaults filters ^= session_filter else: filters = Filter.parse(args_str) if state_args: logger.info(f"toggle states: {state_args}") logger.info(f"current states: {roles}") state_args.symmetric_difference_update(set(roles)) logger.info(f"new states: {state_args}") state = " ".join(state_args).strip() else: state = " ".join(roles).strip() else: logger.info("race parameters") race_filter = int( database.hget(f"race.data:{ctx.channel.id}", "filter")) filters = Filter.parse(args_str, defaults=False) default_quality = Filter().quality if (Filter.from_int(race_filter).quality == default_quality and filters.quality and filters.quality != default_quality): filters ^= Filter() # clear defaults filters ^= race_filter taxon = database.hget(f"race.data:{ctx.channel.id}", "taxon").decode("utf-8") state = database.hget(f"race.data:{ctx.channel.id}", "state").decode("utf-8") logger.info( f"args: filters: {filters}; taxon: {taxon}; state: {state}") return (filters, taxon, state)