def createFiles(): """ Creates the necessary files for the bot to work :return: None """ keyword = "FILE" file_list = ["ignored_users", "ignored_channels", "bot_prefix", "versions"] website_list = ["ad", "dm", "ep", "la"] stop = False settings_default = { "upload to git": False, "channel_to_post": "test", "test_livestream_message": True, "send_message_to_finn": False, "lecture": 111111111111111111111, "test": 111111111111111111111, "prefix": "$" } # This is the file that stores the token if not os.path.exists("../LECTURFIER.json"): log("Creating LECTURFIER.json", keyword) stop = True with open("../LECTURFIER.json", "w") as f: f.write('{"token":""}') if os.path.exists("./data/discord.db"): print("Making sure all DB tables exist") create_tables() check_columns() print("----- DB Check Complete -----") if not os.path.exists("./data/settings.json"): log("Creating settings.json", keyword) stop = True with open("./data/settings.json", "w") as f: json.dump(settings_default, f, indent=2) for file in file_list: if not os.path.exists(f"./data/{file}.json"): log(f"Creating {file}.json", keyword) stop = True with open(f"./data/{file}.json", "w") as f: f.write("{}") for link in website_list: if not os.path.exists(f"./websites/{link}.html"): log(f"Creating {link}.html", keyword) stop = True with open(f"./websites/{link}.html", "w") as f: pass if stop: log("All files created. Restart the bot.", keyword) exit()
def gitpush(directory): """ Commits and pushes a git directory :param directory: directory to commit and push :return: commit and push message """ commit_out = subprocess.run(["git", "-C", directory, "commit", "-a", "-m", "Update"]) log(f"Commited: {commit_out}", "GIT") push_out = subprocess.run(["git", "-C", directory, "push", "-u"]) # git -C ./data push -u origin main log(f"Pushed: {push_out}", "GIT") return commit_out.returncode, push_out.returncode
async def on_ready(self): log("\n----------------------------\nStarting up bot") print("Logged in as:", "LOGIN") print(f"Name: {self.bot.user.name}", "LOGIN") print(f"ID: {self.bot.user.id}", "LOGIN") print(f"Version: {discord.__version__}", "LOGIN") await self.bot.change_presence(activity=discord.Activity( name="myself startup", type=discord.ActivityType.watching)) print("-------------") await self.load_all_extensions(self.startup_extensions) file_creator.createFiles() log("Started up bot\n-------------")
async def load_all_extensions(self, extensions_to_load) -> int: count = 0 for extension in extensions_to_load: try: loaded_cog = self.bot.load_extension("cogs." + extension) log("Loaded extension \"{}\".".format(extension)) count += 1 except discord.ext.commands.errors.ExtensionAlreadyLoaded: pass except Exception as e: log("Failed loading extension \"{}\"\n-{}: {}".format( extension, e, type(e)), print_it=True, warning=True) return count
async def on_message(self, message): if message.author.bot: return # To get a quote you can just type `-name` if message.content.startswith("-"): name = "NONE" try: random.seed(time.time()) name = message.content.replace("-", "").lower() rand_quote = random.choice(self.quotes[str( message.guild.id)][name]) await send_quote(message.channel, rand_quote[1], rand_quote[0], name) except IndexError: log(f"Did not find quote from user: {name}", "QUOTE") except KeyError: log(f"Name does not exist in database: {name}", "QUOTE")
async def point_distribute(self, confirmed_cases): log(f"Starting COVID points distribution", "COVID") lb_messages = [] rank = 1 guessers = SQLFunctions.get_covid_guessers(self.conn, guessed=True) for g in guessers: g.TempPoints = int(calculate_points(confirmed_cases, g.NextGuess)) # Sort the guessers by their gotten points guessers.sort(key=lambda x: x.TempPoints, reverse=True) for g in guessers: msg = f"**{rank}:** <@{g.member.DiscordUserID}> got {g.TempPoints} points *(guess: {g.NextGuess})*" rank += 1 lb_messages.append(msg) SQLFunctions.clear_covid_guesses(users=guessers, increment=True, conn=self.conn) return lb_messages
async def reload(self, ctx, cog=None): """ Used to reload a cog. Does not load a cog if the cog is unloaded. Permissions: Owner """ if cog is None: cog_list = '\n'.join(self.startup_extensions) await ctx.send(f"Following cogs exist:\n" f"{cog_list}") elif cog in self.startup_extensions: await ctx.send(await self.reload_cog(cog)) await ctx.send(f"DONE - Reloaded `{cog}`") elif cog == "all": await ctx.send("Reloading all cogs") log("Reloading all cogs", "COGS") for cog in self.startup_extensions: await ctx.send(await self.reload_cog(cog)) await ctx.send("DONE - Reloaded all cogs") else: await ctx.send(f"Cog does not exist.")
async def point_distribute(self, guild, confirmed_cases): log(f"Starting COVID points distribution", "COVID") conn = self.get_connection() lb_messages = [] rank = 1 for row in conn.execute( "SELECT UniqueMemberID, NextGuess FROM CovidGuessing WHERE NextGuess IS NOT NULL" ): conn.execute( "UPDATE CovidGuessing SET TempPoints=? WHERE UniqueMemberID=?", (int(calculate_points(confirmed_cases, row[1])), row[0])) conn.commit() for row in conn.execute( """ SELECT DM.DiscordUserID, CG.UniqueMemberID, CG.NextGuess, CG.TempPoints FROM CovidGuessing as CG INNER JOIN DiscordMembers as DM on CG.UniqueMemberID=DM.UniqueMemberID WHERE CG.NextGuess IS NOT NULL AND DM.DiscordGuildID=? ORDER BY CG.TempPoints DESC""", (guild.id, )): msg = f"**{rank}:** <@{row[0]}> got {row[3]} points *(guess: {row[2]})*" rank += 1 lb_messages.append(msg) conn.execute("""UPDATE CovidGuessing SET TotalPointsAmount=TotalPointsAmount+TempPoints, GuessCount=GuessCount+1, TempPoints=NULL, NextGuess=NULL WHERE TempPoints IS NOT NULL""") conn.commit() return lb_messages
async def background_check_cases(self): counter = 0 await self.bot.wait_until_ready() while not self.bot.is_closed(): self.time_heartbeat = time.time() async with aiohttp.ClientSession() as cs: async with cs.get( "https://www.covid19.admin.ch/en/overview") as r: response = await r.read() soup = bs(response.decode('utf-8'), "html.parser") new_cases = int( soup.find_all("span", class_="bag-key-value-list__entry-value") [0].get_text().replace(" ", "")) if self.cases_today != new_cases: self.cases_today = new_cases with open("./data/covid19.txt", "w") as f: f.write(str(new_cases)) log("Daily cases have been updated", "COVID") guild = self.bot.get_guild(747752542741725244) channel = guild.get_channel(747752542741725247) await self.send_message(channel, guild, new_cases) await asyncio.sleep(10)
async def quote(self, ctx, name=None, *quote): """ Sends a completely random quote from the server if all parameters are empty. \ If only a name is given, it sends a random quote from that user. By using `-name` for any name that has quotes you can display a random quote from that person \ directly. Some examples: `$quote` - sends a random quote from any user `$quote ueli` - sends a random quote from the user ueli `$quote ueli haHaa` - adds "haHaa" as a quote to the user ueli `$quote ueli all` - displays all quotes from the user ueli `$quote ueli 23` - displays the 23rd indexed quote from the user ueli `$quote names` - displays all names that have a quote `-ueli` - displays a random quote from the one and only ueli """ guild_id = str(ctx.message.guild.id) if name is not None: if name == "names": if guild_id not in self.quotes: await ctx.send("There are no quotes on this server yet.") raise discord.ext.commands.errors.BadArgument else: all_names = "Everybody with a quote as of now:\n" for n in self.quotes[guild_id].keys(): all_names += f"-{n}\n" embed = discord.Embed(title=name, description=all_names, color=0x404648) await ctx.send(embed=embed) else: quote = " ".join(quote) try: memberconverter = discord.ext.commands.MemberConverter() name = await memberconverter.convert(ctx, name) name = name.name except discord.ext.commands.errors.BadArgument: name = str(name) if "@" in name or "@" in quote: await ctx.send( "Quotes can't contain `@` in names (unless they are mentions) or in the quote." ) raise discord.ext.commands.errors.BadArgument name = name.lower() # checks if the name is an alias for key in self.aliases.keys(): for alias in self.aliases[key]: if alias == name: name = key if len(quote) > 0: await self.user_checkup(guild_id, name) try: # Checks if the quote is a quote index index = int(quote) await send_quote(ctx, self.quotes[guild_id][name][index][1], self.quotes[guild_id][name][index][0], name, index) except ValueError: # Is the quote a command or a new quote to add if quote.lower() == "all": # show all quotes from name quote_list = "" for i in range(len(self.quotes[guild_id][name])): quote_to_add = self.quotes[guild_id][ name][i][1].replace("*", "").replace( "_", "").replace("~", "").replace( "\\", "").replace("`", "") quote_list += f"\n**{[i]}:** {quote_to_add}" # If there are no quotes for the given person; if len(quote_list) == 0: await ctx.send( f"{name} doesn't have any quotes yet.") raise discord.ext.commands.errors.BadArgument embed = discord.Embed( title=f"All quotes from {name}", color=0x404648) # if the quote is too long: splitted_lines = quote_list.split("\n") msg = "" counter = 1 msg_length = 0 for line in splitted_lines: if msg_length >= 5000: await ctx.send(embed=embed) embed = discord.Embed(color=0x404648) msg_length = 0 msg = "" if len(line) + len(msg) < 1000: msg += "\n" + line else: embed.add_field(name=f"Page {counter}", value=msg) msg_length += len(msg) msg = line counter += 1 embed.add_field(name=f"Page {counter}", value=msg) await ctx.send(embed=embed) elif quote.lower().split( " ")[0] == "del": # Command to delete quotes if not await self.bot.is_owner(ctx.author): raise discord.ext.commands.errors.NotOwner try: index = int(quote.lower().split(" ")[1]) try: self.quotes[guild_id][name].pop(index) # SAVE FILE with open(self.quotes_filepath, "w") as f: json.dump(self.quotes, f, indent=2) log("SAVED QUOTES", "QUOTES") await ctx.send( f"Deleted quote with index {index}.") except IndexError: await ctx.send("No name with that index.") except (IndexError, ValueError): await ctx.send("You forgot to add an index.") else: # If the quote is a new quote to add date = datetime.datetime.now( timezone("Europe/Zurich")).strftime("%d/%m/%Y") if len(quote ) > 500 and not await self.bot.is_owner( ctx.author): await ctx.send( "This quote exceeds the max_length length of 500 chars. DM Mark if you want the quote added." ) raise discord.ext.commands.errors.NotOwner self.quotes[guild_id][name].append([date, quote]) # SAVE FILE try: with open(self.quotes_filepath, "w") as f: json.dump(self.quotes, f, indent=2) log(f"Added quote for {name}", "QUOTES") log("SAVED QUOTES", "QUOTES") except Exception: log( f"Saving QUOTES file failed:\n{traceback.format_exc()}", "QUOTES") user = self.bot.get_user(self.bot.owner_id) await user.send( f"Saving QUOTES file failed:\n{traceback.format_exc()}" ) await ctx.send(f"Added quote for {name}") except IndexError: await ctx.send( f"{name} doesn't have a quote with that index.") raise discord.ext.commands.errors.BadArgument else: try: random.seed(time.time()) rand_quote = random.choice(self.quotes[guild_id][name]) await send_quote(ctx, rand_quote[1], rand_quote[0], name) except (KeyError, IndexError): await ctx.send(f"{name} doesn't have any quotes yet.") raise discord.ext.commands.errors.BadArgument else: # If $quote is written on its own, send a random quote from any user c = 0 # Counter: So the bot doesnt loop too much in case there's no non-empty quote for some reason while True: try: random.seed(time.time() + c) rand_name = random.choice( list(self.quotes[guild_id].keys())) rand_quote = random.choice( self.quotes[guild_id][rand_name]) await send_quote(ctx, rand_quote[1], rand_quote[0], rand_name) break except IndexError: c += 1 if c >= 10: await ctx.send("No quotes found.") raise discord.ext.commands.errors.BadArgument except KeyError: await ctx.send("There are no quotes on this server yet.") raise discord.ext.commands.errors.BadArgument
async def on_ready(self): print("\n----------------------------") log("Starting up bot") log("Logged in as:") log(f"Name: {self.bot.user.name}") log(f"ID: {self.bot.user.id}") log(f"Version: {discord.__version__}") await self.bot.change_presence(activity=discord.Activity( name=random.choice(self.watching_messages), type=discord.ActivityType.watching)) print("-------------") count = await self.load_all_extensions(self.startup_extensions) log(f"Started up bot with {count}/{len(self.startup_extensions)-2} extensions loaded successfully." ) print("-------------")
async def background_loop(self): await self.bot.wait_until_ready() sent_updates = False sent_covid = False while not self.bot.is_closed(): self.time_heartbeat = time.time() await asyncio.sleep(10) try: cur_time = datetime.now(timezone("Europe/Zurich")).strftime("%a:%H:%M") if self.test_livestream_message: cur_time = "test" # if int(datetime.now(timezone("Europe/Zurich")).strftime("%M")) % 10 == 0: # Only check updates every 10 minutes # await self.check_updates(channel, cur_time, self.lecture_updater_version) # Send the covid guesser notification if not sent_covid and "10:00" in cur_time and "Sat" not in cur_time and "Sun" not in cur_time: sent_covid = True general = self.bot.get_channel(747752542741725247) await general.send("<@&770968106679926868> it's time to guess today's covid cases using `$g <guess>`!") if "10:00" not in cur_time: sent_covid = False # Check what lectures are starting minute = datetime.now().minute if not sent_updates and minute <= 5: sent_updates = True subject = self.get_starting_subject() if subject is not None: await self.send_lecture_start( subject["SubjectName"], subject["SubjectLink"], subject["StreamLink"], self.channel_to_post, 759615935496847412, # Role to ping subject["ZoomLink"], subject["OnSiteLocation"]) # Send in #lecture-distractions without ping await self.send_lecture_start( subject["SubjectName"], subject["SubjectLink"], subject["StreamLink"], 755339832917491722, 0, # Role to ping subject["ZoomLink"], subject["OnSiteLocation"]) # send in #lecture-questions without ping await self.send_lecture_start( subject["SubjectName"], subject["SubjectLink"], subject["StreamLink"], 813397356837863454, 0, # Role to ping subject["ZoomLink"], subject["OnSiteLocation"]) if minute > 5: sent_updates = False # Update activity status: time_till_next = self.get_time_till_next_lesson() if time_till_next != self.current_activity: await self.bot.change_presence(activity=discord.Activity(name=time_till_next, type=discord.ActivityType.watching)) except AttributeError as e: print(f"ERROR in Lecture Updates Loop! Probably wrong channel ID | {e}") except Exception: await asyncio.sleep(10) user = self.bot.get_user(self.bot.owner_id) await user.send(f"Error in background loop: {traceback.format_exc()}") log(f"Error in background loop self.bot.py: {traceback.format_exc()}", "BACKGROUND")
async def background_check_cases(self): try: await self.bot.wait_until_ready() # TURN OFF OVER NEW YEAR dt = datetime.now(timezone("Europe/Zurich")) if (dt.month == 12 and dt.day == 31) or (dt.month == 1 and dt.day in [1, 2]): return # Send the covid guesser notification general_channel = 898674880864743444 try: cur_time = datetime.now( timezone("Europe/Zurich")).strftime("%a:%H:%M") if not self.sent_covid and "10:00" in cur_time and "Sat" not in cur_time and "Sun" not in cur_time: self.sent_covid = True general = self.bot.get_channel(general_channel) msg = "Good Morning!\nGuess today's covid cases using `$g <guess>`!" embed = discord.Embed(description=msg, color=discord.Color.gold()) await general.send("<@&770968106679926868>", embed=embed) if "10:00" not in cur_time: self.sent_covid = False except Exception as e: print(e) # checks the daily cases url = "https://www.covid19.admin.ch/api/data/context/history" response = {} async with aiohttp.ClientSession() as cs: async with cs.get(url) as r: response = await r.json() # gets the last updated day from the website last_updated = response["dataContexts"][0]["date"] daily_url = response["dataContexts"][0]["dataContextUrl"] if len(last_updated) > 0: # to make sure we even got anything day = int(last_updated.split("-")[2]) else: owner = self.bot.get_user(205704051856244736) await owner.send( content= f"Covid cases failed updating. Last updated is empty:\n```{last_updated}```" ) raise ValueError # fetches the new cases # daily_url is of format https://www.covid19.admin.ch/api/data/DATE-random-gibberish/context # we want to go to this instead: https://www.covid19.admin.ch/api/data/DATE-random-gibberish/sources/COVID19Cases_geoRegion.json if self.last_cases_day != day: daily_url = daily_url.replace( "context", "sources/COVID19Cases_geoRegion.json") async with aiohttp.ClientSession() as cs: async with cs.get(daily_url) as r: response = await r.json() new_cases = -1 for line in response: # finds the cases for today's date and for all of switzrland and liechtenstein if line["geoRegion"] == "CHFL" and line[ "datum"] == last_updated: new_cases = line["entries_diff_last"] break if new_cases == -1: print("Wasn't able to get daily covid cases") raise ValueError self.cases_today = new_cases self.last_cases_day = day guild = self.bot.get_guild(747752542741725244) if guild is None: guild = self.bot.get_guild(237607896626495498) channel = guild.get_channel(general_channel) if channel is None: channel = guild.get_channel(402563165247766528) await self.send_message(channel, new_cases) log("Daily cases have been updated", print_it=True) SQLFunctions.insert_or_update_config("COVID_Cases", new_cases, self.conn) SQLFunctions.insert_or_update_config("COVID_Day", day, self.conn) SQLFunctions.store_covid_cases(new_cases, conn=self.conn) except Exception as e: print(f"COVID loop messed up:\n{e}") await asyncio.sleep(20)
async def check_updates(self, channel, cur_time, version): start = time.time() scraped_info = scraper() changes = scraped_info[0] lecture_urls = scraped_info[1] send_ping = True for lesson in changes.keys(): try: if len(changes[lesson]) > 0: for i in range(len(changes[lesson])): # EMBED COLOR color = discord.Color.lighter_grey() if lesson == "Introduction to Programming": color = discord.Color.blue() elif lesson == "Discrete Mathematics": color = discord.Color.purple() elif lesson == "Linear Algebra": color = discord.Color.gold() elif lesson == "Algorithms and Data Structures": color = discord.Color.magenta() try: correct_changes = changes[lesson][i] except KeyError as e: correct_changes = changes[lesson] user = self.bot.get_user(self.bot.owner_id) await user.send(f"Lesson: {lesson}\nError: KeyError\nChanges: `{changes}`") if correct_changes["event"] == "other": embed = discord.Embed(title=f"{lesson} has been changed!", description=f"[Click here to get to {lesson}'s website]({lecture_urls[lesson]}).", timestamp=datetime.utcfromtimestamp(time.time()), color=color) if self.send_message_to_finn: users = [self.bot.owner_id, 304014259975880704] # 304014259975880704 else: users = [self.bot.owner_id] for u_id in users: user = self.bot.get_user(u_id) await user.send(embed=embed) elif correct_changes["event"] == "edit": log(f"{lesson} was changed", "LESSON") title = f"There has been an edit on __{lesson}__" description = f"""**OLD**: {self.format_exercise(correct_changes["content"]["old"])} **NEW**: {self.format_exercise((correct_changes["content"]["new"]), correct_changes["content"]["keys"])}""" embed = discord.Embed(title=title, description=description, timestamp=datetime.utcfromtimestamp(time.time()), color=color) embed.set_footer( text=f"{version} | This message took {round(time.time() - start, 2)} seconds to send") if send_ping: msg = await channel.send("<@&759615935496847412>", embed=embed) else: msg = await channel.send(embed=embed) await msg.publish() send_ping = False elif correct_changes["event"] == "new": log(f"{lesson} got an new update", "LESSON") title = f"Something new was added on __{lesson}__" description = f"""**NEW**:\n{self.format_exercise(correct_changes["content"])}""" embed = discord.Embed(title=title, description=description, timestamp=datetime.utcfromtimestamp(time.time()), color=color) embed.set_footer( text=f"{version} | This message took {round(time.time() - start, 2)} seconds to send") if send_ping: msg = await channel.send("<@&759615935496847412>", embed=embed) else: msg = await channel.send(embed=embed) await msg.publish() send_ping = False except Exception: user = self.bot.get_user(self.bot.owner_id) await user.send(f"Lesson{lesson}\nError: {traceback.format_exc()}")
def createFiles(): """ Creates the necessary files for the bot to work :return: None """ keyword = "FILE" file_list = ["quotes", "reputation", "ignored_users", "ignored_channels", "covid_points", "bot_prefix", "guesses", "versions"] website_list = ["ad", "dm", "ep", "la"] stop = False settings_default = { "upload to git": False, "channel_to_post": "test", "test_livestream_message": True, "send_message_to_finn": False, "lecture": 111111111111111111111, "test": 111111111111111111111, "prefix": "$" } schedule_default = { "eprog": { "Mon:04:20": "FILLER", "Tue:04:20": "FILLER", "url": "FILLER" }, "diskmat": { "Wed:04:20": "FILLER", "Thu:04:20": "FILLER", "url": "FILLER" }, "linalg": { "Fri:04:20": "FILLER", "Sat:04:20": "FILLER", "url": "FILLER" }, "and": { "Sun:04:20": "FILLER", "url": "FILLER" }, "test": { "test": "TEST MESSAGE", "url": "This is the url to the website" } } # This is the file that stores the token if not os.path.exists("../LECTURFIER.json"): log("Creating LECTURFIER.json", keyword) stop = True with open("../LECTURFIER.json", "w") as f: f.write('{"token":""}') if not os.path.exists("./data/discord.db"): print("Creating DB tables") handySQL.create_all_tables("./data/discord.db") print("Created DB tables successfully") if not os.path.exists("./data/settings.json"): log("Creating settings.json", keyword) stop = True with open("./data/settings.json", "w") as f: json.dump(settings_default, f, indent=2) for file in file_list: if not os.path.exists(f"./data/{file}.json"): log(f"Creating {file}.json", keyword) stop = True with open(f"./data/{file}.json", "w") as f: f.write("{}") if not os.path.exists("./data/schedule.json"): log("Creating schedule.json", keyword) stop = True with open("./data/schedule.json", "w") as f: json.dump(schedule_default, f, indent=2) for link in website_list: if not os.path.exists(f"./websites/{link}.html"): log(f"Creating {link}.html", keyword) stop = True with open(f"./websites/{link}.html", "w") as f: pass if not os.path.exists(f"./data/covid19.txt"): log(f"Creating covid19.txt", keyword) stop = True with open(f"./data/covid19.txt", "w") as f: f.write("0") if stop: log("All files created. Restart the bot.", keyword) exit()
from behave import given, when, then import requests import helper.rw_csv as csv from helper.log import custom_logger as log log = log() log.info( "*******************************************NEW RUN*********************************************************" ) @given(u'I set base REST API url and headers correctly') def setup_baseurl(context): context.baseURL = context.config.userdata.get("base_url", "url") context.headers = { "token": context.config.userdata.get("access_token", "token"), "content-type": "application/json" } context.account_id = context.config.userdata.get("account_id", "1001") log.info(f"Base URL set to : {context.baseURL}") log.info(f"Headers set to : {context.headers}") log.info(f"account_id set to : {context.account_id}") @given(u'Execute test case {testcase_id}') def get_testcase_data(context, testcase_id): context.testcase_id = testcase_id context.row = csv.read_csv(testcase_id, key="row") try: # Check if CSV file returned any error if context.row["error"]: raise context.row["error_msg"]
async def background_loop(self): await self.bot.wait_until_ready() try: # Find out what semesters are currently going on # Only works for the 3 bachelor years as of now month = datetime.now().month if 9 <= month <= 12: semesters = [1, 3, 5] elif 2 <= month <= 6: semesters = [2, 4, 6] else: print( "No subjects going on right now. So skipping the loop completely." ) return dt = datetime.now(timezone("Europe/Zurich")) minute = dt.minute day = dt.day # Check what lectures are starting for sem in semesters: if not self.sent_updates[sem] and minute <= 5: role_id = 0 if sem in [1, 2]: role_id = self.lecture_updates_role_ids["first"] elif sem in [3, 4]: role_id = self.lecture_updates_role_ids["second"] elif sem in [5, 6]: role_id = self.lecture_updates_role_ids["third"] subject = SQLFunctions.get_starting_subject( sem, self.conn, dt.weekday(), dt.hour) if subject is not None: await self.send_lecture_start( subject_name=subject.name, website_url=subject.website_link, stream_url=subject.stream_link, channel_id= 756391202546384927, # lecture updates channel, role_id=role_id, zoom_url=subject.zoom_link, subject_room=subject.on_site_location) self.sent_updates[sem] = True if minute > 5: self.sent_updates = { 1: False, 2: False, 3: False, 4: False, 5: False, 6: False } if not self.sent_website_updates and minute % 10 == 0: exercise_update_channel = self.bot.get_channel( 756391202546384927) # lecture updates channel if exercise_update_channel is None: exercise_update_channel = self.bot.get_channel( 402563165247766528) # channel on bot testing server if exercise_update_channel is not None: await self.check_updates(exercise_update_channel, self.lecture_updater_version) self.sent_website_updates = True elif minute % 10 != 0: self.sent_website_updates = False # advent of code ping if minute > 5: self.sent_advent = False if month == 12 and not self.sent_advent and 1 <= day <= 25 and dt.hour == 6 and minute <= 5: channel = self.bot.get_channel(910450760234467328) msg = f"Good Morning! It's time for **Advent of Code** day #{day}!\n[*Click here to get to the challenge*](https://adventofcode.com/2021/day/{day})" msg += "\n||*Consider donating to AoC to have it continue next year again* <:Santawww:910435057607524352>||" embed = discord.Embed(description=msg, color=discord.Color.red()) await channel.send("<@&910433615689699388>", embed=embed) self.sent_advent = True except AttributeError as e: print( f"ERROR in Lecture Updates Loop! Probably wrong channel ID | {e}" ) except Exception: await asyncio.sleep(10) user = self.bot.get_user(self.bot.owner_id) await user.send( f"Error in background loop: {traceback.format_exc()}") log( f"Error in background loop self.bot.py: {traceback.format_exc()}", "BACKGROUND")