44from pathlib import Path
55
66import discord
7+ import pydantic
78from redbot .core import commands
89from redbot .core .i18n import Translator
910
1011from ..abc import MixinMeta
11- from ..common import formatter
12+ from ..common import formatter , models
1213
1314_ = Translator ("LevelUp" , __file__ )
1415log = logging .getLogger ("red.levelup.dashboard" )
@@ -35,7 +36,6 @@ async def get_dashboard_leaderboard(
3536 guild : discord .Guild ,
3637 lbtype : t .Literal ["lb" , "weekly" ],
3738 stat : t .Literal ["exp" , "messages" , "voice" , "stars" ] = "exp" ,
38- query : t .Optional [str ] = None ,
3939 ** kwargs ,
4040 ):
4141 """
@@ -110,7 +110,6 @@ async def get_dashboard_leaderboard(
110110 member = guild .get_member (user .id ),
111111 use_displayname = True ,
112112 dashboard = True ,
113- query = query ,
114113 )
115114 data = {
116115 "user_id" : user .id ,
@@ -145,3 +144,120 @@ async def weekly_page(
145144 ) -> t .Dict [str , t .Any ]:
146145 stat = stat if stat is not None and stat in {"exp" , "messages" , "voice" , "stars" } else "exp"
147146 return await self .get_dashboard_leaderboard (user , guild , "weekly" , stat , query , ** kwargs )
147+
148+ async def save_settings (self , user : discord .User , guild : discord .Guild , data : dict , ** kwargs ):
149+ member = guild .get_member (user .id )
150+ if not member :
151+ return {
152+ "status" : 1 ,
153+ "error_title" : _ ("Member not found" ),
154+ "error_message" : _ ("You are not a member of this guild." ),
155+ }
156+ if not await self .bot .is_admin (member ):
157+ return {
158+ "status" : 1 ,
159+ "error_title" : _ ("Insufficient permissions" ),
160+ "error_message" : _ ("You need to be an admin to access this page." ),
161+ }
162+
163+ try :
164+ new_conf = models .GuildSettings .model_validate (data )
165+ except pydantic .ValidationError as e :
166+ return {
167+ "status" : 1 ,
168+ "error_title" : _ ("Validation error" ),
169+ "error_message" : str (e ),
170+ }
171+
172+ conf = self .db .get_conf (guild )
173+ for k , v in data .items ():
174+ setattr (conf , k , getattr (new_conf , k , v ))
175+ self .save ()
176+ return {
177+ "status" : 0 ,
178+ "success_title" : _ ("Settings saved" ),
179+ "success_message" : _ ("The settings have been saved." ),
180+ }
181+
182+ # @dashboard_page(name="settings", description="Configure the leveling system.")
183+ async def get_cog_settings (self , user : discord .User , guild : discord .Guild , ** kwargs ):
184+ if kwargs .get ("save" ) and (data := kwargs .get ("new_data" )):
185+ log .info (f"Saving settings for { guild .name } by { user .name } " )
186+ return await self .save_settings (user , guild , data , ** kwargs )
187+ log .info (f"Getting settings for { guild .name } by { user .name } " )
188+ member = guild .get_member (user .id )
189+ if not member :
190+ return {
191+ "status" : 1 ,
192+ "error_title" : _ ("Member not found" ),
193+ "error_message" : _ ("You are not a member of this guild." ),
194+ }
195+ if not await self .bot .is_admin (member ):
196+ return {
197+ "status" : 1 ,
198+ "error_title" : _ ("Insufficient permissions" ),
199+ "error_message" : _ ("You need to be an admin to access this page." ),
200+ }
201+
202+ conf = self .db .get_conf (guild )
203+ settings = conf .model_dump (mode = "json" , exclude = ["users" , "users_weekly" ])
204+
205+ users = []
206+ for user in guild .members :
207+ users .append (
208+ {
209+ "id" : user .id ,
210+ "name" : user .name ,
211+ "avatar" : user .display_avatar .url ,
212+ }
213+ )
214+
215+ emojis = []
216+ for emoji in guild .emojis :
217+ emojis .append (
218+ {
219+ "id" : emoji .id ,
220+ "name" : emoji .name ,
221+ "url" : emoji .url ,
222+ }
223+ )
224+
225+ # Add roles data for the settings page
226+ roles = []
227+ for role in sorted (guild .roles , reverse = True ):
228+ if role .is_default ():
229+ continue
230+ roles .append (
231+ {
232+ "id" : role .id ,
233+ "name" : role .name ,
234+ "color" : str (role .color ),
235+ "position" : role .position ,
236+ }
237+ )
238+
239+ parent = Path (__file__ ).parent
240+ source_path = parent / "templates" / "settings.html"
241+ static_dir = parent / "static"
242+ js_path = static_dir / "js" / "settings.js"
243+ css_path = static_dir / "css" / "settings.css"
244+
245+ # Inject JS and CSS into the HTML source for full page loads
246+ source = (
247+ f"<style>\n { css_path .read_text () if css_path .exists () else '' } \n </style>\n \n "
248+ + source_path .read_text ().strip ()
249+ + f"\n \n <script>\n { js_path .read_text ()} \n </script>"
250+ )
251+
252+ payload = {
253+ "status" : 0 ,
254+ "web_content" : {
255+ "source" : source ,
256+ "expanded" : True ,
257+ "settings" : settings ,
258+ "users" : users ,
259+ "emojis" : emojis ,
260+ "roles" : roles ,
261+ },
262+ }
263+ return payload
0 commit comments