async def canceltask(dbrowid: int): scheduler.cancel(loadedtasks[dbrowid]) async with aiosqlite.connect("database.sqlite") as db: await db.execute("DELETE FROM schedule WHERE id=?", (dbrowid,)) await db.commit() del loadedtasks[dbrowid] logger.debug(f"Cancelled task {dbrowid}")
def __exit__(self, type, value, traceback): logger.info(f"Cleaning up {len(self.files_created)} files created by TFS #{self.id}") logger.debug(f"Temp File Session #{self.id} exiting.") for file in self.files_created: try: os.remove(file) logger.debug(f"Removed {file}") except FileNotFoundError: logger.debug(f"Tried to remove {file}, already removed.") except PermissionError: logger.debug(f"Tried to remove {file}, file is in use.") logger.debug(f"Temp File Session #{self.id} exited.")
async def schedule(time: datetime, eventtype: str, eventdata: dict): assert time.tzinfo is not None # offset aware datetimes my beloved if time <= datetime.now(tz=timezone.utc): logger.debug(f"running event now") await run_event(None, eventtype, eventdata) async with aiosqlite.connect("database.sqlite") as db: async with db.execute("INSERT INTO schedule (eventtime, eventtype, eventdata) VALUES (?,?,?)", (time.timestamp(), eventtype, json.dumps(eventdata))) as cursor: lri = cursor.lastrowid timef = time.replace(tzinfo=timezone.utc).replace(tzinfo=None) task = scheduler.schedule(run_event(lri, eventtype, eventdata), timef) loadedtasks[lri] = task logger.debug(f"scheduled event #{lri} for {time}") # logger.debug(loadedtasks) await db.commit() return lri
async def run_event(dbrowid, eventtype: str, eventdata: dict): try: logger.debug(f"Running Event #{dbrowid} type {eventtype} data {eventdata}") if dbrowid is not None: async with aiosqlite.connect("database.sqlite") as db: await db.execute("DELETE FROM schedule WHERE id=?", (dbrowid,)) await db.commit() del loadedtasks[dbrowid] if eventtype == "debug": logger.debug("Hello world! (debug event)") elif eventtype == "message": ch = eventdata["channel"] try: ch = await botcopy.fetch_channel(ch) except discord.errors.NotFound: ch = await botcopy.fetch_user(ch) await ch.send(eventdata["message"]) elif eventtype == "unban": guild, member = await asyncio.gather(botcopy.fetch_guild(eventdata["guild"]), botcopy.fetch_user(eventdata["member"])) await asyncio.gather(guild.unban(member, reason="End of temp-ban."), member.send(f"You were unbanned in **{guild.name}**."), modlog.modlog(f"{member.mention} (`{member}`) " f"was automatically unbanned.", guild.id, member.id)) elif eventtype == "unmute": guild = await botcopy.fetch_guild(eventdata["guild"]) member = await guild.fetch_member(eventdata["member"]) await asyncio.gather(member.remove_roles(discord.Object(eventdata["mute_role"])), member.send(f"You were unmuted in **{guild.name}**."), modlog.modlog(f"{member.mention} (`{member}`) " f"was automatically unmuted.", guild.id, member.id)) elif eventtype == "un_thin_ice": guild = await botcopy.fetch_guild(eventdata["guild"]) member = await guild.fetch_member(eventdata["member"]) await asyncio.gather(member.remove_roles(discord.Object(eventdata["thin_ice_role"])), member.send(f"Your thin ice has expired in **{guild.name}**."), modlog.modlog(f"{member.mention}'s (`{member}`) " f"thin ice has expired.", guild.id, member.id)) async with aiosqlite.connect("database.sqlite") as db: await db.execute("DELETE FROM thin_ice WHERE guild=? and user=?", (guild.id, member.id)) await db.commit() else: logger.error(f"Unknown event type {eventtype} for event {dbrowid}") except Exception as e: logger.error(e, exc_info=(type(e), e, e.__traceback__))
async def macros(self, ctx: commands.Context): macros = [] async with aiosqlite.connect("database.sqlite") as db: async with db.execute("SELECT name FROM macros WHERE server=?", (ctx.guild.id, )) as cursor: macros = [i[0] for i in await cursor.fetchall()] outstr = f"{len(macros)} macro{'' if len(macros) == 1 else 's'}: {', '.join(macros)}" if len(outstr) < 2000: await ctx.reply(outstr, allowed_mentions=discord.AllowedMentions.none()) else: with io.StringIO() as buf: buf.write(outstr) buf.seek(0) await ctx.reply( f"{len(macros)} macro{'' if len(macros) == 1 else 's'}.", file=discord.File(buf, filename="macros.txt")) logger.debug(macros)
def temp_file(extension="png", temp_name=None): """ generates and reserves the name of a file in temp/ :param extension: the extension of the file :param temp_name: optionally reserve a specific name for deletion :return: the reserved name (no file is created) """ if temp_name is None: temp_name = temp_file_name(extension) frame = inspect.currentframe() try: while "tempfilesession" not in frame.f_locals: frame = frame.f_back frame.f_locals["tempfilesession"].append(temp_name) except AttributeError: if globallist is not None: globallist.append(temp_name) else: logger.warning("Temp file created outside TempFileSession.") logger.debug(f"temp_file reserved {temp_name}") return temp_name
async def emojicount(self, ctx): replystr = f"Gathering emoji statistics for **{ctx.guild.name}**. This may take a while." replymsg = await ctx.reply(replystr) messagecount = 0 emojicount = 0 async with ctx.channel.typing(): emojiregex = r"<a?:\w{2,32}:(\d{18,22})>" counts = defaultdict(int) for channel in ctx.guild.text_channels: logger.debug(f"counting emojis in {channel}") if channel.id == 830588015243427890: continue async for msg in channel.history(limit=None): if messagecount % 1000 == 0: await replymsg.edit( content= f"{replystr}\nCurrently scanning:{channel.mention}" f"\nScanned {messagecount} messages.\nFound {emojicount} emojis.\n" ) messagecount += 1 for match in re.finditer(emojiregex, msg.content): emoji = match.group(0) counts[emoji] += 1 emojicount += 1 await replymsg.edit( content= f"{replystr}\nScanned {messagecount} messages.\nFound {emojicount} emojis.\n" ) sortedcount = { k: v for k, v in sorted( counts.items(), key=lambda item: item[1], reverse=True) } with io.BytesIO() as buf: buf.write(json.dumps(sortedcount, indent=4).encode()) buf.seek(0) await ctx.reply(file=discord.File(buf, filename="emojis.json"))
async def start(): logger.debug("starting scheduler") scheduler.start() async with aiosqlite.connect("database.sqlite") as db: async with db.execute("SELECT id, eventtime, eventtype, eventdata FROM schedule") as cursor: async for event in cursor: data = json.loads(event[3]) dt = datetime.fromtimestamp(event[1], tz=timezone.utc) if dt <= datetime.now(tz=timezone.utc): logger.debug(f"running missed event #{event[0]}") loadedtasks[event[0]] = task # not needed but easier to put this here than to ignore the exception await run_event(event[0], event[2], data) else: logger.debug(f"scheduling stored event #{event[0]}") task = scheduler.schedule(run_event(event[0], event[2], data), dt.replace(tzinfo=None)) loadedtasks[event[0]] = task
def __enter__(self): logger.debug(f"Temp File Session #{self.id} entered.") return self.files_created
def __init__(self): self.id = random.randint(0, 999999999999) logger.debug(f"Temp File Session #{self.id} init.") self.files_created = mgr.list()