async def bot_welcome(self, member, guild): bot_welcome = await self.config.guild(guild).BOTS_MSG() bot_role = await self.config.guild(guild).BOTS_ROLE() msg = bot_welcome or rand_choice(await self.config.guild(guild).GREETING()) channel = await self.get_welcome_channel(member, guild) is_embed = await self.config.guild(guild).EMBED() if bot_role: try: role = guild.get_role(bot_role) await member.add_roles(role) except Exception: log.error(_("welcome.py: unable to add a role. ") + f"{bot_role} {member}", exc_info=True) else: log.debug( _("welcome.py: added ") + str(role) + _(" role to ") + _("bot, ") + str(member)) if bot_welcome: # finally, welcome them if is_embed and channel.permissions_for(guild.me).embed_links: em = await self.make_embed(member, guild, msg, False) if await self.config.guild(guild).EMBED_DATA.mention(): await channel.send(member.mention, embed=em) else: await channel.send(embed=em) else: await channel.send( filter_mass_mentions(await self.convert_parms( member, guild, bot_welcome, False)))
async def type_message(destination: discord.abc.Messageable, content: str, **kwargs) -> discord.Message: """Simulate typing and sending a message to a destination. Will send a typing indicator, wait a variable amount of time based on the length of the text (to simulate typing speed), then send the message. """ content = common_filters.filter_mass_mentions(content) content = common_filters.filter_urls(content) content = common_filters.filter_various_mentions(content) try: async with destination.typing(): await asyncio.sleep(len(content) * 0.01) return await destination.send(content=content, **kwargs) except discord.HTTPException: pass # Not allowed to send messages to this destination (or, sending the message failed)
async def process_message(self, rift, message, destination): if isinstance(destination, discord.Message): send_coro = destination.edit else: send_coro = destination.send channel = ( message.author if isinstance(message.channel, discord.DMChannel) else message.channel ) send = channel == rift.source destination = rift.destination if send else rift.source author = message.author me = ( destination.dm_channel.me if isinstance(destination, discord.User) else destination.guild.me ) is_owner = await self.bot.is_owner(author) author_perms = self.permissions(destination, author, is_owner) bot_perms = self.permissions(destination, me) content = message.content if not is_owner: if not author_perms.administrator: content = common_filters.filter_invites(content) if not author_perms.mention_everyone: content = common_filters.filter_mass_mentions(content) attachments = message.attachments files = [] embed = None if attachments and author_perms.attach_files and bot_perms.attach_files: overs = await asyncio.gather(*(self.save_attach(file, files) for file in attachments)) overs = list(filter(bool, overs)) if overs: if bot_perms.embed_links: embed = await self.get_embed(destination, overs) else: content += ( "\n\n" + _("Attachments:") + "\n" + "\n".join(f"({self.xbytes(a.size)}) {a.url}" for a in attachments) ) if not any((content, files, embed)): raise RiftError(_("No content to send.")) if not is_owner or not send: content = f"{author}: {content}" return await send_coro(content=content, files=files, embed=embed)
async def process_message(self, rift, message, destination): if isinstance(destination, discord.Message): send_coro = destination.edit else: send_coro = destination.send channel = ( message.author if isinstance(message.channel, discord.DMChannel) else message.channel ) send = channel == rift.source destination = rift.destination if send else rift.source source = rift.source if send else rift.destination author = message.author me = ( destination.dm_channel.me if isinstance(destination, discord.User) else destination.guild.me ) is_owner = await self.bot.is_owner(author) author_perms = self.permissions(destination, author, is_owner) bot_perms = self.permissions(destination, me) content = message.content if not is_owner: if not author_perms.administrator: content = common_filters.filter_invites(content) if not author_perms.mention_everyone: content = common_filters.filter_mass_mentions(content) attachments = message.attachments files = [] embed = None if attachments and author_perms.attach_files and bot_perms.attach_files: overs = await asyncio.gather(*(self.save_attach(file, files) for file in attachments)) overs = list(filter(bool, overs)) if overs: content += ( "\n\n" + _("Attachments:") + "\n" + "\n".join(f"({self.xbytes(a.size)}) {a.url}" for a in attachments) ) if not any((content, files, embed)): raise RiftError(_("No content to send.")) msg_embed = await self.create_message_embed(ctx=message, source=source, content=content, files=attachments) return await send_coro(embed=msg_embed)
async def send_testing_msg(self, ctx: commands.Context, bot: bool = False, msg: str = None, leave: bool = False) -> None: # log.info(leave) default_greeting = "Welcome {0.name} to {1.name}!" default_goodbye = "See you later {0.name}!" default_bot_msg = "Hello {0.name}, fellow bot!" guild = ctx.message.guild guild_settings = await self.config.guild(guild).get_raw() # log.info(guild_settings) channel = guild.get_channel(guild_settings["CHANNEL"]) if leave: channel = guild.get_channel(guild_settings["LEAVE_CHANNEL"]) rand_msg = msg or rand_choice(guild_settings["GREETING"]) if leave: rand_msg = msg or rand_choice(guild_settings["GOODBYE"]) if bot: rand_msg = guild_settings["BOTS_MSG"] if rand_msg is None and msg is None: rand_msg = default_greeting if rand_msg is None and bot: rand_msg = default_bot_msg if rand_msg is None and leave: rand_msg = default_goodbye is_welcome = not leave is_embed = guild_settings["EMBED"] member = ctx.message.author whisper_settings = guild_settings["WHISPER"] if channel is None and whisper_settings not in ["BOTH", True]: msg = _( "I can't find the specified channel. It might have been deleted." ) await ctx.send(msg) return if channel is None: await ctx.send(_("`Sending a testing message to ") + "` DM") else: await ctx.send( _("`Sending a testing message to ") + "`{0.mention}".format(channel)) if not bot and guild_settings["WHISPER"]: if is_embed: em = await self.make_embed(member, guild, rand_msg, is_welcome) await ctx.author.send(embed=em, delete_after=60) else: await ctx.author.send(await self.convert_parms( member, guild, rand_msg, is_welcome), delete_after=60) if guild_settings["WHISPER"] != "BOTH": return if bot or whisper_settings is not True: if not channel: return if guild_settings["GROUPED"]: member = [ctx.author, ctx.me] if is_embed and channel.permissions_for(guild.me).embed_links: em = await self.make_embed(member, guild, rand_msg, is_welcome) if await self.config.guild(guild).EMBED_DATA.mention(): if guild_settings["GROUPED"]: await channel.send(humanize_list( [m.mention for m in member]), embed=em, delete_after=60) else: await channel.send(member.mention, embed=em, delete_after=60) else: await channel.send(embed=em, delete_after=60) else: await channel.send( filter_mass_mentions(await self.convert_parms( member, guild, rand_msg, is_welcome)), delete_after=60, )
async def on_member_remove(self, member: discord.Member) -> None: guild = member.guild if not await self.config.guild(guild).LEAVE_ON(): return if guild is None: return if version_info >= VersionInfo.from_str("3.4.0"): if await self.bot.cog_disabled_in_guild(self, guild): return if await self.config.guild(guild).GROUPED(): if guild.id not in self.joined: self.joined[guild.id] = [] if member in self.joined[guild.id]: self.joined[guild.id].remove(member) return bot_welcome = member.bot and await self.config.guild(guild).BOTS_MSG() msg = bot_welcome or rand_choice(await self.config.guild(guild).GOODBYE()) is_embed = await self.config.guild(guild).EMBED() delete_after = await self.config.guild(guild).DELETE_AFTER_GOODBYE() save_msg = None # grab the welcome channel # guild_settings = await self.config.guild(guild).guild_settings() channel = self.bot.get_channel( await self.config.guild(guild).LEAVE_CHANNEL()) if channel is None: # complain even if only whisper log.info( _("welcome.py: Channel not found in {guild}. It was most likely deleted." ).format(guild=guild)) return # we can stop here if await self.config.guild(guild).DELETE_PREVIOUS_GOODBYE(): old_id = await self.config.guild(guild).LAST_GOODBYE() if channel is not None and old_id is not None: try: old_msg = await channel.fetch_message(old_id) await old_msg.delete() except discord.errors.NotFound: log.debug(_("Message not found for deletion.")) pass except discord.errors.Forbidden: await self.config.guild(guild).DELETE_PREVIOUS_GOODBYE.set( False) if not channel.permissions_for(guild.me).send_messages: log.info(_("Permissions Error in {guild}")) return elif not member.bot: if is_embed and channel.permissions_for(guild.me).embed_links: em = await self.make_embed(member, guild, msg, False) if await self.config.guild(guild).EMBED_DATA.mention(): save_msg = await channel.send(member.mention, embed=em, delete_after=delete_after) else: save_msg = await channel.send(embed=em, delete_after=delete_after) else: save_msg = await channel.send( filter_mass_mentions(await self.convert_parms( member, guild, msg, False)), delete_after=delete_after, ) if save_msg is not None: await self.config.guild(guild).LAST_GOODBYE.set(save_msg.id)
async def send_member_join(self, member: Union[discord.Member, List[discord.Member]], guild: discord.Guild) -> None: only_whisper = await self.config.guild(guild).WHISPER() is True channel = await self.get_welcome_channel(member, guild) msg = rand_choice(await self.config.guild(guild).GREETING()) is_embed = await self.config.guild(guild).EMBED() delete_after = await self.config.guild(guild).DELETE_AFTER_GREETING() save_msg = None if await self.config.guild(guild).DELETE_PREVIOUS_GREETING(): old_id = await self.config.guild(guild).LAST_GREETING() if channel is not None and old_id is not None: try: old_msg = await channel.fetch_message(old_id) await old_msg.delete() except discord.errors.NotFound: pass except discord.errors.Forbidden: await self.config.guild( guild).DELETE_PREVIOUS_GREETING.set(False) # whisper the user if needed if not await self.config.guild(guild).GROUPED(): if await self.config.guild(guild).WHISPER(): try: if is_embed: em = await self.make_embed(member, guild, msg, True) if await self.config.guild(guild).EMBED_DATA.mention(): await member.send(member.mention, embed=em) # type: ignore else: await member.send(embed=em) # type: ignore else: await member.send(await self.convert_parms( member, guild, msg, False)) # type: ignore except discord.errors.Forbidden: log.info( _("welcome.py: unable to whisper a user. Probably " "doesn't want to be PM'd") + str(member)) except Exception: log.error("error sending member join message", exc_info=True) if only_whisper: return if not channel: return if is_embed and channel.permissions_for(guild.me).embed_links: em = await self.make_embed(member, guild, msg, True) if await self.config.guild(guild).EMBED_DATA.mention(): if await self.config.guild(guild).GROUPED(): members = cast(List[discord.Member], member) save_msg = await channel.send( humanize_list([m.mention for m in members]), embed=em, delete_after=delete_after, ) else: member = cast(discord.Member, member) save_msg = await channel.send(str(member.mention), embed=em, delete_after=delete_after) else: save_msg = await channel.send(embed=em, delete_after=delete_after) else: save_msg = await channel.send( filter_mass_mentions(await self.convert_parms( member, guild, msg, True)), delete_after=delete_after, ) if save_msg is not None: await self.config.guild(guild).LAST_GREETING.set(save_msg.id)
async def translate_message( self, message: discord.Message, flag: str, reacted_user: Optional[discord.Member] = None) -> None: guild = cast(discord.Guild, message.guild) channel = cast(discord.TextChannel, message.channel) if message.id in self.cache["cooldown_translations"]: if str(flag) in self.cache["cooldown_translations"][ message.id]["past_flags"]: return if not self.cache["cooldown_translations"][message.id]["multiple"]: return if time.time() < self.cache["cooldown_translations"][ message.id]["wait"]: delete_after = ( self.cache["cooldown_translations"][message.id]["wait"] - time.time()) await channel.send(_("You're translating too many messages!"), delete_after=delete_after) return if message.embeds != []: if message.embeds[0].description: to_translate = cast(str, message.embeds[0].description) else: to_translate = message.clean_content num_emojis = 0 for reaction in message.reactions: if reaction.emoji == str(flag): num_emojis = reaction.count if num_emojis > 1: return target = FLAGS[str(flag)]["code"] try: detected_lang = await self.detect_language(to_translate) await self.add_detect(guild) except GoogleTranslateAPIError: return except Exception: log.exception("Error detecting language") return original_lang = detected_lang[0][0]["language"] if target == original_lang: return try: translated_text = filter_mass_mentions(await self.translate_text( original_lang, target, to_translate)) await self.add_requests(guild, to_translate) except Exception: log.exception("Error translating message") return if not translated_text: return author = message.author from_lang = detected_lang[0][0]["language"].upper() to_lang = target.upper() if from_lang == to_lang: # don't post anything if the detected language is the same return translation = (translated_text, from_lang, to_lang) if message.id not in self.cache["cooldown_translations"]: if not self.cache["cooldown"]: self.cache["cooldown"] = await self.config.cooldown() cooldown = deepcopy(self.cache["cooldown"]) else: cooldown = self.cache["cooldown_translations"][message.id] cooldown["wait"] = time.time() + cooldown["timeout"] cooldown["past_flags"].append(str(flag)) self.cache["cooldown_translations"][message.id] = cooldown if channel.permissions_for(guild.me).embed_links: em = await self.translation_embed(author, translation, reacted_user) translated_msg = await channel.send(embed=em) else: msg = _("{author} said:\n{translated_text}").format( author=author, translate_text=translated_text) translated_msg = await channel.send(msg) if not cooldown["multiple"]: self.cache["translations"].append(translated_msg.id)