3232
3333
3434def split_topics (topics : str ) -> list [str ]:
35+ # TODO docstring
3536 return [topic for topic in map (str .strip , topics .replace (";" , "," ).split ("," )) if topic ]
3637
3738
38- async def split_parents (topics : list [str ], assignable : bool ) -> list [tuple [str , bool , list [BTPTopic ]] | None ]:
39+ async def split_parents (topics : list [str ], assignable : bool ) -> list [tuple [str , bool , list [BTPTopic ]]]:
40+ # TODO docstring
3941 result : list [tuple [str , bool , list [BTPTopic ]] | None ] = []
4042 for topic in topics :
4143 topic_tree = topic .split ("/" )
4244
43- parents : list [BTPTopic | None | CommandError ] = [
44- await db .first (filter_by (BTPTopic , name = topic ))
45- if await db .exists (filter_by (BTPTopic , name = topic ))
46- else CommandError (t .parent_not_exists (topic ))
47- for topic in topic_tree [:- 1 ]
48- ]
49-
50- parents = [parent for parent in parents if parent is not None ]
51- for parent in parents :
52- if isinstance (parent , CommandError ):
53- raise parent
45+ parents : list [BTPTopic | None ] = []
46+ for par in topic_tree [:- 1 ]:
47+ parents .append (parent := await db .first (filter_by (BTPTopic , name = par ))) # TODO redis?
48+ if parent is None :
49+ raise CommandError (t .parent_not_exists (topic ))
5450
55- topic = topic_tree [- 1 ]
56- result .append ((topic , assignable , parents ))
51+ result .append ((topic_tree [- 1 ], assignable , parents ))
5752 return result
5853
5954
6055async def parse_topics (topics_str : str ) -> list [BTPTopic ]:
56+ # TODO docstring
6157 topics : list [BTPTopic ] = []
6258 all_topics : list [BTPTopic ] = await get_topics ()
6359
6460 if len (all_topics ) == 0 :
6561 raise CommandError (t .no_topics_registered )
6662
6763 for topic_name in split_topics (topics_str ):
68- topic = await db .first (filter_by (BTPTopic , name = topic_name ))
64+ topic = await db .first (filter_by (BTPTopic , name = topic_name )) # TODO db obsolete
6965
7066 if topic is None and len (all_topics ) > 0 :
7167 best_dist , best_match = min (
@@ -83,13 +79,12 @@ async def parse_topics(topics_str: str) -> list[BTPTopic]:
8379
8480
8581async def get_topics () -> list [BTPTopic ]:
86- topics : list [BTPTopic ] = []
87- async for topic in await db .stream (select (BTPTopic )):
88- topics .append (topic )
89- return topics
82+ # TODO docstring
83+ return await db .all (select (BTPTopic ))
9084
9185
9286async def change_setting (ctx : Context , name : str , value : any ):
87+ # TODO docstring
9388 data = t .settings [name ]
9489 await getattr (BeTheProfessionalSettings , name ).set (value )
9590
@@ -116,6 +111,65 @@ async def on_ready(self):
116111 except RuntimeError :
117112 self .update_roles .restart ()
118113
114+ @tasks .loop (hours = 24 )
115+ @db_wrapper
116+ async def update_roles (self ):
117+ role_create_min_users = await BeTheProfessionalSettings .RoleCreateMinUsers .get ()
118+
119+ logger .info ("Started Update Role Loop" )
120+ topic_count : dict [int , int ] = {}
121+
122+ for topic in await db .all (select (BTPTopic ).order_by (BTPTopic .id .asc ())):
123+ if len (topic .users ) >= role_create_min_users :
124+ topic_count [topic .id ] = len (topic .users )
125+
126+ # Sort Topics By Count and Limit Roles to BeTheProfessionalSettings.RoleLimit
127+ top_topics : list [int ] = sorted (topic_count , key = lambda x : topic_count [x ], reverse = True )[
128+ : await BeTheProfessionalSettings .RoleLimit .get ()
129+ ]
130+
131+ new_roles_topic_id : list [int ] = []
132+
133+ # Delete old Top Topic Roles
134+ for topic in await db .all (
135+ select (BTPTopic ).filter (BTPTopic .role_id .is_not (None ), BTPTopic .id .not_in (top_topics ))
136+ ): # type: BTPTopic
137+ await self .bot .guilds [0 ].get_role (topic .role_id ).delete ()
138+ topic .role_id = None
139+
140+ # Create new Topic Roles
141+ roles : dict [int , Role ] = {}
142+ for topic in await db .all (
143+ select (BTPTopic ).filter (BTPTopic .id .in_ (top_topics ), BTPTopic .role_id .is_ (None ))
144+ ): # type: BTPTopic
145+ new_roles_topic_id .append (topic .id )
146+ role = await self .bot .guilds [0 ].create_role (name = topic .name )
147+ topic .role_id = role .id
148+ roles [topic .id ] = role
149+
150+ # Iterate over all members(with topics) and add the role to them
151+ member_ids : set [int ] = {
152+ btp_user .user_id for btp_user in await db .all (select (BTPUser )) if btp_user .topic .id in new_roles_topic_id
153+ }
154+ for member_id in member_ids :
155+ member : Member = self .bot .guilds [0 ].get_member (member_id )
156+ if member is None :
157+ continue
158+ member_roles : list [Role ] = [
159+ roles .get (btp_user .topic ) for btp_user in await db .all (select (BTPUser ).filter_by (user_id = member_id ))
160+ ]
161+ member_roles = list (filter (lambda x : x is not None , member_roles ))
162+ await member .add_roles (* member_roles , atomic = False )
163+
164+ logger .info ("Created Top Topic Roles" )
165+
166+ async def on_member_join (self , member : Member ):
167+ roles : list [Role ] = [
168+ self .bot .guilds [0 ].get_role (topic .role_id )
169+ async for topic in await db .stream (select (BTPUser ).filter_by (user_id = member .id ))
170+ ]
171+ await member .add_roles (* roles , atomic = False )
172+
119173 @commands .command (name = "?" )
120174 @guild_only ()
121175 async def list_topics (self , ctx : Context , parent_topic : str | None ):
@@ -177,7 +231,7 @@ async def assign_topics(self, ctx: Context, *, topics: str):
177231 topics : list [BTPTopic ] = [
178232 topic
179233 for topic in await parse_topics (topics )
180- if (await db .exists (filter_by (BTPTopic , id = topic .id )))
234+ if (await db .exists (filter_by (BTPTopic , id = topic .id ))) # TODO db obsolete
181235 and not (await db .exists (filter_by (BTPUser , user_id = member .id , topic_id = topic .id ))) # noqa: W503
182236 ]
183237
@@ -263,14 +317,14 @@ async def register_topics(self, ctx: Context, *, topic_paths: str, assignable: b
263317 """
264318
265319 names = split_topics (topic_paths )
266- topic_paths : list [tuple [str , bool , list [BTPTopic ] | None ]] = await split_parents (names , assignable )
320+ topic_paths : list [tuple [str , bool , list [BTPTopic ]]] = await split_parents (names , assignable )
267321 if not names or not topic_paths :
268322 raise UserInputError
269323
270324 valid_chars = set (string .ascii_letters + string .digits + " !#$%&'()+-./:<=>?[\\ ]^_`{|}~" )
271325 registered_topics : list [tuple [str , bool , list [BTPTopic ]] | None ] = []
272326 for topic in topic_paths :
273- if len (topic ) > 100 :
327+ if len (topic ) > 100 : # TODO
274328 raise CommandError (t .topic_too_long (topic ))
275329 if any (c not in valid_chars for c in topic [0 ]):
276330 raise CommandError (t .topic_invalid_chars (topic ))
@@ -530,62 +584,3 @@ async def topic_update_roles(self, ctx: Context):
530584
531585 await self .update_roles ()
532586 await reply (ctx , "Updated Topic Roles" )
533-
534- @tasks .loop (hours = 24 )
535- @db_wrapper
536- async def update_roles (self ):
537- role_create_min_users = await BeTheProfessionalSettings .RoleCreateMinUsers .get ()
538-
539- logger .info ("Started Update Role Loop" )
540- topic_count : dict [int , int ] = {}
541-
542- for topic in await db .all (select (BTPTopic ).order_by (BTPTopic .id .asc ())):
543- if len (topic .users ) >= role_create_min_users :
544- topic_count [topic .id ] = len (topic .users )
545-
546- # Sort Topics By Count and Limit Roles to BeTheProfessionalSettings.RoleLimit
547- top_topics : list [int ] = sorted (topic_count , key = lambda x : topic_count [x ], reverse = True )[
548- : await BeTheProfessionalSettings .RoleLimit .get ()
549- ]
550-
551- new_roles_topic_id : list [int ] = []
552-
553- # Delete old Top Topic Roles
554- for topic in await db .all (
555- select (BTPTopic ).filter (BTPTopic .role_id .is_not (None ), BTPTopic .id .not_in (top_topics ))
556- ): # type: BTPTopic
557- await self .bot .guilds [0 ].get_role (topic .role_id ).delete ()
558- topic .role_id = None
559-
560- # Create new Topic Roles
561- roles : dict [int , Role ] = {}
562- for topic in await db .all (
563- select (BTPTopic ).filter (BTPTopic .id .in_ (top_topics ), BTPTopic .role_id .is_ (None ))
564- ): # type: BTPTopic
565- new_roles_topic_id .append (topic .id )
566- role = await self .bot .guilds [0 ].create_role (name = topic .name )
567- topic .role_id = role .id
568- roles [topic .id ] = role
569-
570- # Iterate over all members(with topics) and add the role to them
571- member_ids : set [int ] = {
572- btp_user .user_id for btp_user in await db .all (select (BTPUser )) if btp_user .topic .id in new_roles_topic_id
573- }
574- for member_id in member_ids :
575- member : Member = self .bot .guilds [0 ].get_member (member_id )
576- if member is None :
577- continue
578- member_roles : list [Role ] = [
579- roles .get (btp_user .topic ) for btp_user in await db .all (select (BTPUser ).filter_by (user_id = member_id ))
580- ]
581- member_roles = list (filter (lambda x : x is not None , member_roles ))
582- await member .add_roles (* member_roles , atomic = False )
583-
584- logger .info ("Created Top Topic Roles" )
585-
586- async def on_member_join (self , member : Member ):
587- roles : list [Role ] = [
588- self .bot .guilds [0 ].get_role (topic .role_id )
589- for topic in await db .all (select (BTPUser ).filter_by (user_id = member .id ))
590- ]
591- await member .add_roles (* roles , atomic = False )
0 commit comments