async def send( self, message: discord.Message, destination: typing.Union[discord.TextChannel, discord.DMChannel, discord.User, discord.Member] = None, from_mod: bool = False, note: bool = False, anonymous: bool = False, plain: bool = False, persistent_note: bool = False, thread_creation: bool = False, ) -> None: self.bot.loop.create_task( self._restart_close_timer()) # Start or restart thread auto close if self.close_task is not None: # cancel closing if a thread message is sent. self.bot.loop.create_task(self.cancel_closure()) self.bot.loop.create_task( self.channel.send(embed=discord.Embed( color=self.bot.error_color, description="Scheduled close has been cancelled! ❌", ))) if not self.ready: await self.wait_until_ready() if not from_mod and not note: self.bot.loop.create_task( self.bot.api.append_log(message, channel_id=self.channel.id)) destination = destination or self.channel author = message.author embed = discord.Embed(description=message.content) if self.bot.config["show_timestamp"]: embed.timestamp = message.created_at system_avatar_url = "https://cdn.discordapp.com/attachments/809115390385848340/822195746572861480/pol-wumpus.png" if not note: if anonymous and from_mod and not isinstance( destination, discord.TextChannel): # Anonymously sending to the user. tag = self.bot.config["mod_tag"] if tag is None: tag = str(author.top_role) name = self.bot.config["anon_username"] if name is None: name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: avatar_url = self.bot.guild.icon_url embed.set_author( name=name, icon_url=avatar_url, url= f"https://discordapp.com/channels/{self.bot.guild.id}#{message.id}", ) else: # Normal message name = str(author) avatar_url = author.avatar_url embed.set_author( name=name, icon_url=avatar_url, url= f"https://discordapp.com/users/{author.id}#{message.id}", ) else: # Special note messages embed.set_author( name= f"{'Persistent' if persistent_note else ''} Note ({author.name})", icon_url=system_avatar_url, url=f"https://discordapp.com/users/{author.id}#{message.id}", ) ext = [(a.url, a.filename, False) for a in message.attachments] images = [] attachments = [] for attachment in ext: if is_image_url(attachment[0]): images.append(attachment) else: attachments.append(attachment) image_urls = re.findall( r"http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", message.content, ) image_urls = [(is_image_url(url, convert_size=False), None, False) for url in image_urls if is_image_url(url, convert_size=False)] images.extend(image_urls) images.extend(( str(i.image_url) if isinstance(i.image_url, discord.Asset) else i. image_url, f"{i.name} Sticker", True, ) for i in message.stickers) embedded_image = False prioritize_uploads = any(i[1] is not None for i in images) additional_images = [] additional_count = 1 for url, filename, is_sticker in images: if (not prioritize_uploads or ((url is None or is_image_url(url)) and filename)) and not embedded_image: if url is not None: embed.set_image(url=url) if filename: if is_sticker: if url is None: description = "Unable to retrieve sticker image" else: description = "\u200b" embed.add_field(name=filename, value=description) else: embed.add_field(name="Image", value=f"[{filename}]({url})") embedded_image = True else: if note: color = self.bot.main_color elif from_mod: color = self.bot.mod_color else: color = self.bot.recipient_color img_embed = discord.Embed(color=color) if url is not None: img_embed.set_image(url=url) img_embed.url = url if filename is not None: img_embed.title = filename img_embed.set_footer( text=f"Additional Image Upload ({additional_count})") img_embed.timestamp = message.created_at additional_images.append(destination.send(embed=img_embed)) additional_count += 1 file_upload_count = 1 for url, filename, _ in attachments: embed.add_field(name=f"File upload ({file_upload_count})", value=f"[{filename}]({url})") file_upload_count += 1 if from_mod: embed.colour = self.bot.mod_color # Anonymous reply sent in thread channel if anonymous and isinstance(destination, discord.TextChannel): embed.set_footer(text="Anonymous Reply - Staff") # Normal messages elif not anonymous: mod_tag = self.bot.config["mod_tag"] if mod_tag is None: mod_tag = str(message.author.top_role) embed.set_footer(text=mod_tag) # Normal messages else: embed.set_footer(text=self.bot.config["anon_tag"]) elif note: embed.colour = self.bot.main_color else: embed.set_footer(text="User") embed.colour = self.bot.recipient_color if (from_mod or note) and not thread_creation: delete_message = not bool(message.attachments) if delete_message and destination == self.channel: try: await message.delete() except Exception as e: logger.warning("Cannot delete message: %s.", e) if (from_mod and self.bot.config["dm_disabled"] == DMDisabled.ALL_THREADS and destination != self.channel): logger.info("Sending a message to %s when DM disabled is set.", self.recipient) try: await destination.trigger_typing() except discord.NotFound: logger.warning("Channel not found.") raise if not from_mod and not note: mentions = self.get_notifications() else: mentions = None if plain: if from_mod and not isinstance(destination, discord.TextChannel): # Plain to user if embed.footer.text: plain_message = f"**({embed.footer.text}) " else: plain_message = "**" plain_message += f"{embed.author.name}:** {embed.description}" files = [] for i in embed.fields: if "Image" in i.name: async with self.bot.session.get( i.field[i.field.find("http"):-1]) as resp: stream = io.BytesIO(await resp.read()) files.append(discord.File(stream)) msg = await destination.send(plain_message, files=files) else: # Plain to mods embed.set_footer(text="[Plain Message] " + embed.footer.text) msg = await destination.send(mentions, embed=embed) else: msg = await destination.send(mentions, embed=embed) if additional_images: self.ready = False await asyncio.gather(*additional_images) self.ready = True return msg
async def send(self, message, destination=None, from_mod=False, note=False, anonymous=False): if self.close_task is not None: # cancel closing if a thread message is sent. await self.cancel_closure() await self.channel.send(embed=discord.Embed( color=discord.Color.red(), description='Scheduled close has been cancelled.')) if not from_mod and not note: await self.bot.api.append_log(message, self.channel.id) if not self.ready: await self.wait_until_ready() destination = destination or self.channel author = message.author embed = discord.Embed(description=message.content, timestamp=message.created_at) system_avatar_url = 'https://discordapp.com/assets/' \ 'f78426a064bc9dd24847519259bc42af.png' if not note: if anonymous and from_mod and \ not isinstance(destination, discord.TextChannel): # Anonymously sending to the user. tag = self.bot.config.get('mod_tag', str(message.author.top_role)) name = self.bot.config.get('anon_username', tag) avatar_url = self.bot.config.get('anon_avatar_url', self.bot.guild.icon_url) else: # Normal message name = str(author) avatar_url = author.avatar_url embed.set_author(name=name, icon_url=avatar_url, url=message.jump_url) else: # Special note messages embed.set_author(name=f'Note ({author.name})', icon_url=system_avatar_url, url=message.jump_url) delete_message = not bool(message.attachments) attachments = [(a.url, a.filename) for a in message.attachments] images = [x for x in attachments if is_image_url(*x)] attachments = [x for x in attachments if not is_image_url(*x)] image_links = [ (link, None) for link in re.findall(r'(https?://[^\s]+)', message.content) ] image_links = [x for x in image_links if is_image_url(*x)] images.extend(image_links) embedded_image = False prioritize_uploads = any(i[1] is not None for i in images) additional_images = [] additional_count = 1 for att in images: # TODO: Logic needs review if not prioritize_uploads or (is_image_url(*att) and not embedded_image and att[1]): embed.set_image(url=att[0]) embedded_image = True elif att[1] is not None: if note: color = discord.Color.blurple() elif from_mod: color = self.bot.mod_color else: color = self.bot.recipient_color img_embed = discord.Embed(color=color) img_embed.set_image(url=att[0]) img_embed.set_footer( text=f'Additional Image Upload ({additional_count})') img_embed.timestamp = message.created_at additional_images.append(destination.send(embed=img_embed)) additional_count += 1 file_upload_count = 1 for att in attachments: embed.add_field(name=f'File upload ({file_upload_count})', value=f'[{att[1]}]({att[0]})') file_upload_count += 1 if from_mod: # noinspection PyUnresolvedReferences,PyDunderSlots embed.color = self.bot.mod_color # pylint: disable=E0237 # Anonymous reply sent in thread channel if anonymous and isinstance(destination, discord.TextChannel): embed.set_footer(text='Anonymous Reply') # Normal messages elif not anonymous: tag = self.bot.config.get('mod_tag', str(message.author.top_role)) embed.set_footer(text=tag) # Normal messages else: embed.set_footer( text=self.bot.config.get('anon_tag', 'Response')) elif note: # noinspection PyUnresolvedReferences,PyDunderSlots embed.color = discord.Color.blurple() # pylint: disable=E0237 else: embed.set_footer(text=f'Recipient') # noinspection PyUnresolvedReferences,PyDunderSlots embed.color = self.bot.recipient_color # pylint: disable=E0237 await destination.trigger_typing() if not from_mod: mentions = self.get_notifications() else: mentions = None await destination.send(mentions, embed=embed) if additional_images: self.ready = False await asyncio.gather(*additional_images) self.ready = True if delete_message: try: await message.delete() except discord.HTTPException: pass
async def send( self, message: discord.Message, destination: typing.Union[discord.TextChannel, discord.DMChannel, discord.User, discord.Member] = None, from_mod: bool = False, note: bool = False, anonymous: bool = False, ) -> None: self.bot.loop.create_task( self._restart_close_timer()) # Start or restart thread auto close if self.close_task is not None: # cancel closing if a thread message is sent. self.bot.loop.create_task(self.cancel_closure()) self.bot.loop.create_task( self.channel.send(embed=discord.Embed( color=self.bot.error_color, description="Se canceló el cierre programado.", ))) if not self.ready: await self.wait_until_ready() if not from_mod and not note: self.bot.loop.create_task( self.bot.api.append_log(message, channel_id=self.channel.id)) destination = destination or self.channel author = message.author embed = discord.Embed(description=message.content, timestamp=message.created_at) system_avatar_url = "https://discordapp.com/assets/f78426a064bc9dd24847519259bc42af.png" if not note: if anonymous and from_mod and not isinstance( destination, discord.TextChannel): # Anonymously sending to the user. tag = self.bot.config["mod_tag"] if tag is None: tag = str(author.top_role) name = self.bot.config["anon_username"] if name is None: name = tag avatar_url = self.bot.config["anon_avatar_url"] if avatar_url is None: avatar_url = self.bot.guild.icon_url embed.set_author( name=name, icon_url=avatar_url, url= f"https://discordapp.com/channels/{self.bot.guild.id}#{message.id}", ) else: # Normal message name = str(author) avatar_url = author.avatar_url embed.set_author( name=name, icon_url=avatar_url, url= f"https://discordapp.com/users/{author.id}#{message.id}", ) else: # Special note messages embed.set_author( name=f"Note ({author.name})", icon_url=system_avatar_url, url=f"https://discordapp.com/users/{author.id}#{message.id}", ) ext = [(a.url, a.filename) for a in message.attachments] images = [] attachments = [] for attachment in ext: if is_image_url(attachment[0]): images.append(attachment) else: attachments.append(attachment) image_urls = re.findall( r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", message.content, ) image_urls = [(url, None) for url in image_urls if is_image_url(url)] images.extend(image_urls) embedded_image = False prioritize_uploads = any(i[1] is not None for i in images) additional_images = [] additional_count = 1 for url, filename in images: if not prioritize_uploads or (is_image_url(url) and not embedded_image and filename): embed.set_image(url=url) if filename: embed.add_field(name="Image", value=f"[{filename}]({url})") embedded_image = True elif filename is not None: if note: color = self.bot.main_color elif from_mod: color = self.bot.mod_color else: color = self.bot.recipient_color img_embed = discord.Embed(color=color) img_embed.set_image(url=url) img_embed.title = filename img_embed.url = url img_embed.set_footer( text=f"Additional Image Upload ({additional_count})") img_embed.timestamp = message.created_at additional_images.append(destination.send(embed=img_embed)) additional_count += 1 file_upload_count = 1 for url, filename in attachments: embed.add_field(name=f"File upload ({file_upload_count})", value=f"[{filename}]({url})") file_upload_count += 1 if from_mod: embed.colour = self.bot.mod_color # Anonymous reply sent in thread channel if anonymous and isinstance(destination, discord.TextChannel): embed.set_footer(text="Anonymous Reply") # Normal messages elif not anonymous: mod_tag = self.bot.config["mod_tag"] if mod_tag is None: mod_tag = str(message.author.top_role) embed.set_footer(text=mod_tag) # Normal messages else: embed.set_footer(text=self.bot.config["anon_tag"]) elif note: embed.colour = self.bot.main_color else: embed.set_footer(text=f"Message ID: {message.id}") embed.colour = self.bot.recipient_color if from_mod or note: delete_message = not bool(message.attachments) if delete_message and destination == self.channel: try: await message.delete() except Exception as e: logger.warning("Cannot delete message: %s.", e) if from_mod and self.bot.config[ "dm_disabled"] == 2 and destination != self.channel: logger.info("Sending a message to %s when DM disabled is set.", self.recipient) try: await destination.trigger_typing() except discord.NotFound: logger.warning("Channel not found.") raise if not from_mod and not note: mentions = self.get_notifications() else: mentions = None msg = await destination.send(mentions, embed=embed) if additional_images: self.ready = False await asyncio.gather(*additional_images) self.ready = True return msg
async def send( self, message: discord.Message, destination: typing.Union[discord.TextChannel, discord.DMChannel, discord.User, discord.Member] = None, from_mod: bool = False, note: bool = False, anonymous: bool = False, ) -> None: if self.close_task is not None: # cancel closing if a thread message is sent. self.bot.loop.create_task(self.cancel_closure()) self.bot.loop.create_task( self.channel.send(embed=discord.Embed( color=discord.Color.red(), description="Scheduled close has been cancelled.", ))) if not self.ready: await self.wait_until_ready() if not from_mod and not note: self.bot.loop.create_task( self.bot.api.append_log(message, self.channel.id)) destination = destination or self.channel author = message.author embed = discord.Embed(description=message.content, timestamp=message.created_at) system_avatar_url = ( "https://discordapp.com/assets/f78426a064bc9dd24847519259bc42af.png" ) if not note: if (anonymous and from_mod and not isinstance(destination, discord.TextChannel)): # Anonymously sending to the user. tag = self.bot.config.get("mod_tag", str(message.author.top_role)) name = self.bot.config.get("anon_username", tag) avatar_url = self.bot.config.get("anon_avatar_url", self.bot.guild.icon_url) else: # Normal message name = str(author) avatar_url = author.avatar_url embed.set_author(name=name, icon_url=avatar_url, url=message.jump_url) else: # Special note messages embed.set_author( name=f"Note ({author.name})", icon_url=system_avatar_url, url=message.jump_url, ) delete_message = not bool(message.attachments) attachments = [(a.url, a.filename) for a in message.attachments] images = [x for x in attachments if is_image_url(*x)] attachments = [x for x in attachments if not is_image_url(*x)] image_links = [(link, None) for link in re.findall( r"https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)", message.content, )] image_links = [x for x in image_links if is_image_url(*x)] images.extend(image_links) embedded_image = False prioritize_uploads = any(i[1] is not None for i in images) additional_images = [] additional_count = 1 for att in images: if not prioritize_uploads or (is_image_url(*att) and not embedded_image and att[1]): embed.set_image(url=att[0]) if att[1]: embed.add_field(name="Image", value=f"[{att[1]}]({att[0]})") embedded_image = True elif att[1] is not None: if note: color = discord.Color.blurple() elif from_mod: color = self.bot.mod_color else: color = self.bot.recipient_color img_embed = discord.Embed(color=color) img_embed.set_image(url=att[0]) img_embed.title = att[1] img_embed.url = att[0] img_embed.set_footer( text=f"Additional Image Upload ({additional_count})") img_embed.timestamp = message.created_at additional_images.append(destination.send(embed=img_embed)) additional_count += 1 file_upload_count = 1 for att in attachments: embed.add_field(name=f"File upload ({file_upload_count})", value=f"[{att[1]}]({att[0]})") file_upload_count += 1 if from_mod: # noinspection PyUnresolvedReferences,PyDunderSlots embed.color = self.bot.mod_color # pylint: disable=E0237 # Anonymous reply sent in thread channel if anonymous and isinstance(destination, discord.TextChannel): embed.set_footer(text="Anonymous Reply") # Normal messages elif not anonymous: tag = self.bot.config.get("mod_tag", str(message.author.top_role)) embed.set_footer(text=tag) # Normal messages else: embed.set_footer( text=self.bot.config.get("anon_tag", "Response")) elif note: # noinspection PyUnresolvedReferences,PyDunderSlots embed.color = discord.Color.blurple() # pylint: disable=E0237 else: embed.set_footer(text=f"Recipient") # noinspection PyUnresolvedReferences,PyDunderSlots embed.color = self.bot.recipient_color # pylint: disable=E0237 await destination.trigger_typing() if not from_mod and not note: mentions = self.get_notifications() else: mentions = None _msg = await destination.send(mentions, embed=embed) if additional_images: self.ready = False await asyncio.gather(*additional_images) self.ready = True if delete_message: self.bot.loop.create_task(ignore(message.delete())) return _msg