async def send_reminder(thread, duration, who: typing.Union[discord.Member, discord.TextChannel], message, author: typing.Union[discord.Member, discord.TextChannel], flag=None): if exitFlag: thread.exit() print( f"### ;;; Starting [{thread}] thread for [{duration}] seconds. Send_When == [{flag}]." ) if duration > 0: print( f"### ;;; Creating a task for [{duration}] seconds. [{who}] [{message[:15] + '...'}]" ) await asyncio.sleep(duration) await who.send( f"[Reminder from [{author}] for {who}]: {remove_mentions(message)}" ) process_MySQL(sqlUpdateTasks, values=(0, who.id, message, str(flag), author)) else: imported_datetime = datetime.strptime(flag, "%Y-%m-%d %H:%M:%S.%f") await who.send( f"[Missed reminder from [{author}] for [{who}] set for [{imported_datetime.strftime('%x %X')}]!: {remove_mentions(message)}" ) process_MySQL(sqlUpdateTasks, values=(0, who.id, message, str(flag), author)) print(f"### ;;; Thread [{thread}] completed successfully!")
def initiate_user(self, ctx, value): process_MySQL(query=sqlSetCurrency, values=( self.full_author(ctx.message.author), value, ctx.message.author.id, ))
async def nebraska(self, ctx, who: discord.Member): if not who: raise AttributeError("You must include a user!") timeout = ctx.guild.get_role(ROLE_TIME_OUT) await who.remove_roles(timeout) previous_roles_raw = process_MySQL(query=sqlRetrieveIowa, values=who.id, fetch="all") previous_roles = previous_roles_raw[0]["previous_roles"].split(",") try: if previous_roles: for role in previous_roles: new_role = ctx.guild.get_role(int(role)) await who.add_roles(new_role, reason="Returning from Iowa") except discord.Forbidden: pass except discord.HTTPException: pass process_MySQL(query=sqlRemoveIowa, values=who.id) iowa = ctx.guild.get_channel(CHAN_IOWA) await ctx.send(f"[ {who} ] is welcome back to Nebraska.") await iowa.send(f"[ {who.mention} ] has been sent back to Nebraska.")
async def create(self, ctx, keyword: str, *, description: str): """ Create a custom bet (line) for the Discord to place bets against. :param ctx: :param keyword: A single-word identifier for the bet (line). :param description: A detailed description of the bet (line). This should include conditions on "for" and "against" results. :return: """ # Prevent errors keyword = keyword.replace(" ", "").lower() try: # Insert into `custom_lines` database. process_MySQL(query=sqlInsertCustomLines, values=(ctx.message.author.id, keyword, description)) except ConnectionError: # Was not able to insert into `custom_lines` database. raise AttributeError(f"A MySQL query error occurred!") else: # Alert the user that the bet (line) was created. await ctx.send(embed=build_embed( title="Custom Bet", description= f"{ctx.message.author.mention}'s bet was successfully created!", fields=[["Author", ctx.message.author.mention], ["Keyword", keyword], ["Description", description]]))
async def record_statistics(): if not type(message.channel) == discord.DMChannel: author = str(message.author).encode("ascii", "ignore").decode("ascii") chan = f"{message.guild}.#{message.channel.name}".encode( "ascii", "ignore").decode("ascii") process_MySQL(query=sqlRecordStats, values=(author, chan))
async def after_donate(self, ctx): from utils.mysql import process_MySQL, sqlLogUser process_MySQL( query=sqlLogUser, values=( f"{ctx.message.author.name}#{ctx.message.author.discriminator}", "after_donate", "N/A"))
async def genhis(self, ctx): history = [] guild = member = None guild = client.get_guild(id=GUILD_PROD) if guild is None: guild = client.get_guild(id=GUILD_TEST) member = guild.get_member(PROD_BOT_MEMBER) if member is None: member = guild.get_member(TEST_BOT_MEMBER) async def compile_history(chan: discord.TextChannel, limit=9999): history_raw = await chan.history(limit=limit, after=datetime(year=2020, month=5, day=1)).flatten() history_new = [] for entry in history_raw: history_new.append([ str(entry.author).encode("ascii", "ignore").decode("ascii"), str(entry.channel).encode("ascii", "ignore").decode("ascii"), str(entry.created_at.strftime("%Y-%m-%d %H:%M:%S")).encode( "ascii", "ignore").decode("ascii") ]) del history_raw return history_new for channel in guild.channels: perms = channel.permissions_for(member) if not perms.read_message_history: continue if channel.type == discord.ChannelType.text: print(f"Grabbing history for {channel.name}...") history.extend(await compile_history(channel)) print("Done!") else: continue for entry in history: print(repr(entry)) process_MySQL(query=sqlRecordStatsManual, values=entry)
def retrieve_open_custom_lines(self, keyword=None): """ Returns all or one bet (line). :param keyword: :return: """ if keyword is None: return process_MySQL(query=sqlRetrieveAllOpenCustomLines, fetch="all") else: return process_MySQL(query=sqlRetrieveOneOpenCustomLine, values=keyword, fetch="one")
async def insert_prediction(user, recruit, team_prediction, prediction_confidence, previous_prediction): if previous_prediction is None: insert_prediction_query = '''INSERT INTO fap_predictions (user, user_id, recruit_name, recruit_profile, recruit_class, team, confidence, prediction_date) VALUES (%s, %s, %s, %s, %s, %s, %s, NOW());''' process_MySQL(query=insert_prediction_query, values=(user.name, user.id, recruit.name, recruit.x247_profile, recruit.year, team_prediction, prediction_confidence)) else: update_prediction_query = '''UPDATE fap_predictions SET team = %s, confidence = %s, prediction_date = NOW() WHERE user_id = %s and recruit_profile = %s;''' if team_prediction == previous_prediction['team']: update_prediction_query = '''UPDATE fap_predictions SET team = %s, confidence = %s WHERE user_id = %s and recruit_profile = %s;''' process_MySQL(query=update_prediction_query, values=(team_prediction, prediction_confidence, user.id, recruit.x247_profile))
def tally_score(message: discord.Message, author: typing.Union[discord.Member, discord.User], end): """1000 points per second""" if end == 0: process_MySQL(query=sqlInsertTriviaScore, value=(author.display_name, 0, 0)) print(f">>> {author} got a score of 0.") return footer_text = message.embeds[0].footer.text start = datetime.strptime(footer_text.split("|")[0].strip(), "%Y-%m-%d %H:%M:%S.%f") diff = end - start score = diff.total_seconds() score *= 1000 score = (game.timer * 1000) - score print(f">>> {author} got a score of {score}.") process_MySQL(query=sqlInsertTriviaScore, values=(author.display_name, abs(score), abs(score)))
async def individual_predictions(recruit, ctx): get_individual_preds_query = 'SELECT * FROM fap_predictions WHERE recruit_profile = %s ORDER BY prediction_date ASC' individual_preds = process_MySQL(query=get_individual_preds_query, fetch='all', values=(recruit.x247_profile,)) if individual_preds is None: await ctx.send('This recruit has no predictions.') return embed_title = f'Predictions for {recruit.name}' embed = discord.Embed(title=embed_title) for i, p in enumerate(individual_preds): try: pred_user = ctx.guild.get_member(p['user_id']) pred_user = pred_user.display_name except: pred_user = p['user'] if pred_user is None: pred_user = p['user'] # if i > 0: # embed_description += '\n' pred_dt = p['prediction_date'] if isinstance(pred_dt, str): pred_dt = datetime.datetime.strptime(p['prediction_date'], DATETIME_FORMAT) pred_field = [f"{pred_user}", f"{p['team']} ({p['confidence']}) - {pred_dt.month}/{pred_dt.day}/{pred_dt.year}"] if p['correct'] == 1: pred_field[0] = '✅ ' + pred_field[0] elif p['correct'] == 0: pred_field[0] = '❌ ' + pred_field[0] elif p['correct'] is None: pred_field[0] = '⌛ ' + pred_field[0] embed.add_field(name=pred_field[0], value=pred_field[1], inline=False) embed.set_footer(text='✅ = Correct, ❌ = Wrong, ⌛ = TBD') await ctx.send(embed=embed)
async def get_prediction(user, recruit): get_prediction_query = '''SELECT * FROM fap_predictions WHERE user_id = %s AND recruit_profile = %s;''' sql_response = process_MySQL(query=get_prediction_query, values=(user.id, recruit.x247_profile), fetch='one') return sql_response
async def leaderboard(self, ctx): leaderboard = process_MySQL( query=sqlRetrieveCurrencyLeaderboard, fetch="all" ) lb = "```html\n" for index, person in enumerate(leaderboard): if index > 9: break member = person["username"] spacer = "." * (50 - len(f"🥇: {member}{person['balance']:,}")) if member is not None: if index == 0: lb += f"🥇: {member}{spacer}{person['balance']:,}\n" elif index == 1: lb += f"🥈: {member}{spacer}{person['balance']:,}\n" elif index == 2: lb += f"🥉: {member}{spacer}{person['balance']:,}\n" else: lb += f"🏅: {member}{spacer}{person['balance']:,}\n" # await ctx.send( # embed=build_embed( # title=f"Husker Discord Currency Leaderboard", # fields=[ # [f"Top 10 {CURRENCY_NAME} Leaderboard", lb] # ] # ) # ) await ctx.send(lb + "\n```")
async def leaderboard(self, ctx): leaderboard = process_MySQL(query=sqlRetrieveCurrencyLeaderboard, fetch="all") lb = "" for index, person in enumerate(leaderboard): if index > 9: break member = person["username"][:13] spacer = "." * (35 - len(f"`🥇: {member}{person['balance']:,}`")) if member is not None: if index == 0: lb += f"`🥇: {member}{spacer}{person['balance']:,}`\n" elif index == 1: lb += f"`🥈: {member}{spacer}{person['balance']:,}`\n" elif index == 2: lb += f"`🥉: {member}{spacer}{person['balance']:,}`\n" else: lb += f"`🏅: {member}{spacer}{person['balance']:,}`\n" await ctx.send(embed=build_embed( title=f"Husker Discord Currency Leaderboard", fields=[[f"Top 10 {CURRENCY_NAME} Leaderboard", lb]]))
async def quit_game(ctx): global game scores = scoreboard() await game.channel.send(embed=trivia_embed( ["Quitting", "The current trivia game has ended!"], ["Scores", scores]) ) # award server currency process_MySQL( query=sqlUpdateCurrency, values=( 25, f"{ctx.message.author.name}#{ctx.message.author.discriminator}")) game = TriviaGame(channel=None)
def retrieve_all_bet_keyword_custom_line(self, keyword): try: return process_MySQL( query=sqlRetrieveAllCustomLinesKeywords, values=keyword, fetch="all" ) except: return None
async def leaderboard(self, ctx, year=None): """Get the FAP leaderboard. If no year is given, it will provide the leaderboard for the current recruiting class.""" from utils.client import client if year is None: year = str(CURRENT_CLASS) embed_title = f'{year} FAP Leaderboard' get_all_preds_query = f"SELECT * FROM fap_predictions WHERE recruit_class = {year}" if year.lower() == 'overall': get_all_preds_query = '''SELECT * FROM fap_predictions''' embed_title = 'All-Time FAP Leaderboard' faps = process_MySQL(query=get_all_preds_query, fetch='all') faps_df = pd.DataFrame(faps) faps_nn = faps_df[(faps_df['correct'].notnull())].copy() leaderboard = pd.DataFrame(faps_nn['user_id'].unique(), columns=['user_id']) leaderboard['points'] = 0 leaderboard['correct_pct'] = 0 for u in leaderboard['user_id'].unique(): faps_user = faps_nn[faps_nn['user_id'] == u].copy() leaderboard.loc[leaderboard['user_id'] == u, 'correct_pct'] = faps_user['correct'].mean() * 100 faps_user['correct'] = faps_user['correct'].replace(0.0, -1.0) faps_user[ 'points'] = faps_user['correct'] * faps_user['confidence'] pred_time_deltas = ( faps_user.loc[faps_user['correct'] == 1, 'decision_date'] - faps_user.loc[faps_user['correct'] == 1, 'prediction_date']).values pred_time_delta_sum = float(sum(pred_time_deltas)) pred_time_bonus = (pred_time_delta_sum / 86400000000000) * 0.1 leaderboard.loc[ leaderboard['user_id'] == u, 'points'] = faps_user['points'].sum() + pred_time_bonus leaderboard = leaderboard.sort_values('points', ascending=False) embed_string = 'User: Points (Pct Correct)' place = 1 for u in leaderboard['user_id']: try: user = ctx.guild.get_member(u) username = user.display_name except: user = faps_df.loc[faps_df['user_id'] == u, 'user'].values[-1] username = user if user is None: continue points = leaderboard.loc[leaderboard['user_id'] == u, 'points'].values[0] correct_pct = leaderboard.loc[leaderboard['user_id'] == u, 'correct_pct'].values[0] embed_string += f'\n#{place} {username}: {points:.1f} ({correct_pct:.0f}%)' place += 1 embed_msg = discord.Embed(title=embed_title, description=embed_string) await ctx.send(embed=embed_msg)
def retrieve_all_bet_keyword_custom_line(self, ctx: discord.ext.commands.Context, keyword): try: return process_MySQL(query=sqlRetrieveAllCustomLinesKeywords, values=keyword, fetch="all") except: return None
def retrieve_one_bet_keyword_custom_line(self, ctx: discord.ext.commands.Context, keyword): try: return process_MySQL(query=sqlRetrieveOneCustomLinesKeywords, values=(keyword, ctx.message.author.id), fetch="one") except: return None
def get_croot_predictions(recruit): get_croot_preds_query = '''SELECT f.recruit_name, f.team, avg(f.confidence) as 'confidence', (count(f.team) / t.sumr) * 100 as 'percent', t.sumr as 'total' FROM fap_predictions as f JOIN (SELECT recruit_profile, COUNT(recruit_profile) as sumr FROM fap_predictions GROUP BY recruit_profile) as t on t.recruit_profile = f.recruit_profile WHERE f.recruit_profile = %s GROUP BY f.recruit_profile, f.recruit_name, f.team ORDER BY percent DESC; ''' get_croot_preds_response = process_MySQL(query=get_croot_preds_query, values=(recruit.x247_profile), fetch='all') return get_croot_preds_response
def scoreboard(): scores = process_MySQL(fetch="all", query=sqlRetrieveTriviaScores) if scores: scores_edited = "" for index, score in enumerate(scores): scores_edited += f'#{index + 1}. {score["user"]}: {score["score"]}\n' return scores_edited else: return "N/A"
async def iowa(self, ctx, who: discord.Member, *, reason: str): """ Removes all roles from a user, applies the @Time Out role, and records the user's ID to prevent leaving and rejoining to remove @Time Out """ if not who: raise AttributeError("You must include a user!") if not reason: raise AttributeError("You must include a reason why!") timeout = ctx.guild.get_role(ROLE_TIME_OUT) iowa = ctx.guild.get_channel(CHAN_IOWA) added_reason = f"Time Out by {ctx.message.author}: " roles = who.roles previous_roles = [str(role.id) for role in who.roles[1:]] if previous_roles: previous_roles = ",".join(previous_roles) for role in roles: try: await who.remove_roles(role, reason=added_reason + reason) except discord.Forbidden: pass except discord.HTTPException: pass try: await who.add_roles(timeout, reason=added_reason + reason) except discord.Forbidden: pass except discord.HTTPException: pass process_MySQL(query=sqlInsertIowa, values=(who.id, added_reason + reason, previous_roles)) await iowa.send(f"[ {who.mention} ] has been sent to {iowa.mention}.") await ctx.send( f"[ {who} ] has had all roles removed and been sent to Iowa. Their User ID has been recorded and {timeout.mention} will be reapplied on rejoining the server." ) await who.send( f"You have been moved to [ {iowa.mention} ] for the following reason: {reason}." )
async def grantall(self, ctx, value: int): users = process_MySQL(query=sqlRetrieveCurrencyLeaderboard, fetch="all") for user in users: usr = ctx.guild.get_member(user["user_id"]) if usr: self.adjust_currency(usr, value) return await ctx.send( f"Everyone with a server currency wallet has received [ {value:,} ] {CURRENCY_NAME}!" )
def get_balance(self, user: discord.Member): if self.check_author_initialized(user): balance = process_MySQL(fetch="one", query=sqlRetrieveCurrencyUser, values=user.id) else: raise AttributeError( "Unable to find user! Establish a balance with `$money new`.") if balance is None: raise AttributeError("Unable to find user!") return balance["balance"]
async def user(self, ctx, target_member: discord.Member = None, year: int = None): """Get the predictions for a user for a given year.""" if target_member is None: target_member = ctx.author if year is None: year = CURRENT_CLASS get_user_preds_query = '''SELECT * FROM fap_predictions WHERE user_id = %s AND recruit_class = %s ORDER BY prediction_date ASC''' user_preds = process_MySQL(query=get_user_preds_query, values=(target_member.id, year,), fetch='all') if user_preds is None: if target_member.id == ctx.author.id: await ctx.send(f"You do not have any predictions for the {year} class. Get on it already.") else: await ctx.send(f"{target_member.display_name} doesn't have any predictions for the {year} class.") return embed_title = f"{target_member.display_name}'s {year} Predictions" embed = discord.Embed(title=embed_title) correct_amount = 0 incorrect_amount = 0 for i, p in enumerate(user_preds): field_title = '' field_value = '' if p['correct'] == 1: field_title += '✅ ' correct_amount += 1 elif p['correct'] == 0: field_title = '❌ ' incorrect_amount += 1 elif p['correct'] is None: field_title += '⌛ ' field_title += f"{p['recruit_name']}" pred_date = p['prediction_date'] if isinstance(pred_date, str): pred_date = datetime.datetime.strptime(p['prediction_date'], DATETIME_FORMAT) field_value = f"{p['team']} ({p['confidence']}) - {pred_date.month}/{pred_date.day}/{pred_date.year} \[[247 Profile]({p['recruit_profile']})\]" embed.add_field(name=field_title, value=field_value, inline=False) embed_description = '' if correct_amount + incorrect_amount > 0: embed_description = f"""Total {year} Predictions: {len(user_preds)}\nPercent Correct: {(correct_amount / (correct_amount + incorrect_amount)) * 100:.0f}% ({correct_amount}/{correct_amount + incorrect_amount})\n\n""" else: embed_description = f"""Total {year} Predictions: {len(user_preds)}\n\n""" embed.description = embed_description embed.set_footer(text='✅ = Correct, ❌ = Wrong, ⌛ = TBD') await ctx.send(embed=embed)
def retrieve_custom_lines_bets(self, keyword): """ Return all bets placed against keyword. :param keyword: :return: """ if keyword: return process_MySQL( query=sqlRetreiveCustomLinesForAgainst, values=keyword, fetch="all" ) return None
def setup(self, user: discord.Member, chan, timer, questions, category): self.trivia_master = user self.channel = chan self.timer = int(timer) if category[0] == 0: trivia_questions = process_MySQL(fetch="all", query=sqlRetrieveTriviaQuestions) random.shuffle(trivia_questions) self.questions = trivia_questions[0:int(questions)] self.category_index = category[0] self.category = category[1].title() else: self.category_index = category[0] self.category = category[1].title() url = f"https://opentdb.com/api.php?amount={questions}&category={self.category_index}&&type=multiple" q = [] try: r = requests.get(url) for index, question in enumerate(r.json()["results"]): q.append({ "question": html.unescape( question["question"]).strip("\r").strip("\n"), "correct": html.unescape(question["correct_answer"]).strip( "\r").strip("\n"), "wrong_1": html.unescape(question["incorrect_answers"][0]).strip( "\r").strip("\n"), "wrong_2": html.unescape(question["incorrect_answers"][1]).strip( "\r").strip("\n"), "wrong_3": html.unescape(question["incorrect_answers"][2]).strip( "\r").strip("\n") }) except: print("Error in questions....") return self.questions = q[0:int(questions)] self.setup_complete = True
def validate_keyword_bet(self, keyword: str): """ Retrieves all bets from `custom_lines` database. Returns True if `keyword` exists else returns False :param keyword: :return: """ try: check = process_MySQL(query=sqlRetrieveOneOpenCustomLine, values=keyword, fetch="all") except ConnectionError: return False else: if check is None: return False for ch in check: if keyword in ch.values(): return True
def check_author_initialized(self, user: discord.Member): author_init = process_MySQL(fetch="one", query=sqlCheckCurrencyInit, values=user.id) err = AttributeError( f"You have not established a wallet yet. This is accomplished by completing `$money new`." ) if author_init is None: return False try: if author_init["init"] == 1: return True elif author_init["init"] == 0: return False else: return False except: return False
def is_iowegian(self, member: discord.Member): return process_MySQL(query=sqlRetrieveIowa, values=member.id, fetch="all")