Advertisement
Guest User

Untitled

a guest
Mar 19th, 2019
149
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.41 KB | None | 0 0
  1. """A Cog that controls the search and reply functionality of the bot.
  2.  
  3. Also is responsible for saving messages sent to the bot
  4. """
  5.  
  6. import typing
  7. from datetime import datetime
  8.  
  9. import discord
  10. from discord.ext import commands
  11. from discord.ext.commands.context import Context
  12. from sqlalchemy import func
  13.  
  14. from core import logging
  15. from models import Message, make_session
  16. from tools import methods
  17.  
  18.  
  19. class ReplyCog(commands.Cog, name="Reply Commands"):
  20.     """ReplyCog"""
  21.  
  22.     def __init__(self, bot):
  23.         self.bot = bot
  24.  
  25.     @commands.command(usage="[<channel> <target_user>] <search term> [〰 <response>]")
  26.     async def reply(self, ctx: Context, channel: typing.Optional[discord.TextChannel],
  27.                     target_user: typing.Optional[discord.Member], *, user_input):
  28.         """ Searches the past messages in a server for the text after the command.
  29.  
  30.        Place a 〰 (:wavy-dash:) between your search string and your response to activate the response functionality.
  31.  
  32.        channel: (Optional) The #channel_name for a text channel. Will only search in that channel.
  33.        user: (Optional) The @user_name for a user. Will only search for that user.
  34.        search term: (Required) The part of a message to search for.
  35.        response: (Optional) Your response to append to the end of the message. Make sure to add the 〰 to deliniate.
  36.        """
  37.         # Null Check is used to tell if a hit was found must be initialized here
  38.         new_message: Message = None
  39.  
  40.         search_terms, response = self.split_message(user_input)
  41.  
  42.         new_message = self.database_search(ctx, channel, target_user, search_terms)
  43.  
  44.         # Catch the failure to find a message before other things are requested of new_message, avoiding null refrences
  45.         if not new_message:
  46.             await ctx.send("Failed to find the requested message! Please try again with less specific search terms. "
  47.                            "\nYou may also not be able to view the channel that the message was from.")
  48.             return
  49.  
  50.         # Had issues getting the children of new_message, this reduced them
  51.         new_message_content = new_message.message_content
  52.         new_message_sender_id = new_message.message_sender
  53.         new_message_channel_id = new_message.message_channel
  54.         new_message_sent_time = new_message.message_sent_time
  55.         new_message_id = new_message.message_id
  56.  
  57.         await self.send_response(ctx, response, channel, new_message_content, new_message_sender_id,
  58.                                  new_message_channel_id, new_message_sent_time, new_message_id)
  59.  
  60.         await methods.delete_invocation(ctx)
  61.  
  62.     @commands.Cog.listener()
  63.     async def on_message(self, message):
  64.         """Saves a message sent on a server the bot is in.
  65.  
  66.        Will not save if it is a command for this bot or if the message is from this bot
  67.        """
  68.         skip_saving = False
  69.  
  70.         if message.author == self.bot.user:
  71.             skip_saving = True
  72.         if 'r!' in message.content:
  73.             skip_saving = True
  74.  
  75.         if not skip_saving:
  76.             session = make_session()
  77.             if message.clean_content != '':
  78.                 current_message = Message(message_content=message.clean_content, message_sender=message.author.id,
  79.                                           message_channel=message.channel.id, message_server=message.guild.id,
  80.                                           message_id=message.id)
  81.                 session.add(current_message)
  82.             session.commit()
  83.             session.close()
  84.             Message.prune_db(50000)
  85.  
  86.     async def send_original_message(self, ctx, message_content, message_sender, message_sent_time,
  87.                                     message_id):
  88.         """Sends a message as an embed, includes the channel it was sent from"""
  89.         sender = ctx.guild.get_member(message_sender)
  90.         message = await self.get_message(ctx, message_id)
  91.         embed = discord.Embed(colour=sender.color, description="**" + message_content + "**",
  92.                               timestamp=message_sent_time)
  93.         embed.set_author(name=sender.display_name, icon_url=sender.avatar_url,
  94.                          url=message.jump_url)
  95.         embed.add_field(name="‍ ", value="*Sent in: " + message.channel.mention + "*")
  96.         # embed.set_footer(text="ReplyBot", icon_url=self.bot.user.avatar_url)
  97.  
  98.         await ctx.send(embed=embed)
  99.  
  100.     async def send_original_message_no_channel(self, ctx, message_content, message_sender, message_sent_time,
  101.                                                message_id):
  102.         """Sends a message as an embed, doesn't include the channel it was sent from"""
  103.         sender = ctx.guild.get_member(message_sender)
  104.         message = await self.get_message(ctx, message_id)
  105.         embed = discord.Embed(colour=sender.color, description="**" + message_content + "**",
  106.                               timestamp=message_sent_time)
  107.         embed.set_author(name=sender.display_name, icon_url=sender.avatar_url,
  108.                          url=message.jump_url)
  109.         # embed.set_footer(text="ReplyBot", icon_url=self.bot.user.avatar_url)
  110.  
  111.         await ctx.send(embed=embed)
  112.  
  113.     async def get_message(self, ctx, message_id: int):
  114.         """Gets the message from an ID"""
  115.         message = await ctx.get_message(message_id)
  116.         return message
  117.  
  118.     def split_message(self, user_input):
  119.         """Splits up the inserted text on the :wavy-dash: character"""
  120.         # noinspection PyBroadException
  121.         try:
  122.             search_terms, response = user_input.split("〰", 1)
  123.             logging.debug(search_terms + "::" + response)
  124.         except:
  125.             search_terms = user_input
  126.             response = None
  127.             logging.debug(search_terms + "::nothing")
  128.         return search_terms, response
  129.  
  130.     def database_search(self, ctx: Context, channel: typing.Optional[discord.TextChannel],
  131.                         target_user: typing.Optional[discord.Member], search_terms: str) -> discord.message.Message:
  132.         """Searches through the database for the search for the requested message.
  133.  
  134.        :param ctx: The Context of the message
  135.        :param channel: The channel that the desired message is in. Is optional
  136.        :param target_user: The user that sent the desired message. Is optional
  137.        :param search_terms: The main text that the user is searching for
  138.        :return message: The message found. Returns None if no message is found
  139.        """
  140.         session = make_session()
  141.         new_message = None
  142.  
  143.         if channel is not None and target_user is not None:
  144.             if search_terms != "":
  145.                 new_message = session.query(Message
  146.                                             # func.lower() insures that case isn't an issue
  147.                                             ).filter(
  148.                     func.lower(Message.message_content).contains(func.lower(search_terms)),
  149.                     Message.message_channel == channel.id,
  150.                     Message.message_sender == target_user.id,
  151.                     Message.message_server == ctx.guild.id
  152.                 ).order_by(Message.message_sent_time.desc()).first()
  153.             else:
  154.                 new_message = session.query(Message
  155.                                             ).filter(Message.message_channel == channel.id,
  156.                                                      Message.message_sender == target_user.id,
  157.                                                      Message.message_server == ctx.guild.id
  158.                                                      ).order_by(Message.message_sent_time.desc()).first()
  159.         elif channel is not None:
  160.             if search_terms != "":
  161.                 new_message = session.query(Message
  162.                                             ).filter(
  163.                     func.lower(Message.message_content).contains(func.lower(search_terms)),
  164.                     Message.message_channel == channel.id,
  165.                     Message.message_server == ctx.guild.id
  166.                 ).order_by(Message.message_sent_time.desc()).first()
  167.             else:
  168.                 new_message = session.query(Message
  169.                                             ).filter(Message.message_channel == channel.id,
  170.                                                      Message.message_server == ctx.guild.id
  171.                                                      ).order_by(Message.message_sent_time.desc()).first()
  172.         elif target_user is not None:
  173.             if search_terms != "":
  174.                 new_message = session.query(Message
  175.                                             ).filter(
  176.                     func.lower(Message.message_content).contains(func.lower(search_terms)),
  177.                     Message.message_sender == target_user.id,
  178.                     Message.message_server == ctx.guild.id
  179.                 ).order_by(Message.message_sent_time.desc()).first()
  180.             else:
  181.                 new_message = session.query(Message
  182.                                             ).filter(Message.message_sender == target_user.id,
  183.                                                      Message.message_server == ctx.guild.id
  184.                                                      ).order_by(Message.message_sent_time.desc()).first()
  185.         else:
  186.             if search_terms != '':
  187.                 new_message = session.query(Message
  188.                                             ).filter(
  189.                     func.lower(Message.message_content).contains(func.lower(search_terms)),
  190.                     Message.message_server == ctx.guild.id
  191.                 ).order_by(Message.message_sent_time.desc()).first()
  192.             else:
  193.                 new_message = session.query(Message
  194.                                             ).filter(Message.message_server == ctx.guild.id
  195.                                                      ).order_by(Message.message_sent_time.desc()).first()
  196.  
  197.         session.close()
  198.         return new_message
  199.  
  200.     async def send_response(self, ctx: Context, response, channel, original_content, original_sender_id,
  201.                             original_channel_id, original_sent_time, original_message_id):
  202.         """Checks that the requester has the read_messages permission on the requested channel.
  203.  
  204.        If so, sends message. If not, sends error to the user
  205.        """
  206.         # For unit testing
  207.  
  208.         # Checks to make sure the requester has perms to see the channel the message is in
  209.         if ctx.message.author.permissions_in(self.bot.get_channel(original_channel_id)).read_messages:
  210.             logging.debug(methods.clean_string_light(original_content))
  211.             if response is not None:  # Check to see if the message has an attached response
  212.                 if channel is not None and channel.id != original_channel_id:  # Print with channel name included if pulled from another channel
  213.                     await self.send_original_message(ctx, original_content, original_sender_id, original_sent_time,
  214.                                                      original_message_id)
  215.                     await ctx.send("To which " + ctx.message.author.mention + " says:")
  216.                     await self.send_original_message_no_channel(ctx, response, ctx.message.author.id,
  217.                                                                 datetime.utcnow(), ctx.message.id)
  218.                 else:  # Print normally with a response
  219.                     await self.send_original_message_no_channel(ctx, original_content, original_sender_id,
  220.                                                                 original_sent_time, original_message_id)
  221.                     await ctx.send("To which " + ctx.message.author.mention + " says:")
  222.                     await self.send_original_message_no_channel(ctx, response, ctx.message.author.id,
  223.                                                                 datetime.utcnow(), ctx.message.id)
  224.             else:
  225.                 await self.send_original_message_no_channel(ctx, original_content, original_sender_id,
  226.                                                             original_sent_time, original_message_id)
  227.         else:
  228.             logging.info("User had insufficient permissions to access that text")
  229.             await ctx.send("Failed to find the requested message! Please try again with less specific search terms. "
  230.                            "\nYou may also not be able to view the channel that the message was from.")
  231.  
  232.  
  233. def setup(bot):
  234.     bot.add_cog(ReplyCog(bot))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement