async def _urbandictionary(self, ctx: SlashContext, *, word: str): r = requests.get(f"http://www.urbandictionary.com/define.php?term={word}") soup = BeautifulSoup(r.content, features="html.parser") try: definitions = soup.find_all(name="div", attrs={"class": "def-panel"}) except AttributeError: raise UserError(f"Unable to find [{word}] in the Urban Dictionary.") del r, soup if len(definitions) == 0: raise UserError(f"Unable to find [{word}] in the Urban Dictionary.") try: del definitions[1] # Word of the day except IndexError: pass results = [] for definition in definitions: results.append( self.Definition( lookup_word=definition.contents[1].contents[0].text, meaning=definition.contents[2].text, example=definition.contents[3].text, contributor=definition.contents[4].text, ) ) pages = [] for index, result in enumerate(results): pages.append( build_embed( title=f"Searched for: {result.lookup_word}", description=f"Definition #{index + 1} from Urban Dictionary", fields=[ ["Meaning", result.meaning], ["Example", result.example], ["Contributor", result.contributor], ], ) ) await Paginator( bot=ctx.bot, ctx=ctx, pages=pages, useIndexButton=True, useSelect=False, firstStyle=ButtonStyle.gray, nextStyle=ButtonStyle.gray, prevStyle=ButtonStyle.gray, lastStyle=ButtonStyle.gray, indexStyle=ButtonStyle.gray, ).run()
async def _crootbot(self, ctx: SlashContext, year: int, search_name: str): print(f"[{datetime.datetime.now().astimezone(tz=TZ)}] ### Crootbot") if len(search_name) == 0: raise UserError("A player's first and/or last search_name is required.") if len(str(year)) == 2: year += 2000 elif len(str(year)) == 1 or len(str(year)) == 3: raise UserError("The search year must be two or four digits long.") if year > datetime.datetime.now().year + 5: raise UserError( "The search year must be within five years of the current class." ) if year < 1869: raise UserError( "The search year must be after the first season of college football--1869." ) await ctx.defer() # Similar to sending a message with a loading screen to edit later on log(f"Searching for [{year} {search_name.capitalize()}]", 1) global croot_search croot_search = FootballRecruit(year, search_name) log(f"Found [{len(croot_search)}] results", 1) if len(croot_search) == 1: return await final_send_embed_fap_loop( ctx=ctx, target_recruit=croot_search[0], bot=self.bot ) result_info = search_result_info(croot_search) action_row = create_actionrow(*search_buttons) embed = build_embed( title=f"Search Results for [{year} {search_name.capitalize()}]", fields=[["Search Results", result_info]], ) await ctx.send(embed=embed, components=[action_row]) log(f"Sent search results for [{year} {search_name.capitalize()}]", 1)
async def _fap_predict(self, ctx: SlashContext, year: int, search_name: str): if len(str(year)) == 2: year += 2000 if year > datetime.datetime.now().year + 5: raise UserError( "The search year must be within five years of the current class." ) if year < 1869: raise UserError( "The search year must be after the first season of college football--1869." ) await ctx.defer(hidden=True) global fap_search fap_search = FootballRecruit(year, search_name) if type(fap_search) == commands.UserInputError: return await ctx.send(content=fap_search, hidden=True) async def send_fap_convo(target_recruit): await initiate_fap( ctx=ctx, user=ctx.author, recruit=target_recruit, client=ctx.bot ) if len(fap_search) == 1: return await send_fap_convo(fap_search[0]) result_info = search_result_info(fap_search) action_row = create_actionrow(*search_buttons) embed = build_embed( title=f"Search Results for [{year} {search_name.capitalize()}]", fields=[["Search Results", result_info]], ) await ctx.send(embed=embed, components=[action_row], hidden=True)
async def _vote( self, ctx: SlashContext, query: str, option_a: str = "UP VOTE", option_b: str = "DOWN VOTE", ): if (option_a is not None and option_b is None) or ( option_b is not None and option_a is None ): raise UserError("You must provide both options!") option_a = str(option_a).upper() option_b = str(option_b).upper() but_a = ButtonStyle.green but_b = ButtonStyle.red key = set_component_key() buttons_voting = [] query = query.capitalize() if not query.endswith("?"): query += "?" if option_a != "UP VOTE" and option_b != "DOWN VOTE": # Non-standard vote but_a = but_b = ButtonStyle.gray buttons_voting.append( create_button(custom_id=f"{key}_a", label=option_a, style=but_a) ) buttons_voting.append( create_button(custom_id=f"{key}_b", label=option_b, style=but_b) ) embed = build_embed( title=f"Q: {query}", inline=False, fields=[ [buttons_voting[-2]["label"], "0"], [buttons_voting[-1]["label"], "0"], ["Voters", "_"], ], footer=key, ) await ctx.send( content="", embed=embed, components=[create_actionrow(*buttons_voting)] )
async def _possumdroppings(self, ctx: SlashContext, message: str): await ctx.defer() if not ctx.channel_id == CHAN_POSSUMS: raise UserError( f"You can only use this command in [{ctx.guild.get_channel(CHAN_POSSUMS).mention}]" ) await ctx.send("Thinking...", delete_after=0) embed = build_embed( title="Possum Droppings", inline=False, thumbnail="https://cdn.discordapp.com/attachments/593984711706279937/875162041818693632/unknown.jpeg", footer="Created by a possum", fields=[["Droppings", message]], ) await ctx.send(embed=embed)
async def _weather( self, ctx: SlashContext, city: str, state: str, country: str = "US" ): def shift_utc_tz(dt, shift): return dt + timedelta(seconds=shift) if not len(state) == 2: raise UserError("State input must be the two-digit state code.") found = False for item in US_STATES: if item.get("Code") == state.upper(): found = True break if not found: raise UserError( f"Unable to find the state {state.upper()}. Please try again!" ) weather_url = f"https://api.openweathermap.org/data/2.5/weather?appid={WEATHER_API_KEY}&units=imperial&lang=en&q={city},{state},{country}" response = requests.get(weather_url, headers=HEADERS) j = json.loads(response.content) weather = WeatherResponse(j) if weather.cod == "404": raise UserError( f"Unable to find {city.title()}, {state.upper()}. Try again!" ) temp_str = ( f"Temperature: {weather.main.temp}℉\n" f"Feels Like: {weather.main.feels_like}℉\n" f"Humidity: {weather.main.humidity}%\n" f"Max: {weather.main.temp_max}℉\n" f"Min: {weather.main.temp_min}℉" ) if len(weather.wind) == 2: wind_str = ( f"Speed: {weather.wind.speed} MPH\n" f"Direction: {weather.wind.deg} °" ) elif len(weather.wind) == 3: wind_str = ( f"Speed: {weather.wind.speed} MPH\n" f"Gusts: {weather.wind.gust} MPH\n" f"Direction: {weather.wind.deg} °" ) else: wind_str = f"Speed: {weather.wind.speed} MPH" hourly_url = f"https://api.openweathermap.org/data/2.5/onecall?lat={weather.coord.lat}&lon={weather.coord.lon}&appid={WEATHER_API_KEY}&units=imperial" response = requests.get(hourly_url, headers=HEADERS) j = json.loads(response.content) hours = [] for index, item in enumerate(j["hourly"]): hours.append(WeatherHour(item)) if index == 3: break hour_temp_str = "" hour_wind_str = "" for index, hour in enumerate(hours): if index < len(hours) - 1: hour_temp_str += f"{hour.temp}℉ » " hour_wind_str += f"{hour.wind_speed} MPH » " else: hour_temp_str += f"{hour.temp}℉" hour_wind_str += f"{hour.wind_speed} MPH" sunrise = shift_utc_tz(weather.sys.sunrise, weather.timezone) sunset = shift_utc_tz(weather.sys.sunset, weather.timezone) sun_str = ( f"Sunrise: {sunrise.astimezone(tz=TZ).strftime(DT_OPENWEATHER_UTC)}\n" f"Sunset: {sunset.astimezone(tz=TZ).strftime(DT_OPENWEATHER_UTC)}" ) embed = build_embed( title=f"Weather conditions for {city.title()}, {state.upper()}", description=f"It is currently {weather.weather[0].main} with {weather.weather[0].description}. {city.title()}, {state.upper()} is located at {weather.coord.lat}, {weather.coord.lon}.", fields=[ ["Temperature", temp_str], ["Clouds", f"Coverage: {weather.clouds.all}%"], ["Wind", wind_str], ["Temp Next 4 Hours", hour_temp_str], ["Wind Next 4 Hours", hour_wind_str], ["Sun", sun_str], ], inline=False, thumbnail=f"https://openweathermap.org/img/wn/{weather.weather[0].icon}@4x.png", ) await ctx.send(embed=embed)
def FootballRecruit(year, name): all_team_ids = Process_MySQL(fetch="all", query=sqlTeamIDs) name = name.split(" ") if len(name) == 1: _247_search = f"https://247sports.com/Season/{year}-Football/Recruits.json?&Items=15&Page=1&Player.FirstName={name[0]}" first_name = requests.get(url=_247_search, headers=HEADERS) first_name = json.loads(first_name.text) _247_search = f"https://247sports.com/Season/{year}-Football/Recruits.json?&Items=15&Page=1&Player.LastName={name[0]}" last_name = requests.get(url=_247_search, headers=HEADERS) last_name = json.loads(last_name.text) search_results = first_name + last_name elif len(name) == 2: _247_search = f"https://247sports.com/Season/{year}-Football/Recruits.json?&Items=15&Page=1&Player.FirstName={name[0]}&Player.LastName={name[1]}" search_results = requests.get(url=_247_search, headers=HEADERS) search_results = json.loads(search_results.text) else: raise UserError(f"Error occurred attempting to create 247sports search URL.") if not search_results: raise UserError( f"Unable to find [{name[0] if len(name) <= 1 else name[0] + ' ' + name[1]}] in the [{year}] class. Please try again!" ) search_result_players = [] for index, search_player in enumerate(search_results): cur_player = search_player["Player"] reqs = requests.get(url=search_player["Player"]["Url"], headers=HEADERS) soup = BeautifulSoup(reqs.content, "html.parser") # Put into separate variables for debugging purposes # red_shirt _247_highlights = cur_player.get("Url") + "Videos/" _247_profile = cur_player.get("Url", None) bio = cur_player.get("Bio", None) cb_experts = get_cb_experts(soup, all_team_ids) cb_predictions = get_cb_predictions(soup) city = cur_player["Hometown"].get("City", None) commitment_date = search_player.get("AnnouncementDate", None) committed = reformat_commitment_string(search_player) committed_school = get_committed_school( all_team_ids, get_team_id(search_player) ) early_enrollee = is_early_enrolee(soup) early_signee = is_early_signee(soup) height = reformat_height(cur_player.get("Height", None)) key = cur_player.get("Key", None) name = cur_player.get("FullName", None) position = cur_player["PrimaryPlayerPosition"].get("Abbreviation", None) ranking_all_time = get_all_time_ranking(soup) ranking_national = get_national_ranking(cur_player) ranking_position = get_position_ranking(cur_player) ranking_state = get_state_ranking(cur_player) rating_numerical = reformat_composite_rating(cur_player) rating_stars = cur_player.get("CompositeStarRating", None) recruit_interests = get_recruit_interests(search_player) recruit_interests_url = cur_player.get("RecruitInterestsUrl", None) school = cur_player["PlayerHighSchool"].get("Name", None) school_type = get_school_type(soup) scout_evaluation = cur_player.get("ScoutEvaluation", None) state = cur_player["Hometown"].get("State", None) state_abbr = get_state_abbr(cur_player) team_id = get_team_id(search_player) thumbnail = get_thumbnail(cur_player) twitter = get_twitter_handle(soup) walk_on = get_walk_on(soup) weight = reformat_weight(cur_player.get("Weight", None)) year = search_player.get("Year", None) search_result_players.append( Recruit( _247_highlights=_247_highlights, _247_profile=_247_profile, bio=bio, cb_experts=cb_experts, cb_predictions=cb_predictions, city=city, commitment_date=commitment_date, committed=committed, committed_school=committed_school, early_enrollee=early_enrollee, early_signee=early_signee, height=height, key=key, name=name, position=position, ranking_all_time=ranking_all_time, ranking_national=ranking_national, ranking_position=ranking_position, ranking_state=ranking_state, rating_numerical=rating_numerical, rating_stars=rating_stars, recruit_interests=recruit_interests, recruit_interests_url=recruit_interests_url, # red_shirt=None, school=school, school_type=school_type, scout_evaluation=scout_evaluation, state=state, state_abbr=state_abbr, team_id=team_id, thumbnail=thumbnail, twitter=twitter, walk_on=walk_on, weight=weight, year=year, ) ) if index == CROOT_SEARCH_LIMIT - 1: break return search_result_players
async def _remindme( self, ctx: SlashContext, remind_when: str, message: str, who: discord.member = None, channel: discord.TextChannel = None, ): if who and channel: raise UserError( "You cannot input both a member and channel to remind.") elif who and not ctx.author == who: raise UserError( "You cannot set reminders for anyone other than yourself!") elif channel in CHAN_BANNED: raise ValueError( f"Setting reminders in {channel.mention} is banned!") await ctx.defer() today = datetime.today() def convert_dt_value(dt_item: str, from_when: str): if dt_item in from_when: raw = from_when.split(dt_item)[0] if raw.isnumeric(): return int(raw) else: try: findall = re.findall(r"\D", raw)[-1] return int(raw[raw.find(findall) + 1:]) except: return 0 else: return 0 days = convert_dt_value(DateTimeStrings.day, remind_when) hours = convert_dt_value(DateTimeStrings.hour, remind_when) minutes = convert_dt_value(DateTimeStrings.minute, remind_when) seconds = convert_dt_value(DateTimeStrings.seconds, remind_when) time_diff = timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds) min_timer_allowed = 5 # 60 * 5 if time_diff.total_seconds() < min_timer_allowed: raise UserError( f"The num_seconds entered is too short! The minimum allowed timer is {min_timer_allowed} seconds." ) try: raw_when = today + time_diff except ValueError: raise UserError("The num_seconds entered is too large!") duration = raw_when - today send_when = today + duration mysql_author = f"{ctx.author.name}#{ctx.author.discriminator}" is_open = 1 if who: destination = who elif channel: destination = channel else: destination = ctx.channel try: Process_MySQL( sqlRecordTasks, values=( str(destination.id), message, str(send_when), is_open, mysql_author, ), ) destination = ctx.channel except: raise CommandError("Error submitting MySQL") nest_asyncio.apply() asyncio.create_task( send_reminder( num_seconds=duration.total_seconds(), destination=destination, message=message, source=ctx.author, alert_when=str(send_when), )) embed = build_embed( title="Bot Frost Reminders", description= f"Setting a timer for [{destination.mention}] in [{pretty_time_delta(duration.total_seconds())}]. The timer will go off at [{send_when.strftime('%x %X')}].", inline=False, fields=[["Author", ctx.author.mention], ["Message", message]], ) await ctx.send(embed=embed)