1
- import discord
2
- from discord . ext import commands
1
+ from urllib . parse import urlparse
2
+ import traceback
3
3
import datetime
4
4
import asyncio
5
5
import functools
6
6
import string
7
7
import re
8
+ import io
9
+
10
+ import discord
11
+ from discord .ext import commands
12
+
13
+ from core .decorators import asyncexecutor
14
+ from colorthief import ColorThief
8
15
9
16
class Thread :
10
17
'''Represents a discord modmail thread'''
@@ -39,11 +46,13 @@ def close(self):
39
46
40
47
async def _edit_thread_message (self , channel , message_id , message ):
41
48
async for msg in channel .history ():
42
- if msg .embeds :
43
- embed = msg .embeds [0 ]
44
- if f'Moderator - { message_id } ' in embed .footer .text :
49
+ if not msg .embeds :
50
+ continue
51
+ embed = msg .embeds [0 ]
52
+ if embed and embed .author :
53
+ if message_id == int (re .findall ('\d+' , embed .author .url )[0 ]):
45
54
if ' - (Edited)' not in embed .footer .text :
46
- embed .set_footer (text = embed .footer .text + ' - (Edited)' )
55
+ embed .set_footer (text = embed .footer .text + ' - (Edited)' )
47
56
embed .description = message
48
57
await msg .edit (embed = embed )
49
58
break
@@ -80,6 +89,8 @@ async def send(self, message, destination=None, from_mod=False, delete_message=T
80
89
description = message .content ,
81
90
timestamp = message .created_at
82
91
)
92
+
93
+ em .set_author (name = str (author ), icon_url = author .avatar_url , url = f'https://{ message .id } .id' ) # store message id in hidden url
83
94
84
95
image_types = ['.png' , '.jpg' , '.gif' , '.jpeg' , '.webp' ]
85
96
is_image_url = lambda u : any (urlparse (u ).path .endswith (x ) for x in image_types )
@@ -100,12 +111,10 @@ async def send(self, message, destination=None, from_mod=False, delete_message=T
100
111
101
112
if from_mod :
102
113
em .color = discord .Color .green ()
103
- em .set_author (name = str (author ), icon_url = author .avatar_url )
104
- em .set_footer (text = f'Moderator - { message .id } ' )
114
+ em .set_footer (text = f'Moderator' )
105
115
else :
106
116
em .color = discord .Color .gold ()
107
- em .set_author (name = str (author ), icon_url = author .avatar_url )
108
- em .set_footer (text = f'User - { message .id } ' )
117
+ em .set_footer (text = f'User' )
109
118
110
119
await destination .trigger_typing ()
111
120
await destination .send (embed = em )
@@ -211,13 +220,14 @@ async def create(self, recipient, *, creator=None):
211
220
212
221
thread .channel = channel
213
222
214
- log_url , log_data = await asyncio .gather (
223
+ log_url , log_data , dc = await asyncio .gather (
215
224
self .bot .modmail_api .get_log_url (recipient , channel , creator or recipient ),
216
- self .bot .modmail_api .get_user_logs (recipient .id )
225
+ self .bot .modmail_api .get_user_logs (recipient .id ),
226
+ self .get_dominant_color (recipient .avatar_url )
217
227
)
218
228
219
229
log_count = len (log_data )
220
- info_embed = self ._format_info_embed (recipient , creator , log_url , log_count )
230
+ info_embed = self ._format_info_embed (recipient , creator , log_url , log_count , dc )
221
231
222
232
topic = f'User ID: { recipient .id } '
223
233
mention = self .bot .config .get ('MENTION' , '@here' ) if not creator else None
@@ -233,6 +243,39 @@ async def create(self, recipient, *, creator=None):
233
243
async def find_or_create (self , recipient ):
234
244
return await self .find (recipient = recipient ) or await self .create (recipient )
235
245
246
+ @staticmethod
247
+ def valid_image_url (url ):
248
+ '''Checks if a url leads to an image.'''
249
+ types = ['.png' , '.jpg' , '.gif' , '.webp' ]
250
+ parsed = urlparse (url )
251
+ if any (parsed .path .endswith (i ) for i in types ):
252
+ return url .replace (parsed .query , 'size=128' )
253
+ return False
254
+
255
+ @asyncexecutor ()
256
+ def _do_get_dc (self , image , quality ):
257
+ with io .BytesIO (image ) as f :
258
+ return ColorThief (f ).get_color (quality = quality )
259
+
260
+ async def get_dominant_color (self , url = None , quality = 10 ):
261
+ '''
262
+ Returns the dominant color of an image from a url
263
+ (misc)
264
+ '''
265
+ url = self .valid_image_url (url )
266
+
267
+ if not url :
268
+ raise ValueError ('Invalid image url passed.' )
269
+ try :
270
+ async with self .bot .session .get (url ) as resp :
271
+ image = await resp .read ()
272
+ color = await self ._do_get_dc (image , quality )
273
+ except Exception as e :
274
+ traceback .print_exc ()
275
+ return discord .Color .blurple ()
276
+ else :
277
+ return discord .Color .from_rgb (* color )
278
+
236
279
def _format_channel_name (self , author ):
237
280
'''Sanitises a username for use with text channel names'''
238
281
name = author .name .lower ()
@@ -243,27 +286,22 @@ def _format_channel_name(self, author):
243
286
new_name += '-x' # two channels with same name
244
287
return new_name
245
288
246
- def _format_info_embed (self , user , creator , log_url , log_count = None ):
289
+ def _format_info_embed (self , user , creator , log_url , log_count , dc ):
247
290
'''Get information about a member of a server
248
291
supports users from the guild or not.'''
249
292
server = self .bot .guild
250
293
member = self .bot .guild .get_member (user .id )
251
294
avi = user .avatar_url
252
295
time = datetime .datetime .utcnow ()
253
- desc = f'{ creator .mention } has created a thread with { user .mention } ' if creator else f'{ user .mention } has started a thread. '
296
+ desc = f'{ creator .mention } has created a thread with { user .mention } ' if creator else f'{ user .mention } has started a thread: '
254
297
key = log_url .split ('/' )[- 1 ]
255
298
desc = f'{ desc } [`{ key } `]({ log_url } )'
256
- color = discord .Color .blurple ()
257
299
258
300
if member :
259
301
roles = sorted (member .roles , key = lambda c : c .position )
260
302
rolenames = ' ' .join ([r .mention for r in roles if r .name != "@everyone" ])
261
- # member_number = sorted(server.members, key=lambda m: m.joined_at).index(member) + 1
262
- for role in roles :
263
- if str (role .color ) != "#000000" :
264
- color = role .color
265
303
266
- em = discord .Embed (colour = color , description = desc , timestamp = time )
304
+ em = discord .Embed (colour = dc , description = desc , timestamp = time )
267
305
268
306
days = lambda d : (' day ago.' if d == '1' else ' days ago.' )
269
307
0 commit comments