You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

264 lines
9.7KB

  1. import datetime
  2. import time
  3. import checks
  4. import discord
  5. from config.server_config import ServerConfig
  6. from discord.ext.commands import bot, group
  7. class Admin():
  8. """
  9. Admin Commands for those admins
  10. """
  11. def __init__(self, Bot):
  12. self.bot = Bot
  13. self.slow_mode = False
  14. self.slow_mode_channels = {}
  15. self.users = {}
  16. self.con = ServerConfig()
  17. self.servers = self.con.servers
  18. async def on_message(self, message):
  19. # Slow Mode Code
  20. channel = message.channel
  21. author = message.author
  22. if not author == self.bot.user:
  23. if self.slow_mode and channel.id in self.slow_mode_channels:
  24. if author.id not in self.users[channel.id]:
  25. # If user hasn't sent a message in this channel after slow mode was turned on
  26. self.users[channel.id][author.id] = message.timestamp
  27. else:
  28. # Else, check when their last message was and if time is smaller than the timer, delete the message.
  29. timer = datetime.timedelta(seconds=self.slow_mode_channels[channel.id])
  30. if message.timestamp - self.users[channel.id][author.id] < timer:
  31. await self.bot.delete_message(message)
  32. else:
  33. self.users[message.channel.id][author.id] = message.timestamp
  34. else:
  35. pass
  36. @checks.not_pm()
  37. @checks.is_admin_or_mod()
  38. @bot.command(pass_context=True)
  39. async def slowmode(self, ctx, time):
  40. if time == "off" and self.slow_mode: # Turn Slow Mode off
  41. self.slow_mode = False
  42. self.slow_mode_channels.pop(ctx.message.channel.id)
  43. self.users.pop(ctx.message.channel.id)
  44. return await self.bot.say("Slowmode off")
  45. elif time.isdigit() and not self.slow_mode: # Turn Slow Mode On
  46. self.users[ctx.message.channel.id] = {}
  47. self.slow_mode_channels[ctx.message.channel.id] = int(time)
  48. self.slow_mode = True
  49. return await self.bot.say("Slowmode on :snail: ({} seconds)".format(time))
  50. elif time.isdigit and self.slow_mode: # Change value of Slow Mode timer
  51. self.slow_mode_channels[ctx.message.channel.id] = int(time)
  52. return await self.bot.say("Slowmode set to :snail: ({} seconds)".format(time))
  53. else:
  54. pass
  55. @checks.is_admin_or_mod()
  56. @bot.command(pass_context=True, enabled=False)
  57. async def emojiuse(self, ctx, emoji, *args):
  58. # TODO: Add check that emoji is an emoji
  59. # TODO: Disable so like when we go to 1.3 this isn't live cause it needs more work and it needs to be completed already
  60. # The way forward is clearly put the given emoji in and treat it as a list of emojis,
  61. # if all emojis, then generate the list. Allows for more than one emoji to be analysed. Works better for larger servers/
  62. # Flag Parsing
  63. if "-v" in args:
  64. verbose = True
  65. else:
  66. verbose = False
  67. if "-w" in args or emoji == "-w": # Second check just in case user just puts ";emojiuse -w"
  68. all_emojis = True
  69. else:
  70. all_emojis = False
  71. # Functions
  72. def sum(usage):
  73. amount = 0
  74. for channel in usage.values():
  75. amount += channel
  76. return amount
  77. def use_by_day(amount):
  78. useperday = amount / 30
  79. useperday = "{0:.2f}".format(useperday)
  80. return useperday
  81. def verbose_output(usage):
  82. output = ""
  83. for channel in usage:
  84. channel = self.bot.get_channel(channel) # Convert channel from ID to channel object to get name
  85. output = output + "{}: {} \n".format(channel.name, usage[channel.id])
  86. return output
  87. async def count_uses():
  88. usage = {}
  89. for channel in ctx.message.server.channels:
  90. if channel.type == discord.ChannelType.text: # Only looks at server's text channels
  91. x = 0
  92. async for message in self.bot.logs_from(channel, limit=1000000, after=datetime.datetime.now() + datetime.timedelta(-30)):
  93. if str(emoji) in message.content:
  94. x += 1
  95. usage[channel.id] = x
  96. print(str(emoji) + "HAS {} AMOUNT OF USES IN {}".format(x, str(channel)))
  97. else:
  98. pass
  99. print("EMOJI WAS USED {} TOTAL TIMES".format(sum(usage)))
  100. return usage
  101. async def count_all_emoji():
  102. whitelist = [":yeetpride:",":yeet:", ":transgendercat:", ":thonkspin:", ":thonkegg:", ":ThinkPride:", ":thinkinggaysounds:", ":thatsgoodnews", ":pansexualcat:", ":nonbinarycat: ", ":kappa:", ":icantputpunctuationinemojinames:", ":hellothere:", ":agendercat:", ":Hedgeok:", ":extremethink:", ":donttryit:", ":cutie:", ":catappa:", ":boots:", ":awoo:", ":anotherhappylanding:", ":angrygay:"]
  103. usage = {}
  104. for emote in ctx.message.server.emojis:
  105. name = ":{}:".format(emote.name)
  106. if name in whitelist:
  107. usage[emote.id] = 0
  108. for channel in ctx.message.server.channels: # TODO: ADD COUNTING BY CHANNEL
  109. if channel.type == discord.ChannelType.text: # Only looks at server's text channels
  110. async for message in self.bot.logs_from(channel, limit=1000000, after=datetime.datetime.now() + datetime.timedelta(-30)):
  111. for emote in ctx.message.server.emojis:
  112. if str(emote) in message.content and ":{}:".format(emote.name) in whitelist:
  113. usage[emote.id] += 1
  114. print("{} found in message {}".format(str(emote), message.id))
  115. return usage
  116. # Command
  117. await self.bot.say("Warning! This command may take upto 15 minutes to process. Please do no spam me. I am working.", delete_after=20)
  118. await self.bot.send_typing(ctx.message.channel)
  119. if all_emojis:
  120. emoji_usage = await count_all_emoji()
  121. em = discord.Embed(colour=0xDEADBF)
  122. for emoji in emoji_usage:
  123. emoji_obj = discord.utils.get(ctx.message.server.emojis, id=emoji)
  124. amount = emoji_usage[emoji]
  125. useperday = use_by_day(amount)
  126. em.add_field(name=str(emoji_obj), value="Amount Used: {}\nUse/Day: {}".format(amount, useperday), inline=False)
  127. return await self.bot.say(content="Below is a report of all custom emoji on this server and how many times they have been used in the previous 30 days. This includes a usage/day ratio.", embed=em)
  128. else:
  129. usage = await count_uses()
  130. amount = sum(usage)
  131. useperday = use_by_day(amount)
  132. if verbose:
  133. output = verbose_output(usage)
  134. output_em = discord.Embed(description=output, colour=0xDEADBF)
  135. return await self.bot.say(content="{} has been used {} time(s) in the last month. That's {}/day. Here is the break down per channel.".format(emoji, amount, useperday), embed=output_em)
  136. else: # Non-verbose output
  137. return await self.bot.say("{} has been used {} time(s) in the last month. That's {}/day.".format(emoji, amount, useperday))
  138. @checks.is_admin_or_mod()
  139. @group(pass_context=True)
  140. async def warn(self, ctx):
  141. if ctx.invoked_subcommand is None:
  142. return await self.bot.say('Missing Argument')
  143. @warn.command(pass_context=True)
  144. async def add(self, ctx, user: discord.User = None, *, warning = ""):
  145. # Warning in the config is a dictionary of user ids. The user ids are equal to a list of dictionaries.
  146. self.servers = self.con.load_config()
  147. warning_limit = 2
  148. id = ctx.message.server.id
  149. warning_dict = {
  150. "warned-by": ctx.message.author.id,
  151. "date": time.time(),
  152. "warning": warning
  153. }
  154. if not user.id in self.servers[id]["warnings"]:
  155. self.servers[id]["warnings"][user.id] = []
  156. self.servers[id]["warnings"][user.id].append(warning_dict)
  157. self.con.update_config(self.servers)
  158. amount_warnings = len(self.servers[id]["warnings"][user.id])
  159. if amount_warnings > warning_limit:
  160. await self.bot.send_message(ctx.message.author,"{} has been reported {} time(s). This is a reminder that this is over the set limit of {}.".format(
  161. user.name+"#"+user.discriminator, amount_warnings, warning_limit))
  162. return await self.bot.say("Reported {}.".format(user.name+"#"+user.discriminator))
  163. @warn.command(pass_context=True)
  164. async def list(self, ctx, *, user: discord.User = None):
  165. await self.bot.send_typing(ctx.message.channel)
  166. if user == None:
  167. output = ""
  168. for user in self.servers[ctx.message.server.id]["warnings"]:
  169. user_obj = await self.bot.get_user_info(user)
  170. output += "{}#{}: {} Warning(s)\n".format(user_obj.name, user_obj.discriminator, len(self.servers[ctx.message.server.id]["warnings"][user]))
  171. return await self.bot.say(output)
  172. if not user.id in self.servers[ctx.message.server.id]["warnings"]:
  173. return await self.bot.say("This user doesn't have any warning on record.")
  174. em = discord.Embed(title="Warnings for {}".format(user.name+"#"+user.discriminator), colour=0XDEADBF)
  175. em.set_thumbnail(url=user.avatar_url)
  176. x = 1
  177. userlist = self.servers[ctx.message.server.id]["warnings"][user.id]
  178. for warning in userlist:
  179. try:
  180. warnuser = await self.bot.get_user_info(warning["warned-by"])
  181. warned_by = warnuser.name + "#" + warnuser.discriminator
  182. except:
  183. warned_by = warning["warned-by"]
  184. date = datetime.datetime.fromtimestamp(warning["date"]).strftime('%c')
  185. warn_reason = warning["warning"]
  186. em.add_field(name="Warning %s"%x, value="Warned by: {}\nTime: {}\nReason: {}".format(warned_by, date, warn_reason))
  187. x += 1
  188. return await self.bot.say(embed=em)
  189. @warn.command(pass_context=True)
  190. async def remove(self, ctx, user: discord.User = None, index = None):
  191. self.servers = self.con.load_config()
  192. if index:
  193. try:
  194. index = int(index)
  195. index -= 1
  196. self.servers[ctx.message.server.id]["warnings"][user.id].pop(index)
  197. self.con.update_config(self.servers)
  198. return await self.bot.say("Removed Warning {} from {}".format(index+1, user.name+"#"+user.discriminator))
  199. except Exception as e:
  200. if isinstance(e, IndexError):
  201. return await self.bot.say(":warning: Index Error.")
  202. elif isinstance(e, KeyError):
  203. return await self.bot.say("Could not find user in warning list.")
  204. elif isinstance(e, ValueError):
  205. return await self.bot.say("Please enter a valid index number.")
  206. else:
  207. raise e
  208. else:
  209. try:
  210. self.servers[ctx.message.server.id]["warnings"].pop(user.id)
  211. self.con.update_config(self.servers)
  212. return await self.bot.say("Removed all warnings for {}".format(user.name+"#"+user.discriminator))
  213. except KeyError:
  214. return await self.bot.say("Could not find user in warning list.")
  215. def setup(Bot):
  216. Bot.add_cog(Admin(Bot))