-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinfo.py
294 lines (272 loc) · 15.3 KB
/
info.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
import asyncio
import typing
import discord
from discord.ext import commands
import contextlib
import time
class info(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.bot.AWARDS = {1:'<:gold_bimm:896479698878615552> (1)', 2:':second_place:', 3:':third_place:'}
self.delay = 0
#if self.bot.config['USE_CUSTOM_EMOJI']:
#self.bot.AWARDS[1] = '<:gold_bimm:896479698878615552> (1)'
async def convert(self, ctx, arg):
return await commands.MemberConverter().convert(ctx, arg)
async def convert_to_member(self, ctx, user, allow_none=False):
if user:
user = await self.convert(ctx, user)
elif allow_none and user == None:
pass
else:
user = ctx.author
return user
async def await_delete(self, ctx, message):
await message.add_reaction("\U0001f5d1")
await asyncio.sleep(0.5)
start = time.time()
while True:
if time.time() - start >= 120:
await message.clear_reaction("\U0001f5d1")
return False
try:
reaction = await self.bot.wait_for('reaction_add', timeout=120.0)
except asyncio.TimeoutError:
await message.clear_reaction("\U0001f5d1")
return False
users = [user async for user in reaction[0].users()]
if ctx.message.author in users and reaction[0].message.id == message.id and reaction.emoji == "\U0001f5d1":
await message.delete()
return True
async def show_loading_message(self, ctx, text):
if self.delay > 1:
return await ctx.send(text)
return None
async def command_completed(self, ctx, response, loading):
deleted = await self.await_delete(ctx, response)
if loading and deleted:
await loading.delete()
#TODO: cache jmmmapping so we don't need to do this on demand (it's slow)
async def get_jmmmapping(self):
'''Gets jmmboard data for every user'''
jmmmapping = {}
start = time.time()
#step one: calculate total messages and reactions
for message in self.bot.messages:
try:
jmmmapping[str(message.author)]
except KeyError:
jmmmapping[str(message.author)] = {'reactions':0, 'messages':0, 'draobmmjmessages':0, 'draobmmjreactions':0, 'jmmscore':0}
for i in message.reactions:
if hasattr(i.emoji, 'id'):
if i.emoji.id == 774445538409054218:
if i.count >= 4:
jmmmapping[str(message.author)]['messages'] += 1
jmmmapping[str(message.author)]['reactions'] += i.count
elif i.emoji.id == 776612785647910933:
if i.count >= 3:
jmmmapping[str(message.author)]['draobmmjmessages'] += 1
jmmmapping[str(message.author)]['draobmmjreactions'] += i.count
#step two: calculate stats based on those reactions
for i in list(jmmmapping.keys()):
jmmmapping[i]['jmmscore'] = jmmmapping[i]['reactions']-jmmmapping[i]['draobmmjreactions']
#don't include users with no stats on the leaderboard
if not jmmmapping[i]['reactions'] and not jmmmapping[i]['draobmmjreactions']:
jmmmapping.pop(i)
else:
jmmmapping[i]['positivity'] = round((jmmmapping[i]['reactions']/(jmmmapping[i]['reactions']+jmmmapping[i]['draobmmjreactions']))*100,1)
self.delay = time.time()-start
return jmmmapping
async def get_most_jmms(self, user, draobmmj=False):
start = time.time()
jmms = []
for message in self.bot.messages:
#TODO: why in the hell do we convert user to str
if str(message.author) != user and user != "None":
continue
for i in message.reactions:
if hasattr(i.emoji, 'id'):
if i.emoji.id == 774445538409054218 and not draobmmj:
if i.count >= 1:
jmms.append({'message':message, 'reactions':i.count})
if i.emoji.id == 776612785647910933 and draobmmj:
if i.count >= 1:
jmms.append({'message':message, 'reactions':i.count})
self.delay = time.time()-start
return jmms
def get_messages(self, m):
return m[1]['messages']
def get_jmms(self, m):
return m[1]['reactions']
def get_jmmscore(self, m):
return m[1]['jmmscore']
def get_positivity(self, m):
return m[1]['positivity']
def get_jmms_alt(self, m):
return m['reactions']
def get_award(self, num):
'''Gets the award corresponding to a place on the leaderboard'''
try:
award = self.bot.AWARDS[num+1]
except KeyError:
award = num+1
return award
def is_enabled(self, setting, guild_id):
'''Returns whether a setting is enabled'''
try:
return self.bot.settings[setting][guild_id]
except KeyError:
return False
def get_key(self, guild_id):
'''Returns a key to sort jmmmapping by. The key returned is determined by what settings are enabled.'''
if self.is_enabled('sort by jmms', guild_id):
return self.get_jmms
elif self.is_enabled('sort by jmmscore', guild_id):
return self.get_jmmscore
elif self.is_enabled('sort by positivity', guild_id):
return self.get_positivity
return self.get_messages
@commands.command(hidden=True, aliases=['mostjmms'])
async def mostjmmed(self, ctx, *, user=None):
if self.bot.cache_lock.locked() and self.bot.initial_caching == True:
total = len(self.bot.guilds[0].text_channels)
if self.bot.IS_DPY_2:
total += len(self.bot.guilds[0].threads)
return await ctx.send(f"The message cache isn't ready yet. Try again later. \n{self.bot.itercount}/{total} channels have been cached.")
try:
user = await self.convert_to_member(ctx, user, allow_none=True)
except:
return await ctx.send("I can't find that user.")
loading = await self.show_loading_message(ctx, "Fetching jmmboard data...")
most_jmmed = await self.get_most_jmms(str(user))
most_jmmed.sort(key=self.get_jmms_alt, reverse=True)
if not most_jmmed:
return await ctx.send("It doesn't look like you have any golden jmms on your messages.")
desc = ""
for i in most_jmmed[:10]:
if len(desc+f"{i['reactions']} gold jmms: [Go to message]({i['message'].jump_url})") >= 4096:
break
if user:
desc += f"[{i['reactions']} gold jmms]({i['message'].jump_url})\n"
else:
desc += f"[{i['reactions']} gold jmms (by {i['message'].author})]({i['message'].jump_url})\n"
if not user:
user = "The server"
response = await ctx.send(embed=discord.Embed(title=f"{user}'s most golden jmmed messages:", description=desc, color=0xFDFE00))
await self.command_completed(ctx, response, loading)
@commands.command(hidden=True, aliases=['demmjtsom', 'negativegoldjmms', 'mostjmmednt', 'mostcursed'])
async def mostunjmmed(self, ctx, *, user=None):
if self.bot.cache_lock.locked() and self.bot.initial_caching == True:
total = len(self.bot.guilds[0].text_channels)
if self.bot.IS_DPY_2:
total += len(self.bot.guilds[0].threads)
return await ctx.send(f"The message cache isn't ready yet. Try again later. \n{self.bot.itercount}/{total} channels have been cached.")
try:
user = await self.convert_to_member(ctx, user, allow_none=True)
except:
return await ctx.send("I can't find that user.")
loading = await self.show_loading_message(ctx, "Getting draobmmj data...")
most_jmmed = await self.get_most_jmms(str(user), True)
most_jmmed.sort(key=self.get_jmms_alt, reverse=True)
if not most_jmmed:
return await ctx.send("It doesn't look like you have any nogoldjmms on your messages.")
desc = ""
for i in most_jmmed[:10]:
if len(desc+f"[{i['reactions']} nogoldjmms]({i['message'].jump_url})") >= 4096:
break
if user:
desc += f"[{i['reactions']} nogoldjmms]({i['message'].jump_url})\n"
else:
desc += f"[{i['reactions']} nogoldjmms (by {i['message'].author})]({i['message'].jump_url})\n"
if not user:
user = "The server"
response = await ctx.send(embed=discord.Embed(title=f"{user}'s most nogoldjmmed messages:", description=desc, color=discord.Color.dark_red()))
await self.command_completed(ctx, response, loading)
@commands.command(hidden=True, aliases=['leaderboard', 'jmmleaderboards'])
async def jmmleaderboard(self, ctx, limit:typing.Optional[str]=None):
if isinstance(limit, str):
if ':' in limit:
limit = [int(i) for i in limit.split(':')]
if limit[1] < limit[0]:
return await ctx.send("the limit can't be less than the start!")
if limit[0] > 0:
limit[0] -= 1
else:
limit = [0, int(limit)]
else:
limit = [0, 10]
if limit[1] < 2 or limit[1]-limit[0] < 2:
return await ctx.send("I can't show less than 2 people on the leaderboard. sorry.")
if self.bot.cache_lock.locked() and self.bot.initial_caching == True:
total = len(self.bot.guilds[0].text_channels)
if self.bot.IS_DPY_2:
total += len(self.bot.guilds[0].threads)
return await ctx.send(f"The message cache isn't ready yet. Try again later. \n{self.bot.itercount}/{total} channels have been cached.")
key = self.get_key(ctx.guild.id)
if self.delay >= 1:
loading = await ctx.send("Fetching leaderboard data...")
else:
loading = None
jmmmapping = await self.get_jmmmapping()
leaderboard = sorted(list(jmmmapping.items()), key=lambda m: (key(m), self.get_messages(m)), reverse=True)
desc = f"**Currently sorted by *{key.__name__.replace('get_','')}***.\n**Showing places {limit[0]+1} through {limit[1]}. (out of {len(leaderboard)})**\n"
for value in leaderboard[limit[0]:limit[1]]:
place = leaderboard.index(value)
award = self.get_award(place)
if not self.is_enabled('show draobmmj', ctx.guild.id):
desc += f"{award}: {value[0]} ({value[1]['messages']} messages on the jmmboard, {value[1]['reactions']} golden jmms recieved, a jmmscore of {value[1]['reactions']-value[1]['draobmmjreactions']}, and {value[1]['positivity']}% positive reactions)\n"
else:
desc += f"{award}: {value[0]} ({value[1]['messages']} messages on the jmmboard, {value[1]['reactions']} golden jmms recieved, {value[1]['draobmmjmessages']} messages on the draobmmj, {value[1]['draobmmjreactions']} nogoldjmms recieved, a jmmscore of {value[1]['reactions']-value[1]['draobmmjreactions']}, and {value[1]['positivity']}% positive reactions)\n"
leaderboard = discord.Embed(title="Jmmboard leaderboard:", description=desc, color=0xFDFE00)
try:
response = await ctx.send(embed=leaderboard)
except discord.HTTPException:
response = await ctx.send("<:blobpaiN:839543891518685225> I can't show what you requested. Try using a smaller limit. (or a smaller interval if you're using leaderboard slicing)")
deleted = await self.await_delete(ctx, response)
if loading and deleted:
await loading.delete()
@commands.command(hidden=True, aliases=['stats', 'jmmboardstats'])
async def jmmstats(self, ctx, *, user=None):
if self.bot.cache_lock.locked() and self.bot.initial_caching == True:
total = len(self.bot.guilds[0].text_channels)
if self.bot.IS_DPY_2:
total += len(self.bot.guilds[0].threads)
return await ctx.send(f"The message cache isn't ready yet. Try again later. \n{self.bot.itercount}/{total} channels have been cached.")
try:
user = await self.convert_to_member(ctx, user)
except:
return await ctx.send("I can't find that user.")
key = self.get_key(ctx.guild.id)
if self.delay >= 1:
loading = await ctx.send(f"Looking up stats for {user}...")
else:
loading = None
jmmmapping = await self.get_jmmmapping()
leaderboard = sorted(list(jmmmapping.items()), key=lambda m: (key(m), self.get_messages(m)), reverse=True)
try:
current = (str(user), jmmmapping[str(user)])
except KeyError:
return await ctx.send(f"Something went wrong when looking up stats for '{user}'. They might not have anything on the jmmboard.")
place = leaderboard.index(current)
embed = discord.Embed(title=f"Jmmboard stats for {user}", color=0xFDFE00, description=f"**The leaderboard is currently sorted by *{key.__name__.replace('get_','')}***.\n")
award = self.get_award(place)
embed.add_field(name="Place on the leaderboard:", value=award)
embed.add_field(name="Messages on the jmmboard:", value=f"{current[1]['messages']} messages")
embed.add_field(name="Golden jmms recieved:", value=str(current[1]['reactions']))
embed.add_field(name="jmmscore (goldjmms - nogoldjmms):", value=f"{current[1]['jmmscore']} ({current[1]['positivity']}% positive)")
if self.is_enabled('show draobmmj', ctx.guild.id):
embed.add_field(name="Messages on the draobmmj:", value=f"{current[1]['draobmmjmessages']} messages")
embed.add_field(name="nogoldjmms recieved:", value=str(current[1]['draobmmjreactions']))
with contextlib.suppress(IndexError):
if place <= len(leaderboard)+1:
embed.add_field(name="Ahead of:", value=f"{leaderboard[place+1][0]} (with {leaderboard[place+1][1]['messages']} messages on the jmmboard, {leaderboard[place+1][1]['reactions']} golden jmms recieved, a jmmscore of {leaderboard[place+1][1]['jmmscore']}, and {leaderboard[place+1][1]['positivity']}% positive reactions)", inline=False)
if place > 0:
embed.add_field(name="Behind:", value=f"{leaderboard[place-1][0]} (with {leaderboard[place-1][1]['messages']} messages on the jmmboard, {leaderboard[place-1][1]['reactions']} golden jmms recieved, a jmmscore of {leaderboard[place-1][1]['jmmscore']}, and {leaderboard[place-1][1]['positivity']}% positive reactions)", inline=False)
response = await ctx.send(embed=embed)
deleted = await self.await_delete(ctx, response)
if loading and deleted:
await loading.delete()
async def setup(bot):
await bot.add_cog(info(bot))
async def teardown(bot):
await bot.remove_cog(info(bot))