18
18
# for now, it works well and is quite fast.
19
19
20
20
# ***** IMPORTANT:
21
- # This program uses ADMINISTRATOR priviledges.
21
+ # This program MAY still require ADMINISTRATOR priviledges. Work is being done to
22
+ # curb that.
23
+ #
24
+ # The following permissions are NOW required:
25
+ # create_instant_invite, kick_members, ban_members,
26
+ # manage_channels, manage_guild, add_reactions, view_audit_log,
27
+ # view_channel, manage_roles, manage_permissions, manage_webhooks,
28
+ # manage_emojis_and_stickers, send_messages, send_tts_messages,
29
+ # manage_messages, embed_links, attach_files, read_message_history,
30
+ # mention_everyone, manage_threads, use_embedded_activities,
31
+ # send_messages_in_threads, use_application_commands, manage_events
32
+
33
+ # According to Discord documentation,
34
+ # https://discord.com/community/permissions-on-discord-discord
35
+ #
36
+ # Without the Administrator permission:
37
+ #
38
+ # The role cannot bypass channel-specific permissions unless explicitly granted
39
+ # in each channel.
40
+ #
41
+ # Cannot access permissions higher than its own role in the hierarchy. (This
42
+ # appears to no longer work).
22
43
23
44
# Forum and thread support is a strange approach. Threads are treated like
24
45
# channels, with a few extra bits. Webhooks, slowdown mode, edits, even the way
25
- # message are sent into the thread is effected. Activitieshave to be tested and
46
+ # message are sent into the thread is effected. Activities have to be tested and
26
47
# is it is a thread, most of the time, you have to pull the parent channel.
27
48
# Webhooks and slowdown mode, in particular, do NOT have separate
28
49
# functionalities of a channel, even though discord treats them like a channel.
29
50
30
51
### *** At some point, I'm going to really have to rewrite this. The forum/thread
31
52
### detection code is a stinking hot mess and scattered everywhere.
32
53
33
- # Areas where a classifier can improve functionality (at a higher cost):
34
- # Phone number detection would have a significantly lower lecel of false
35
- # positives.
36
- #
37
- # Technical messages versus non-technical for varying the temperature of
38
- # the conversation.
39
-
40
54
# Emotion scoring (classifier)
41
55
#
42
56
# Emotional scoring (major scale): 10 (love) to -10 (hatred) sets the
122
136
# "THREAT", "SEXUALLY_EXPLICIT", "FLIRTATION", "PERSONAL ATTACK",
123
137
# "INFLAMMATORY", "OBSCENE", "BULLYING"
124
138
139
+ # In consideration/progres
125
140
# Anti nuke
126
141
# Ticket management
127
142
# Anti nudity verification for images.
@@ -175,7 +190,7 @@ from googleapiclient.discovery import build
175
190
176
191
# Active version
177
192
178
- Version = "0.0.0.0.1250 "
193
+ Version = "0.0.0.0.1265 "
179
194
180
195
# The running name of the program. Must be global and NEVER changing.
181
196
@@ -350,6 +365,7 @@ def function_trapper(failed_result=None):
350
365
351
366
# Cheap mkdir
352
367
368
+ @function_trapper (None )
353
369
def mkdir (fn ):
354
370
if not os .path .exists (fn ):
355
371
os .makedirs (fn ,exist_ok = True )
@@ -373,13 +389,15 @@ def ReadFile(fn,binary=False):
373
389
374
390
# Append a single line to an existing file
375
391
392
+ @function_trapper (None )
376
393
def AppendFile (fname ,text ):
377
394
fh = open (fname ,'a+' )
378
395
fh .write (text )
379
396
fh .close ()
380
397
381
398
# Write file to disk
382
399
400
+ @function_trapper (None )
383
401
def WriteFile (fn ,data ):
384
402
cf = open (fn ,'w' )
385
403
cf .write (data )
@@ -822,7 +840,6 @@ def WriteLog(gid,uid,channel,text):
822
840
AppendFile (fn ,s )
823
841
except Exception as err :
824
842
print (f'LOG Broke: { err } ' )
825
- pass
826
843
LoggingLock .release ()
827
844
828
845
# Log errors
@@ -1734,7 +1751,10 @@ def GetOpenRouter(apikey,messages,model,freqpenalty,temperature,timeout):
1734
1751
timeout = timeout
1735
1752
)
1736
1753
clientAI .close ()
1737
- response = completion .choices [0 ].message .content .strip ()
1754
+ try :
1755
+ response = completion .choices [0 ].message .content .strip ()
1756
+ except Exception as err :
1757
+ return None
1738
1758
RawLog (f"OpenRouter/{ model } : { str (completion )} " )
1739
1759
return response
1740
1760
@@ -2440,6 +2460,13 @@ async def VerifyCompanionAdministration(guild):
2440
2460
if orole not in guild .owner .roles :
2441
2461
await guild .owner .add_roles (orole )
2442
2462
2463
+ # Push it to the highest position
2464
+ # await guild.edit_role_positions(positions={orole: len(guild.roles)-1})
2465
+ # else:
2466
+ # Push it to the highest position
2467
+ # if orole!=guild.roles[-1]:
2468
+ # await guild.edit_role_positions(positions={orole: len(guild.roles)-1})
2469
+
2443
2470
# Check for the 'companion-administration' channel
2444
2471
channel = discord .utils .get (guild .text_channels , name = 'companion-administration' )
2445
2472
@@ -2466,6 +2493,36 @@ async def VerifyCompanionAdministration(guild):
2466
2493
channel .edit (overwrites = overwrites )
2467
2494
return channel
2468
2495
2496
+ # Verify all required permissions
2497
+
2498
+ @function_trapper
2499
+ def VerifyGuildPermissions (guild ):
2500
+ # List of non-voice-related permissions
2501
+ non_voice_permissions = [
2502
+ "create_instant_invite" , "kick_members" , "ban_members" , "administrator" ,
2503
+ "manage_channels" , "manage_guild" , "add_reactions" , "view_audit_log" ,
2504
+ "view_channel" , "manage_roles" , "manage_permissions" , "manage_webhooks" ,
2505
+ "manage_emojis_and_stickers" , "send_messages" , "send_tts_messages" ,
2506
+ "manage_messages" , "embed_links" , "attach_files" , "read_message_history" ,
2507
+ "mention_everyone" , "manage_threads" , "use_embedded_activities" ,
2508
+ "send_messages_in_threads" , "use_application_commands" , "manage_events"
2509
+ ]
2510
+
2511
+ # Get the bot's current guild permissions
2512
+ bot_permissions = guild .me .guild_permissions
2513
+
2514
+ # Find missing permissions
2515
+ missing_permissions = [perm for perm in non_voice_permissions if not getattr (bot_permissions , perm )]
2516
+
2517
+ # Print missing permissions if any
2518
+ if missing_permissions :
2519
+ print (f"{ guild .id } Missing permissions:" )
2520
+ for perm in missing_permissions :
2521
+ print (f"- { perm } " )
2522
+ return False # Not all permissions are enabled
2523
+
2524
+ return True # All permissions are enabled
2525
+
2469
2526
# This function checks the security setup of a Discord server to ensure
2470
2527
# it’s well-protected and highlights any weak points. It verifies if an
2471
2528
# "owner" role exists, has the highest permissions, and is assigned to the
@@ -2490,6 +2547,8 @@ async def SecurityAudit(guild=None,message=None,ShowResults=False,auto=False):
2490
2547
# Create the CompanionAdministration area (if not exist) and get the channel
2491
2548
admin = await VerifyCompanionAdministration (guild )
2492
2549
2550
+ PermChk = VerifyGuildPermissions (guild )
2551
+
2493
2552
# Start with the automatic setting. Results will be forced if audit fails
2494
2553
FailedAudit = False
2495
2554
AuditOwnerRole = False
@@ -2549,6 +2608,8 @@ async def SecurityAudit(guild=None,message=None,ShowResults=False,auto=False):
2549
2608
if ShowResults or FailedAudit :
2550
2609
await admin .send (f"Guild: { guild .name } ({ guild .id } )" )
2551
2610
await admin .send (f"Owner: { guild .owner } ({ guild .owner .id } )" )
2611
+ if not PermChk :
2612
+ await admin .send (f"This guild does NOT have the proper permissions set to function." )
2552
2613
if not AuditOwnerRole :
2553
2614
await admin .send (f"The `owner` role does not exist. A dedicated guild owner role is vital for securing control, ensuring only trusted hands hold top permissions. This role acts as the ultimate safeguard against unauthorized changes, breaches, and ensures accountability in managing server integrity." )
2554
2615
if not IsHighestPos :
@@ -2615,7 +2676,12 @@ async def ImposterAmoungUs(guild, member):
2615
2676
return True
2616
2677
return False
2617
2678
2618
- # Check wwhitelist
2679
+ # This function acts as a bypass for regular system measures, granting special
2680
+ # permissions to **trusted** users, roles, or channels listed in a whitelist. It
2681
+ # checks if a user’s ID, their role name, or the channel name matches an entry in
2682
+ # the bot’s predefined whitelist. If a match is found, it allows the action without
2683
+ # enforcing standard restrictions. This ensures trusted individuals or channels can
2684
+ # operate freely, even when other controls are in place.
2619
2685
2620
2686
def CheckWhitelist (bot ,whitelist ,message = None ,user = None ):
2621
2687
if message == None and author == None :
@@ -3328,7 +3394,7 @@ async def on_typing(channel, user, when):
3328
3394
# Determine slow mode duration
3329
3395
if typing_count > 2 * expected_users : # Over threshold
3330
3396
bot = GetCompanionPersona (server .id ,None ,Welcome = True )
3331
- await ModeratorNotify (bot ,server . id ,f"Under potential raid attack, { joins } joins, { typing_count } users>{ expected_users } users" )
3397
+ await ModeratorNotify (bot ,server ,f"Under potential raid attack, { joins } joins, { typing_count } users>{ expected_users } users" )
3332
3398
slow_mode_duration = SlowModeMultiplier * typing_count * 10 * joins
3333
3399
elif typing_count > expected_users :
3334
3400
slow_mode_duration = SlowModeMultiplier * typing_count * joins
@@ -3734,6 +3800,9 @@ async def on_ready():
3734
3800
3735
3801
# Print some fluff
3736
3802
for guild in client .guilds :
3803
+ if not VerifyGuildPermissions (guild ):
3804
+ print (f"{ guild .id } does NOT have the proper permissions to function." )
3805
+
3737
3806
# Add the guild to the circular guild queue, if not already in it.
3738
3807
if guild .id not in GuildQueue and GuildQueueLock .acquire (timeout = GuildQueueTimeout ):
3739
3808
GuildQueue .append (guild )
0 commit comments