-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenerate_invite.py
More file actions
executable file
·402 lines (334 loc) · 14 KB
/
generate_invite.py
File metadata and controls
executable file
·402 lines (334 loc) · 14 KB
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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#!/usr/bin/env python3
"""
Bot Invite Link Generator for UtilsBot+
This script generates Discord invite links for the bot with appropriate permissions.
It can be run standalone or imported as a module.
Usage:
python generate_invite.py [--minimal] [--admin] [--custom]
Options:
--minimal Generate invite with minimal permissions
--admin Generate invite with administrator permissions
--custom Interactive mode to select custom permissions
--help Show this help message
"""
import argparse
import sys
from pathlib import Path
# Add project root to path for imports
sys.path.insert(0, str(Path(__file__).parent))
try:
from config.settings import settings
except ImportError:
print("❌ Error: Could not import settings. Make sure you're in the correct directory and have set up the environment.")
sys.exit(1)
class InviteLinkGenerator:
"""Generate Discord bot invite links with various permission sets"""
def __init__(self, bot_id: str):
self.bot_id = bot_id
self.base_url = "https://discord.com/api/oauth2/authorize"
def generate_link(self, permissions: int = None, scopes: list = None) -> str:
"""Generate an invite link with specified permissions and scopes"""
if scopes is None:
scopes = ["bot", "applications.commands"]
if permissions is None:
permissions = self.get_recommended_permissions()
scopes_str = "%20".join(scopes)
return f"{self.base_url}?client_id={self.bot_id}&permissions={permissions}&scope={scopes_str}"
def get_minimal_permissions(self) -> int:
"""Get minimal permissions required for basic functionality"""
permissions = 0
permissions |= 1 << 10 # View Channels
permissions |= 1 << 11 # Send Messages
permissions |= 1 << 14 # Embed Links
permissions |= 1 << 15 # Attach Files
permissions |= 1 << 16 # Read Message History
permissions |= 1 << 18 # Use External Emojis
permissions |= 1 << 24 # Use Slash Commands
return permissions
def get_recommended_permissions(self) -> int:
"""Get recommended permissions for full functionality"""
permissions = self.get_minimal_permissions()
permissions |= 1 << 13 # Manage Messages (for cleanup)
permissions |= 1 << 17 # Add Reactions
permissions |= 1 << 19 # Use External Stickers
permissions |= 1 << 22 # Manage Threads
permissions |= 1 << 34 # Use External Sounds
permissions |= 1 << 35 # Send Voice Messages
return permissions
def get_admin_permissions(self) -> int:
"""Get administrator permissions (full access)"""
return 1 << 3 # Administrator permission
def get_network_permissions(self) -> int:
"""Get permissions needed for network/screenshot features"""
permissions = self.get_recommended_permissions()
# Network features don't need additional Discord permissions
return permissions
def get_moderation_permissions(self) -> int:
"""Get permissions for moderation features"""
permissions = self.get_recommended_permissions()
permissions |= 1 << 1 # Kick Members
permissions |= 1 << 2 # Ban Members
permissions |= 1 << 13 # Manage Messages
permissions |= 1 << 28 # Manage Nicknames
permissions |= 1 << 30 # Moderate Members
return permissions
def interactive_permissions(self) -> int:
"""Interactive permission selection"""
print("\n🔧 Custom Permission Selection")
print("=" * 40)
permission_options = {
"minimal": ("Minimal (View, Send Messages, Slash Commands)", self.get_minimal_permissions()),
"recommended": ("Recommended (Full Bot Functionality)", self.get_recommended_permissions()),
"network": ("Network Tools (Screenshots, IP lookup)", self.get_network_permissions()),
"moderation": ("Moderation (Kick, Ban, Manage Messages)", self.get_moderation_permissions()),
"admin": ("Administrator (Full Server Access)", self.get_admin_permissions())
}
print("Available permission sets:")
for key, (description, _) in permission_options.items():
print(f" {key}: {description}")
while True:
choice = input("\nSelect permission set: ").strip().lower()
if choice in permission_options:
return permission_options[choice][1]
print(f"Invalid choice. Please select from: {', '.join(permission_options.keys())}")
def describe_permissions(self, permissions: int) -> list:
"""Describe what permissions are included"""
permission_names = {
1 << 0: "Create Instant Invite",
1 << 1: "Kick Members",
1 << 2: "Ban Members",
1 << 3: "Administrator",
1 << 4: "Manage Channels",
1 << 5: "Manage Guild",
1 << 6: "Add Reactions",
1 << 10: "View Channels",
1 << 11: "Send Messages",
1 << 12: "Send TTS Messages",
1 << 13: "Manage Messages",
1 << 14: "Embed Links",
1 << 15: "Attach Files",
1 << 16: "Read Message History",
1 << 17: "Mention Everyone",
1 << 18: "Use External Emojis",
1 << 20: "Connect",
1 << 21: "Speak",
1 << 22: "Mute Members",
1 << 23: "Deafen Members",
1 << 24: "Move Members",
1 << 25: "Use Voice Activity",
1 << 26: "Change Nickname",
1 << 27: "Manage Nicknames",
1 << 28: "Manage Roles",
1 << 29: "Manage Webhooks",
1 << 30: "Manage Emojis and Stickers",
1 << 31: "Use Slash Commands",
1 << 32: "Request to Speak",
1 << 33: "Manage Events",
1 << 34: "Manage Threads",
1 << 35: "Create Public Threads",
1 << 36: "Create Private Threads",
1 << 37: "Use External Stickers",
1 << 38: "Send Messages in Threads",
1 << 39: "Use Embedded Activities",
1 << 40: "Moderate Members"
}
granted_permissions = []
for bit, name in permission_names.items():
if permissions & bit:
granted_permissions.append(name)
return granted_permissions
def print_invite_info(generator: InviteLinkGenerator, permissions: int, link: str):
"""Print formatted invite link information"""
print(f"\n📋 Bot ID: {generator.bot_id}")
print(f"🔢 Permissions Value: {permissions}")
print(f"\n🌐 Invite Link:")
print(f"{link}")
granted_perms = generator.describe_permissions(permissions)
if len(granted_perms) <= 10:
for perm in granted_perms:
print(f" ✅ {perm}")
else:
for perm in granted_perms[:8]:
print(f" ✅ {perm}")
print(f" ... and {len(granted_perms) - 8} more permissions")
def extract_bot_id_from_token(token: str) -> str:
"""Extract bot ID from Discord bot token"""
try:
import base64
# Discord bot tokens have the format: base64(bot_id).random_chars.signature
# The bot ID is encoded in the first part before the first dot
if not token:
return None
# Split token by dots and get the first part (bot ID section)
token_parts = token.split('.')
if len(token_parts) < 2:
return None
# The first part contains the bot ID encoded in base64
bot_id_encoded = token_parts[0]
# Add padding if needed for base64 decoding
missing_padding = len(bot_id_encoded) % 4
if missing_padding:
bot_id_encoded += '=' * (4 - missing_padding)
# Decode base64 to get bot ID
try:
decoded = base64.b64decode(bot_id_encoded, validate=True)
bot_id = decoded.decode('utf-8')
# Validate that it's a numeric Discord ID
if bot_id.isdigit() and len(bot_id) >= 17: # Discord IDs are typically 18-19 digits
return bot_id
else:
return None
except Exception:
return None
except Exception:
return None
def get_bot_id_automatically() -> str:
"""Try multiple methods to get bot ID automatically"""
methods_tried = []
# Method 1: Check if bot_id or application_id is set in settings
try:
if hasattr(settings, 'bot_id') and settings.bot_id:
if str(settings.bot_id).isdigit():
return str(settings.bot_id)
methods_tried.append("settings.bot_id")
except:
pass
try:
if hasattr(settings, 'application_id') and settings.application_id:
if str(settings.application_id).isdigit():
return str(settings.application_id)
methods_tried.append("settings.application_id")
except:
pass
# Method 2: Extract from bot token
try:
if hasattr(settings, 'bot_token') and settings.bot_token:
bot_id = extract_bot_id_from_token(settings.bot_token)
if bot_id:
return bot_id
methods_tried.append("bot_token_extraction")
except:
pass
# Method 3: Check environment variables directly
import os
try:
for env_var in ['BOT_ID', 'APPLICATION_ID', 'CLIENT_ID', 'DISCORD_BOT_ID']:
bot_id = os.getenv(env_var)
if bot_id and bot_id.isdigit():
return bot_id
methods_tried.append("environment_variables")
except:
pass
# Method 4: Try to extract from BOT_TOKEN environment variable
try:
bot_token = os.getenv('BOT_TOKEN')
if bot_token:
bot_id = extract_bot_id_from_token(bot_token)
if bot_id:
return bot_id
methods_tried.append("env_bot_token_extraction")
except:
pass
# If all methods failed, provide helpful error message
print(f"❌ Could not automatically determine bot ID.")
print(f"Methods tried: {', '.join(methods_tried)}")
print("\n💡 Solutions:")
print("1. Add BOT_ID to your .env file")
print("2. Add APPLICATION_ID to your .env file")
print("3. Use --bot-id parameter")
print("4. Ensure your BOT_TOKEN is valid")
print("\nTo find your bot ID:")
print("• Go to https://discord.com/developers/applications")
print("• Select your application")
print("• Copy the Application ID")
return None
def main():
"""Main function for command line usage"""
parser = argparse.ArgumentParser(
description="Generate Discord invite links for UtilsBot+",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python generate_invite.py # Auto-detect bot ID, recommended permissions
python generate_invite.py --minimal # Auto-detect bot ID, minimal permissions
python generate_invite.py --admin # Auto-detect bot ID, administrator permissions
python generate_invite.py --custom # Auto-detect bot ID, interactive selection
python generate_invite.py --bot-id 123456 # Manual bot ID override
The script will automatically try to detect your bot ID from:
1. BOT_ID in settings/environment
2. APPLICATION_ID in settings/environment
3. Extraction from BOT_TOKEN
4. Environment variables (BOT_ID, APPLICATION_ID, CLIENT_ID, DISCORD_BOT_ID)
For more information, visit: https://github.com/ad1107/utils-bot-plus
"""
)
parser.add_argument(
"--minimal",
action="store_true",
help="Generate invite with minimal permissions"
)
parser.add_argument(
"--admin",
action="store_true",
help="Generate invite with administrator permissions"
)
parser.add_argument(
"--custom",
action="store_true",
help="Interactive mode to select custom permissions"
)
parser.add_argument(
"--bot-id",
type=str,
help="Override bot ID (auto-detects from settings/token by default)"
)
parser.add_argument(
"--debug",
action="store_true",
help="Show debug information about bot ID detection"
)
args = parser.parse_args()
# Get bot ID with automatic detection
if args.bot_id:
bot_id = args.bot_id
if args.debug:
print(f"🔧 Using manually specified bot ID: {bot_id}")
else:
if args.debug:
print("🔍 Attempting automatic bot ID detection...")
bot_id = get_bot_id_automatically()
if not bot_id:
sys.exit(1)
if args.debug:
print(f"✅ Automatically detected bot ID: {bot_id}")
# Validate bot ID
if not bot_id or not str(bot_id).isdigit():
print("❌ Error: Invalid bot ID. Must be a numeric Discord application ID.")
if args.debug:
print(f"Received bot ID: '{bot_id}' (type: {type(bot_id)})")
sys.exit(1)
# Create generator
generator = InviteLinkGenerator(str(bot_id))
# Show detection success message
if not args.bot_id:
print(f"✅ Auto-detected Bot ID: {bot_id}")
# Determine permissions based on arguments
if args.admin:
permissions = generator.get_admin_permissions()
mode = "Administrator"
elif args.minimal:
permissions = generator.get_minimal_permissions()
mode = "Minimal"
elif args.custom:
permissions = generator.interactive_permissions()
mode = "Custom"
else:
permissions = generator.get_recommended_permissions()
mode = "Recommended"
# Generate link
link = generator.generate_link(permissions)
# Print results
print(f"Mode: {mode} Permissions")
print_invite_info(generator, permissions, link)
if __name__ == "__main__":
main()