async def user_role_looper(self): """ Loop every hour to remove roles from everyone who might have talked. """ # Set up an inner method so we can try and do all of this at once async def inner_method(guild, db): bot_user = guild.get_member( self.bot.user.id) or await self.bot.fetch_member( self.bot.user.id) if not bot_user.guild_permissions.manage_roles: return for member in guild.members: if member.bot: return await self.user_role_handler(member, db) # Ping every guild member self.logger.info("Pinging every guild member with an update") tasks = [] async with self.bot.database() as db: for guild in self.bot.guilds: tasks.append(inner_method(guild, db)) await asyncio.gather(tasks) self.logger.info("Done pinging every guild member")
async def checkPing(self): tasks = [] for i in extrafuncs.CHANNEL_LIST: tasks.append( self.bot.loop.create_task(extrafuncs.ping(self.bot.loop, i))) await asyncio.wait(tasks) pings = [x.result() for x in tasks] if len(pingHistory[0]) == 60: #Over 10 minutes for i in pingHistory: i.pop(0) for i in range(len(pings)): pingHistory[i].append(pings[i]) message = None output = extrafuncs.serverStatusSummary(pingHistory) while True: try: message = await self.bot.get_channel( STATUS_CHANNEL_ID).fetch_message(STATUS_MESSAGE_ID) await message.edit( content="```" + output + f"\nTimestamp: {str(datetime.datetime.now(datetime.timezone.utc))} UTC```" ) break except discord.errors.DiscordServerError: print( "Failed to update the server status tracker. Trying again." ) continue
async def on_reddit_post(self, subreddit: Subreddit, submission: Submission) -> None: if subreddit.id not in self.subreddits: try: self._streams[subreddit.id].cancel() except Exception: log.exception("Error closing stream.") del self._streams[subreddit.id] else: tasks = [] for channel_id in self.subreddits[subreddit.id]["channels"]: channel = self.bot.get_channel(channel_id) if channel is None: continue chan_perms = channel.permissions_for(channel.guild.me) if not chan_perms.send_messages and not chan_perms.manage_webhooks: continue use_embed = True # channel.id not in self.regular_embed_channels contents = await make_embed_from_submission( channel, subreddit, submission) if not contents: continue contents["subreddit"] = subreddit contents["submission"] = submission tasks.append( self.post_new_submissions(channel, contents, use_embed)) await bounded_gather(*tasks, return_exceptions=True)
async def assign_mentors_to_all(): resp = await send_request(method_type="GET", url="/api/v1/mmts") resp = resp.json() mentors_data = resp["data"] tasks = [] for i in range(len(mentors_data)): user_discord_id = mentors_data[i]["attributes"]["user_discord_id"] mentor_discord_id = mentors_data[i]["attributes"]["mentors_discord_id"] user = await client.fetch_user(int(user_discord_id)) mentor = await client.fetch_user(int(mentor_discord_id)) user_msg = 'Your new mentor is: {0.mention}'.format( mentor ) + '\n Feel free to schedule sessions weekly along with the mentor and get your doubts resolved weekly. ' mentor_msg = 'Your new mentee is: {0.mention}'.format( user ) + '\n You are required to give a dedicated amount of time to your mentee and help him to get his/her doubts resolved.' user_prompt = get_basic_prompt(user_msg) mentor_prompt = get_basic_prompt(mentor_msg) tasks.append(asyncio.create_task(user.send(embed=user_prompt))) tasks.append(asyncio.create_task(mentor.send(embed=mentor_prompt))) await asyncio.wait(tasks)
async def add_assignee( self, pulls: typing.Iterable[storage.models.pull.Pull]) -> None: """ Add a person as assignee (requires both the person adding and the person to-be-added to be the repository team's members). """ # FIXME: this doesn't work with channel settings yet, but should. if not pulls or not self.assignee_login: return async with self.github.make_session() as aio_session: tasks = [] for pull in pulls: if self.assignee_login in pull.assignees_logins + [ pull.user_login ]: continue future = self.github.add_assignee(pull.number, self.assignee_login, session=aio_session) tasks.append(asyncio.create_task(future)) if tasks: results = await asyncio.gather(*tasks, return_exceptions=True) if tasks: for pull, result in zip(pulls, results): # 404 also means that you have no write access to a repository if isinstance(result, Exception): logger.error("%s: failed to add assignee for #%s: %s", self.name, pull.number, result)
async def scan_feeds(self, feeds): loop = asyncio.get_event_loop() tasks = [] for feed in feeds: channels = list(feed.get_channels(self.bot)) if len(channels) <= 0: self.bot.logger.info(f'Feed without channels: {feed.id}') continue tasks.append( loop.run_in_executor(None, self.scan_single_feed, feed)) return await asyncio.gather(*tasks)
async def check_dota_blog(self): feed = await httpgetter.get(r'https://blog.dota2.com/feed', return_type="text") blog = feedparser.parse(feed) title = "Dota 2 Blog" updated = rsstools.is_new_blog(blog.entries[0]) if not updated: #if its not updated, stop here return embed = rsstools.create_embed(title, blog.entries[0]) #generate embed ##next section copies code in check_dota_patch in general cogs messageables = [] #find channels to post in guildinfos = botdata.guildinfo_list() for guildinfo in guildinfos: if guildinfo.dotablogchannel is not None: channel = self.bot.get_channel(guildinfo.dotablogchannel) if channel is not None: messageables.append(channel) else: print(f"couldn't find channel {guildinfo.dotablogchannel} when announcing dota blog") #find users userinfos = botdata.userinfo_list() for userinfo in userinfos: if userinfo.dmdotablog: user = self.bot.get_user(userinfo.discord) if user is not None: messageables.append(user) else: print(f"couldn't find user {userinfo.discord} when announcing dota blog") #bundle tasks and execute tasks = [] for messageable in messageables: tasks.append(messageable.send(embed=embed)) bundler = AsyncBundler(tasks) await bundler.wait()
async def websocket_handler(self, connection: _WSSP, cluster: str): cluster_id = int("".join(c for c in cluster if c.isdigit())) logger.debug(f"New Websocket connection from cluster {cluster_id}") tasks: list[asyncio.Task[Any]] = [] self.websockets[cluster_id] = connection try: async for msg in connection: logger.debug(f"Recieved msg from cluster {cluster_id}: {msg}") json_msg: WSGenericJSON = orjson.loads(msg) command = json_msg["c"] handler = getattr(self, f"{command}_handler", None) if handler is None: logger.error(f"Websocket sent unknown command: {command}") else: handler_coro = handler(connection, request=json_msg) tasks.append(self.loop.create_task(handler_coro)) except websockets.ConnectionClosed: logger.error(f"{cluster_id} closed websocket connection!") finally: await asyncio.gather(*tasks)
async def introduction_purger(self): tasks = [] total_messages = 0 messages_to_remove = [] async for introduction in self.get_channel("introductions").history( limit=200): if isinstance(introduction.author, discord.User): messages_to_remove.append(introduction) total_messages += 1 if len(messages_to_remove) >= (total_messages // 2): return for introduction in messages_to_remove: embed = discord.Embed( color=self.bot.get_dominant_color(self.guild), title=f"Purged: Introduction by {introduction.author}", description=introduction.content) tasks.append(self.log("logs", embed=embed)) tasks.append(introduction.delete()) asyncio.gather(*tasks)
async def todo(ctx, *, msg=""): tasks = [] msg = msg.split(" ") if ctx.message.author.id == 173502986448797696: if msg[0] == "add" or msg[0] == "a": try: f = open("todo.txt", mode="a") f.write(msg[1] + "\n") f.close() await ctx.channel.send(msg[1] + " has been added to the todo list") except: print("Something went wrong with adding, it'll be fixed") elif msg[0] == "remove" or msg[0] == "r": try: f = open("todo.txt", mode="r") lines = f.readlines() f.close() newFile = open("todo.txt", "w") for line in lines: if line.strip("\n") != msg[1]: newFile.write(line) newFile.close() await ctx.channel.send("Deleted the command") except: await ctx.channel.send("Unable to find the command") elif msg[0] == "": f = open("todo.txt", "r") for word in f.read().splitlines(): tasks.append(word) await ctx.channel.send( "Master would like to do <@" + str(ctx.message.author.id) + ">'s mother but he also plans to implement the following commands: \n" + (", ".join(tasks))) else: await ctx.send("You do not own this bot!")
async def check_dota_patch(self): print("check_dota_patch() entered") url = "https://www.dota2.com/patches/" try: text = await httpgetter.get(url, return_type="text") except HttpError as e: print(f"patches update failed with http {e.code} error") await self.send_owner( f"patches update failed the check with a http {e.code} error") return # failed, so return except Exception as e: etype = str(type(e).__name__) print(f"patches update failed the check w/ exception {etype}: {e}") await self.send_owner( f"patches update failed the check w/ exception {etype}: {e}") return # failed, so return soup = BeautifulSoup(text, "html.parser") print("patch parse starting") current_patch = soup.find(name="title").contents[0] old_patch = botdata["dotapatch"] if old_patch == current_patch: return # thats the current patch, do nothing if current_patch.strip() == "Gameplay Update": return # thats what happens when theyre tryna switch it and theyre in the process, so give it a minute and try again later print(f"\"{current_patch}\"") print(current_patch == "Gameplay Update") print(str(current_patch) == "Gameplay Update") await self.send_owner( f"patches update triggered: (new one is '{current_patch}', old one was '{old_patch}')" ) botdata["dotapatch"] = current_patch def count_class_in_id(element_id, classname): element = soup.find(id=element_id) if element is None: return 0 return len( element.find_all(lambda tag: tag.get("class") == [classname])) description = "" section_counts = OrderedDict() section_counts["General"] = count_class_in_id("GeneralSection", "PatchNote") section_counts["Item"] = count_class_in_id("ItemsSection", "ItemName") section_counts["Hero"] = count_class_in_id("HeroesSection", "HeroName") for section in section_counts: count = section_counts[section] if count > 0: description += f"\n{count} {section} changes" image_meta_tag = soup.find(name="meta", attrs={"property": "og:image"}) if image_meta_tag is not None: description = "" if description == "" and image_meta_tag is None: description = "*Couldn't parse the changes.*" # we can improve this embed later but for now this is what we got embed = discord.Embed(timestamp=datetime.datetime.utcnow()) embed.title = current_patch embed.url = url embed.description = description embed.set_thumbnail( url= "https://cdn.cloudflare.steamstatic.com/apps/dota2/images/blog/play/dota_logo.png" ) if image_meta_tag: embed.set_image(url=image_meta_tag["content"]) messageables = [] guildinfos = botdata.guildinfo_list() for guildinfo in guildinfos: if guildinfo.dotapatchchannel is not None: channel = self.bot.get_channel(guildinfo.dotapatchchannel) if channel is not None: messageables.append(channel) else: print( f"couldn't find channel {guildinfo.dotapatchchannel} when announcing dota patches" ) userinfos = botdata.userinfo_list() for userinfo in userinfos: if userinfo.dmdotapatch: user = self.bot.get_user(userinfo.discord) if user is not None: messageables.append(user) else: print( f"couldn't find user {userinfo.discord} when announcing dota patches" ) tasks = [] for messageable in messageables: tasks.append(messageable.send(embed=embed)) bundler = AsyncBundler(tasks) print("waiting for dota patch bundle to complete") await bundler.wait() print("dota patch bundle completed") await self.send_owner("__Dota Patch Sent!__\n" + bundler.status_as_string())
async def _highest_mythic_plus(ctx, *args): await ctx.trigger_typing() res = await Blizzard.get_guild_members(config.get("default_realm"), config.get("default_guild")) if res is None: await ctx.send( embed=discord.Embed(title="실행 오류", color=COLOR.RED, description="길드원 목록을 불러오는 데 실패했습니다.")) return None members = list() for member in res["members"]: if member["character"]["level"] >= MAX_LEVEL: members.append(member["character"]["name"]) if len(members) == 0: await ctx.send(embed=discord.Embed( title="실행 오류", color=COLOR.RED, description="길드원 중 {}레벨 캐릭터가 없습니다.".format(MAX_LEVEL))) return None tasks = list() for m in members: tasks.append(Raider.get_character(config.get("default_realm"), m)) mythic_members = await asyncio.gather(*tasks) classified = {"15단 이상": [], "10단 이상": [], "10단 미만": [], "쐐기 간 적 없음": []} for m in mythic_members: if m is None: continue if m["mythic_plus_scores_by_season"][0]["scores"]["all"] > 0: if len(m["mythic_plus_weekly_highest_level_runs"]) > 0: best_run = m["mythic_plus_weekly_highest_level_runs"][0] if best_run["mythic_level"] >= 15: classified["15단 이상"].append("{}({})".format( m["name"], best_run["mythic_level"])) elif best_run["mythic_level"] >= 10: classified["10단 이상"].append("{}({})".format( m["name"], best_run["mythic_level"])) else: classified["10단 미만"].append("{}({})".format( m["name"], best_run["mythic_level"])) else: classified["쐐기 간 적 없음"].append(m["name"]) period = await Blizzard.get_mythic_keystone_period() period_s = "" if period is not None: start = datetime.fromtimestamp(int( period["start_timestamp"] / 1000)) + timedelta(hours=9) end = datetime.fromtimestamp(int( period["end_timestamp"] / 1000)) + timedelta(hours=9) period_s = "{} ~ {}".format(start.strftime("%Y-%m-%d %H:%M"), end.strftime("%Y-%m-%d %H:%M")) embed = discord.Embed(title="이번주 길드원 쐐기 던전 현황", color=COLOR.BLUE, description=period_s) for i in classified: if len(classified[i]) > 0: embed.add_field(name=i, value=", ".join(classified[i])) embed.set_footer(text="* 이번 시즌에 쐐기 던전을 간 적이 있는 캐릭터만 표시됩니다.") await ctx.send(embed=embed) return embed
async def write_usage_data(self): start = time() values = [] total_messages = 0 for guild_id in self.xp_cache.keys(): for user_id, value in self.xp_cache[guild_id].items(): values.append((int(guild_id), int(user_id), value["bot"], value["xp"], value["messages"])) total_messages += value["messages"] self.average_mps.append(total_messages) if len(self.average_mps) > 10: self.average_mps = self.average_mps[1:] tasks = [] if values: currenthour = arrow.utcnow().hour for activity_table in [ "user_activity", "user_activity_day", "user_activity_week", "user_activity_month", ]: tasks.append( self.bot.db.executemany( f""" INSERT INTO {activity_table} (guild_id, user_id, is_bot, h{currenthour}, message_count) VALUES (%s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE h{currenthour} = h{currenthour} + VALUES(h{currenthour}), message_count = message_count + VALUES(message_count) """, values, )) self.xp_cache = {} unicode_emoji_values = [] for guild_id in self.emoji_usage_cache["unicode"].keys(): for user_id in self.emoji_usage_cache["unicode"][guild_id].keys(): for emoji_name, value in self.emoji_usage_cache["unicode"][ guild_id][user_id].items(): unicode_emoji_values.append( (int(guild_id), int(user_id), emoji_name, value)) if unicode_emoji_values: tasks.append( self.bot.db.executemany( """ INSERT INTO unicode_emoji_usage (guild_id, user_id, emoji_name, uses) VALUES (%s, %s, %s, %s) ON DUPLICATE KEY UPDATE uses = uses + VALUES(uses) """, unicode_emoji_values, )) self.emoji_usage_cache["unicode"] = {} custom_emoji_values = [] for guild_id in self.emoji_usage_cache["custom"].keys(): for user_id in self.emoji_usage_cache["custom"][guild_id].keys(): for emoji_id, value in self.emoji_usage_cache["custom"][ guild_id][user_id].items(): custom_emoji_values.append( (int(guild_id), int(user_id), value["name"], emoji_id, value["uses"])) if custom_emoji_values: tasks.append( self.bot.db.executemany( """ INSERT INTO custom_emoji_usage (guild_id, user_id, emoji_name, emoji_id, uses) VALUES (%s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE uses = uses + VALUES(uses) """, custom_emoji_values, )) self.emoji_usage_cache["custom"] = {} await asyncio.gather(*tasks) logger.info( f"Inserted {total_messages} messages in {time()-start:.3f}s, " f"{len(self.average_mps)*2} min average: {(sum(self.average_mps) / len(self.average_mps))/(60*2):.2f} msg/s" )
async def on_message(message): if message.author == client.user: return if message.author.id in Moderators: if message.content.startswith('>roles'): embed = discord.Embed(title="Identity Roles", color=0xd52d00) embed.add_field( name="React to this message to add roles", value= "\U0001F1E6 <@&699897962431512658>\n\U0001F1E7 <@&699897995600068608>\n\U0001F1E8 <@&699898033013260308>\n\U0001F1E9 <@&699898067859538011>\n\U0001F1EA <@&699898104333205564>\n\U0001F1EB <@&699898136818090084>\n\U0001F1EC <@&699898190178287637>\n\U0001F1ED <@&813435393290141727>\nIf any roles are missing, ping a <@&699812268145115137> and they'll assign them for you", inline=False) await message.channel.send(embed=embed) time.sleep(0.5) embed = discord.Embed(title="Orientation Roles", color=0xef7528) embed.add_field( name="React to this message to add roles", value= "\U0001F1E6 <@&699889869845168198>\n\U0001F1E7 <@&699889907212222535>\n\U0001F1E8 <@&699889940787494983>\n\U0001F1E9 <@&699889980067151882>\n\U0001F1EA <@&699890018658811964>\n\U0001F1EB <@&699890085969264680>\n\U0001F1EC <@&699890061025738752>\n\U0001F1ED <@&699890443718230016>\n\U0001F1EE <@&699890469810995260>\n\U0001F1EF <@&699890503944241202>\n\U0001F1F0 <@&699890541071958036>\n\U0001F1F1 <@&699890607317057590>\n\U0001F1F2 <@&699890646877601823>\n\U0001F1F3 <@&699890683066056744>\n\U0001F1F4 <@&712744400169730100>\n\U0001F1F5 <@&721393433276710961>\n\U0001F1F6 <@&734468187411710043>\n\U0001F1F7 <@&782389274833322004>\n\U0001F1F8 <@&813434723124117524>\n\U0001F1F9 <@&813434024378761227>\n\U0001F1FA <@&813435267889365073>\n\U0001F1FB <@&828024612495032372>\n\U0001F1FC <@&835195868432957510>\n\U0001F1FD <@&799339270745096202>\n\U0001F1FE <@&799339405755547739>\nIf your orientation(s) aren't listed, ping a <@&699812268145115137> and they'll assign them for you", inline=False) await message.channel.send(embed=embed) await message.channel.send("** **") time.sleep(1) embed = discord.Embed(title="Gender Identity Roles", color=0xff9b57) embed.add_field( name="React to this message to add roles", value= "\U0001F1E6 <@&699885677256507402>\n\U0001F1E7 <@&699885751239835679>\n\U0001F1E8 <@&699885789042966558>\n\U0001F1E9 <@&699885851366391868>\n\U0001F1EA <@&699885897264398366>\n\U0001F1EB <@&699885931439849473>\n\U0001F1EC <@&699886147811147786>\n\U0001F1ED <@&699886187548246057>\n\U0001F1EE <@&699886232691408976>\n\U0001F1EF <@&699886265587335168>\n\U0001F1F0 <@&766684553594667039>\n\U0001F1F1 <@&766971952719855618>\n\U0001F1F2 <@&766684282545504256>\n\U0001F1F3 <@&766684436582367322>\n\U0001F1F4 <@&768930342937165864>\n\U0001F1F5 <@&766685258879860777>\n\U0001F1F6 <@&771966534062833664>\n\U0001F1F7 <@&788565283220488212>\n\U0001F1F8 <@&805548468697432114>\n\U0001F1F9 <@&799357832326938674>If your gender(s) aren't listed, ping a <@&699812268145115137> and they'll assign them for you", inline=False) await message.channel.send(embed=embed) time.sleep(1) embed = discord.Embed(title="Pronoun Roles", color=0xfffffe) embed.add_field( name="React to this message to add roles", value= "\U0001F1E6 <@&699878300842983525>\n\U0001F1E7 <@&699878594280816641>\n\U0001F1E8 <@&699878350583365714>\n\U0001F1E9 <@&699880196706140190>\n\U0001F1EA <@&699878641500291072>\n\U0001F1EB <@&699878743463952474>\n\U0001F1EC <@&699878808546705468>\n\U0001F1ED <@&699878835457359934>\n\U0001F1EE <@&699878930999541780>\n\U0001F1EF <@&699878974033231912>\n\U0001F1F0 <@&700133237216772196>\n\U0001F1F1 <@&709408864012992553>\n\U0001F1F2 <@&700131772469477436>\n\U0001F1F3 <@&774456768771391498>\n\U0001F1F4 <@&801439760844718110>\n\U0001F1F5 <@&804814388833681429>\n\U0001F1F6 <@&808464718893154314>\n\U0001F1F7 <@&811745182339956747>\nIf your pronouns aren't listed, ping a <@&699812268145115137> and they'll assign them for you", inline=False) await message.channel.send(embed=embed) time.sleep(1) embed = discord.Embed(title="Colour Roles", color=0xd162a4) embed.add_field( name="React to this message to add roles", value= "\U0001F1E6 <@&699844873439805441>\n\U0001F1E7 <@&699844894960648222>\n\U0001F1E8 <@&699844915479445624>\n\U0001F1E9 <@&699844922261635123>\n\U0001F1EA <@&699845102473969755>\n\U0001F1EB <@&699845122891841587>\n\U0001F1EC <@&699845182991892570>\n\U0001F1ED <@&699845206312484995>\n\U0001F1EE <@&699847500517081128>\n\U0001F1EF <@&699848093960634418>\n\U0001F1F0 <@&699848846762704947>\n\U0001F1F1 <@&699849297717362698>\n\U0001F1F2 <@&699849584461086763>\n\U0001F1F3 <@&699850050427289620>\n\U0001F1F4 <@&699850191175548969>\n\U0001F1F5 <@&806993825431420958> changes daily", inline=False) await message.channel.send(embed=embed) time.sleep(1) embed = discord.Embed(title="Continent Roles", color=0xb55690) embed.add_field( name="React to this message to add roles", value= "\U0001F1E6 <@&795313728777355305>\n\U0001F1E7 <@&795314377849962497>\n\U0001F1E8 <@&795313849452068894>\n\U0001F1E9 <@&795314609938235423>\n\U0001F1EA <@&795313953857077249>\n\U0001F1EB <@&795314238385946676>\n\U0001F1EC <@&795314313102491648>", inline=False) await message.channel.send(embed=embed) time.sleep(1) embed = discord.Embed(title="Misc Roles", color=0xa30262) embed.add_field( name="React to this message to add roles", value= "\U0001F1E6 <@&711239368504770600>\n\U0001F1E7 <@&711239278956642337>\n\U0001F1E8 <@&711239427158179930>\n\U0001F1E9 <@&733610027432149022> for the <#777143414533390346> channel\n\U0001F1EA <@&762736076586352690>\n\U0001F1EB <@&734945400699617342>\n\U0001F1EC <@&768905152807567452> for the <#768904994367602718> channel\n\U0001F1ED <@&818880535899537438> for the <#818878492665970688> channel\n\nYou need to have been in the server for a few hours to assign the <@&733610027432149022> role", inline=False) await message.channel.send(embed=embed) if message.content.startswith('>rules'): embed = discord.Embed(title="Rules", color=0xf1c40f) x = 0 rules = storage_reader("data/rules.csv") for i in rules[0]: embed.add_field(name=numbermotes[x] + rules[0][x], value=rules[1][x] + "\n\n", inline=False) x += 1 await message.channel.send(embed=embed) time.sleep(1) embed = discord.Embed(title="Info", color=0xf1c40f) x = 0 info = storage_reader("data/info.csv") for i in info[0]: embed.add_field(name=info[0][x], value=info[1][x] + "\n\n", inline=False) x += 1 await message.channel.send(embed=embed) if message.content.startswith('>changelog'): embed = discord.Embed(title="Changelog", color=0xf1c40f) embed.add_field( name="1️⃣ bot and roles channel fixed and ready for use <3", value= "does what it says on the tin, also i think erin is p cool", inline=False) await message.channel.send(embed=embed) if message.content.startswith('>botinfo'): embed = discord.Embed(title="Command Info", color=0xf1c40f) embed.add_field( name="⚠️ Spoiler command ⚠️", value= "Send this command:\n```yaml\n>spoiler ExampleText```Along with your image file to spoiler the image.\nThis command allows mobile users to spoiler images.", inline=False) await message.channel.send(embed=embed) if message.content.startswith('>spoiler'): try: x = message.content x = x.split(">spoiler")[1] try: x = x.lstrip() except: pass except IndexError: x = "See User Message" y = "cw: " + x + "\nAuthor: " + message.author.name file = message.attachments[0] file.filename = f"SPOILER_{file.filename}" spoiler = await file.to_file() await message.channel.send(y, file=spoiler) await message.delete() if message.attachments: tasks = [] scanfiles = [] for i in message.attachments: if i.filename.endswith(tuple(embedformats)): break else: scanfiles.append(i) else: for i in scanfiles: tasks.append(virus_scan(i)) scanresults = await asyncio.gather(*tasks) statuscolour = 0x79b553 status = "\n\u2705 **Probably Safe** \u2705\n" for index, item in enumerate(scanresults): if item.last_analysis_stats.get("malicious") > 1: statuscolour = 0xde2a42 status = "\n\U0001F6D1 **Potentially Malicious** \U0001F6D1\n" break elif item.last_analysis_stats.get("suspicious") > 1: statuscolour = 0xffcd4c status = "\n\u26a0\ufe0f **Suspicious** \u26a0\ufe0f\n" break embed = discord.Embed(title="Malware Scan", color=statuscolour) for index, item in enumerate(scanresults): embed.add_field( name=scanfiles[index].filename + "\n", value=status + "\nMalware: " + str(item.last_analysis_stats.get("malicious")) + " \U0001F6D1 Suspicious: " + str(item.last_analysis_stats.get("suspicious")) + " \u26a0\ufe0f Clean: " + str(item.last_analysis_stats.get("undetected")) + " \u2705\n[Virustotal results 🔗](https://www.virustotal.com/gui/file/" + str(item.id) + "/detection)", inline=False) await message.reply(embed=embed, mention_author=False)
async def checkHighlights(self, msg: discord.Message): """Background listener to check if a highlight has been triggered.""" if not isinstance(msg.channel, discord.TextChannel): return user = msg.author # Prevent bots from triggering your highlight word. if user.bot: return guildConfig = self.config.guild(msg.channel.guild) # Prevent messages in a denylist channel from triggering highlight words if msg.channel.id in await guildConfig.get_attr(KEY_CHANNEL_DENYLIST )(): self.logger.debug("Message is from a denylist channel, returning") return # Don't send notification for filtered messages if not self.wordFilter: self.wordFilter = self.bot.get_cog("WordFilter") elif await self.wordFilter.containsFilterableWords(msg): return tasks = [] activeMessages = [] try: async for message in msg.channel.history(limit=50, before=msg): activeMessages.append(message) except (aiohttp.ClientResponseError, aiohttp.ServerDisconnectedError): self.logger.error("Error within discord.py!", exc_info=True) # Iterate through every user's words on the guild, and notify all highlights guildData = await self.config.all_members(msg.guild) for currentUserId, data in guildData.items(): self.logger.debug("User ID: %s", currentUserId) # Handle case where user is no longer in the guild of interest. hiliteUser = msg.guild.get_member(currentUserId) if not hiliteUser: continue # Handle case where user cannot see the channel. perms = msg.channel.permissions_for(hiliteUser) if not perms.read_messages: continue # Handle case where message was sent in a user denied channel if msg.channel.id in data[KEY_CHANNEL_IGNORE]: continue # Handle case where user was at-mentioned. if currentUserId in [atMention.id for atMention in msg.mentions]: continue # Handle case where message author has been blacklisted by the user. if KEY_BLACKLIST in data.keys( ) and msg.author.id in data[KEY_BLACKLIST]: continue # Handle case where message contains words being ignored by the user. isWordIgnored = False if KEY_WORDS_IGNORE in data.keys(): self.logger.debug("Checking for ignored words") for word in data[KEY_WORDS_IGNORE]: if self._isWordMatch(word, msg.content): self.logger.debug( "%s is being ignored, skipping user.", word) isWordIgnored = True break if isWordIgnored: continue # If we reach this point, then the message is not from a user that has been # blacklisted, nor does the message contain any ignored words, so now we can # check to see if there is anything that needs to be highlighted. for word in data[KEY_WORDS]: active = _isActive(currentUserId, msg, activeMessages) match = self._isWordMatch(word, msg.content) timeout = data[KEY_TIMEOUT] if KEY_TIMEOUT in data.keys( ) else DEFAULT_TIMEOUT triggeredRecently = self._triggeredRecently( msg, currentUserId, timeout) if match and not active and not triggeredRecently and user.id != currentUserId: self._triggeredUpdate(msg.channel, hiliteUser, msg.created_at) tasks.append(self._notifyUser(hiliteUser, msg, word)) await asyncio.gather(*tasks) # pylint: disable=no-member