1
0

commands.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import discord
  2. import urllib
  3. from typing import List, Tuple
  4. import myanimebot.utils as utils
  5. import myanimebot.globals as globals
  6. def build_info_cmd_message(users, server, channels, filters : List[utils.Service]) -> str:
  7. ''' Build the corresponding message for the info command '''
  8. registered_channel = globals.client.get_channel(int(channels[0]["channel"]))
  9. # Store users
  10. mal_users = []
  11. anilist_users = []
  12. for user in users:
  13. # If user is part of the server, add it to the message
  14. if str(server.id) in user['servers'].split(','):
  15. try:
  16. user_service = utils.Service.from_str(user["service"])
  17. if user_service == utils.Service.MAL:
  18. mal_users.append(user[globals.DB_USER_NAME])
  19. elif user_service == utils.Service.ANILIST:
  20. anilist_users.append(user[globals.DB_USER_NAME])
  21. except NotImplementedError:
  22. pass # Nothing to do here
  23. if not mal_users and not anilist_users:
  24. return "No users registered on this server. Try to add one."
  25. else:
  26. message = 'Registered user(s) on **{}**\n\n'.format(server)
  27. if mal_users: # If not empty
  28. # Don't print if there is filters and MAL is not in them
  29. if not filters or (filters and utils.Service.MAL in filters):
  30. message += '**MyAnimeList** users:\n'
  31. message += '```{}```\n'.format(', '.join(mal_users))
  32. if anilist_users: # If not empty
  33. # Don't print if there is filters and MAL is not in them
  34. if not filters or (filters and utils.Service.ANILIST in filters):
  35. message += '**AniList** users:\n'
  36. message += '```{}```\n'.format(', '.join(anilist_users))
  37. message += 'Assigned channel : **{}**'.format(registered_channel)
  38. return message
  39. def get_service_filters_list(filters : str) -> List[utils.Service]:
  40. ''' Creates and returns a service filter list from a comma-separated string '''
  41. filters_list = []
  42. for filter in filters.split(','):
  43. try:
  44. filters_list.append(utils.Service.from_str(filter))
  45. except NotImplementedError:
  46. pass # Ignore incorrect filter
  47. return filters_list
  48. def check_user_name_validity(user_name: str, service : utils.Service) -> Tuple[bool, str]:
  49. """ Check if user_name exists on a specific service.
  50. Returns:
  51. - bool: True if user_name exists
  52. - str: Error string if the user does not exist
  53. """
  54. if service == utils.Service.MAL:
  55. try:
  56. # Ping user profile to check validity
  57. urllib.request.urlopen('{}{}'.format(globals.MAL_PROFILE_URL, user_name))
  58. except urllib.error.HTTPError as e:
  59. if (e.code == 404): # URL profile not found
  60. return False, "User **{}** doesn't exist on MyAnimeList!".format(user_name)
  61. else:
  62. globals.logger.warning("HTTP Code {} while trying to add user '{}' and checking its validity.".format(e.code, user_name))
  63. return False, "An error occured when we checked this username on MyAnimeList, maybe the website is down?"
  64. elif service == utils.Service.ANILIST:
  65. is_user_valid = anilist.check_username_validity(user_name)
  66. if is_user_valid == False:
  67. globals.logger.warning("No results returned while trying to add user '{}' and checking its validity.".format(user_name))
  68. return False, "User **{}** doesn't exist on AniList!".format(user_name)
  69. return True, None
  70. async def add_user_cmd(words, message):
  71. ''' Processes the command "add" and add a user to fetch the data for '''
  72. # Check if command is valid
  73. if len(words) != 4:
  74. if (len(words) < 4):
  75. return await message.channel.send("Usage: {} add **{}**/**{}** **username**".format(globals.prefix, globals.SERVICE_MAL, globals.SERVICE_ANILIST))
  76. return await message.channel.send("Too many arguments! You have to specify only one username.")
  77. try:
  78. service = utils.Service.from_str(words[2])
  79. except NotImplementedError:
  80. return await message.channel.send('Incorrect service. Use **"{}"** or **"{}"** for example'.format(globals.SERVICE_MAL, globals.SERVICE_ANILIST))
  81. user = words[3]
  82. server_id = str(message.guild.id)
  83. if(len(user) > 14):
  84. return await message.channel.send("Username too long!")
  85. try:
  86. # Check user validity
  87. is_valid, error_string = check_user_name_validity(user, service)
  88. if is_valid == False:
  89. return await message.channel.send(error_string)
  90. # Get user's servers
  91. user_servers = utils.get_user_servers(user, service)
  92. # User not present in database
  93. if user_servers is None:
  94. utils.insert_user_into_db(user, service, server_id)
  95. return await message.channel.send("**{}** added to the database for the server **{}**.".format(user, str(message.guild)))
  96. else: # User present in database
  97. is_server_present = server_id in user_servers.split(',')
  98. if is_server_present == True: # The user already has registered this server
  99. return await message.channel.send("User **{}** is already registered in our database for this server!".format(user))
  100. else:
  101. new_servers = '{},{}'.format(user_servers, server_id)
  102. utils.update_user_servers_db(user, service, new_servers)
  103. return await message.channel.send("**{}** added to the database for the server **{}**.".format(user, str(message.guild)))
  104. except Exception as e:
  105. globals.logger.warning("Error while adding user '{}' on server '{}': {}".format(user, message.guild, str(e)))
  106. return await message.channel.send("An unknown error occured while addind this user, the error has been logged.")
  107. async def delete_user_cmd(words, message):
  108. ''' Processes the command "delete" and remove a registered user '''
  109. # Check if command is valid
  110. if len(words) != 4:
  111. if (len(words) < 4):
  112. return await message.channel.send("Usage: {} delete **{}**/**{}** **username**".format(globals.prefix, globals.SERVICE_MAL, globals.SERVICE_ANILIST))
  113. return await message.channel.send("Too many arguments! You have to specify only one username.")
  114. try:
  115. service = utils.Service.from_str(words[2])
  116. except NotImplementedError:
  117. return await message.channel.send('Incorrect service. Use **"{}"** or **"{}"** for example'.format(globals.SERVICE_MAL, globals.SERVICE_ANILIST))
  118. user = words[3]
  119. server_id = str(message.guild.id)
  120. user_servers = utils.get_user_servers(user, service)
  121. # If user is not present in the database
  122. if user_servers is None:
  123. return await message.channel.send("The user **" + user + "** is not in our database for this server!")
  124. # Else if present, update the servers for this user
  125. srv_string = utils.remove_server_from_servers(server_id, user_servers)
  126. if srv_string is None: # Server not present in the user's servers
  127. return await message.channel.send("The user **" + user + "** is not in our database for this server!")
  128. if srv_string == "":
  129. utils.delete_user_from_db(user, service)
  130. else:
  131. utils.update_user_servers_db(user, service, srv_string)
  132. return await message.channel.send("**" + user + "** deleted from the database for this server.")
  133. async def info_cmd(message, words):
  134. ''' Processes the command "info" and sends a message '''
  135. # Get filters if available
  136. filters = []
  137. if (len(words) >= 3): # If filters are specified
  138. filters = get_service_filters_list(words[2])
  139. server = message.guild
  140. if utils.is_server_in_db(server.id) == False:
  141. await message.channel.send("The server **{}** is not in our database.".format(server))
  142. else:
  143. users = utils.get_users()
  144. channels = utils.get_channels(server.id)
  145. if channels is None:
  146. await message.channel.send("No channel assigned for this bot on this server.")
  147. else:
  148. await message.channel.send(build_info_cmd_message(users, server, channels, filters))
  149. async def ping_cmd(channel):
  150. ''' Responds to ping command '''
  151. await channel.send("pong")
  152. async def about_cmd(channel):
  153. ''' Responds to about command with a brief description of this bot '''
  154. title = "MyAnimeBot version {} by Penta & lulu".format(globals.VERSION)
  155. description = """MyAnimeBot checks MyAnimeList and Anilist profiles for specified users, and send a message for every new activities found.
  156. More help with the **{} help** command.
  157. Check our GitHub page for more informations: https://github.com/Penta/MyAnimeBot
  158. """.format(globals.prefix)
  159. await channel.send(embed=discord.Embed(colour=0x777777, title=title, description=description).set_thumbnail(url=globals.iconBot))
  160. async def help_cmd(channel):
  161. ''' Responds to help command '''
  162. embed = discord.Embed(title="***MyAnimeBot Commands***", colour=0xEED000)
  163. embed.add_field(name="`here`", value="Register this channel. The bot will send new activities on registered channels.")
  164. embed.add_field(name="`stop`", value="Un-register this channel. The bot will now stop sending new activities for this channel.")
  165. embed.add_field(name="`info [mal|ani]`", value="Get the registered users for this server. Users can be filtered by specifying a service.")
  166. embed.add_field(name="`add {mal|ani} <user>`", value="Register a user for a specific service.\nEx: `add mal MyUser`")
  167. embed.add_field(name="`delete {mal|ani} <user>`", value="Remove a user for a specific service.\nEx: `delete ani MyUser`")
  168. embed.add_field(name="`role <@discord_role>`", value="Specify a role that is able to manage the bot.\nEx: `role @Moderator`, `role @everyone`")
  169. embed.add_field(name="`top`", value="Show statistics for this server.")
  170. embed.add_field(name="`ping`", value="Ping the bot.")
  171. embed.add_field(name="`about`", value="Get some information about this bot")
  172. await channel.send(embed=embed)