-
Notifications
You must be signed in to change notification settings - Fork 15
Expand file tree
/
Copy pathmisc.py
More file actions
727 lines (610 loc) · 30.6 KB
/
misc.py
File metadata and controls
727 lines (610 loc) · 30.6 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
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
"""
Misc commands cog.
"""
import discord
from discord import app_commands
from discord.ext import commands
from typing import Optional, Any, Union
from datetime import datetime, timezone, timedelta
import calendar
from better_profanity import profanity
from utils.config import Config
class Misc(commands.Cog):
"""Miscellaneous commands."""
def __init__(self, bot: commands.Bot, config: Config):
self.bot = bot
self.config = config
@commands.hybrid_command(name='join-vc', description='Join your voice channel for fun')
async def join_vc(self, ctx: commands.Context):
"""Join the invoker's voice channel (only if it is not empty)."""
if ctx.guild is None:
return await ctx.send("Server only command.")
if not isinstance(ctx.author, discord.Member):
return await ctx.send("Server member only.")
if not ctx.author.voice or not ctx.author.voice.channel:
return await ctx.send("Join a voice channel first.")
channel = ctx.author.voice.channel
non_bot_members = [m for m in channel.members if not m.bot]
if len(non_bot_members) == 0:
return await ctx.send("I will not join an empty voice channel.")
vc = ctx.voice_client
try:
if isinstance(vc, discord.VoiceClient) and vc.is_connected():
if vc.is_playing() or vc.is_paused():
return await ctx.send("I am currently playing audio in a voice channel.")
if vc.channel == channel:
return await ctx.send("I am already in your voice channel.")
await vc.move_to(channel)
else:
await channel.connect()
except discord.Forbidden:
return await ctx.send("I do not have permission to join that voice channel.")
except discord.ClientException:
return await ctx.send("I could not connect to that voice channel.")
await ctx.send(f"Joined {channel.mention}.")
@commands.Cog.listener()
async def on_voice_state_update(
self,
member: discord.Member,
before: discord.VoiceState,
after: discord.VoiceState,
):
"""Auto-leave when the last non-bot member leaves the bot's channel."""
if member.bot:
return
vc = getattr(member.guild, 'voice_client', None)
if not isinstance(vc, discord.VoiceClient) or not vc.is_connected() or not vc.channel:
return
# Only react to events involving the channel we're currently in.
if before.channel != vc.channel and after.channel != vc.channel:
return
# If nobody (except bots) is left in the channel, disconnect.
remaining_humans = [m for m in vc.channel.members if not m.bot]
if len(remaining_humans) != 0:
return
if vc.is_playing() or vc.is_paused():
return
try:
await vc.disconnect()
except Exception:
return
@commands.hybrid_command(name='about', description='Learn about Eigen Bot')
async def about(self, ctx: commands.Context):
"""Show information about the bot."""
embed = discord.Embed(
title="Eigen Bot",
description=(
"Feature-rich Discord bot for community engagement, "
"support tickets, and utilities. Built with discord.py."
),
color=0x000000
)
# Add bot stats
total_guilds = len(self.bot.guilds)
total_users = sum(guild.member_count for guild in self.bot.guilds if guild.member_count)
total_commands = len(self.bot.tree.get_commands())
embed.add_field(
name="Statistics",
value=(
f"Servers: **{total_guilds}**\n"
f"Users: **{total_users:,}**\n"
f"Commands: **{total_commands}**"
),
inline=True
)
embed.add_field(
name="Features",
value=(
"Support Tickets\n"
"Starboard\n"
"Custom Tags\n"
"Elections\n"
"Invite Tracker\n"
"AFK System\n"
"Fun Commands\n"
"Utilities"
),
inline=True
)
embed.add_field(
name="Links",
value=(
"[GitHub](https://github.com/TheCodeVerseHub/Eigen-Bot) · "
"[Invite](https://discord.com/api/oauth2/authorize) · "
"[Support](https://discord.gg/4TkQYz7qea)"
),
inline=False
)
embed.set_footer(
text=f"discord.py {discord.__version__} · TheCodeVerseHub"
)
# Set bot thumbnail
if self.bot.user and self.bot.user.avatar:
embed.set_thumbnail(url=self.bot.user.avatar.url)
await ctx.send(embed=embed)
@commands.hybrid_command(name='song', aliases=['sp', 'spotify'], description='Show what you are currently listening to on Spotify')
async def song(self, ctx: commands.Context, user: Optional[discord.Member] = None):
"""Display the current song/music that a user is listening to on Spotify or other music apps."""
target_user = user or ctx.author
# Ensure target_user is a Member (has activities attribute)
if not isinstance(target_user, discord.Member):
embed = discord.Embed(
title="❌ Error",
description="This command only works in servers, not in DMs.",
color=discord.Color.red()
)
await ctx.send(embed=embed)
return
# Check all activities - be more comprehensive
spotify_activity = None
music_activity = None
for activity in target_user.activities:
# Check for Spotify specifically
if isinstance(activity, discord.Spotify):
spotify_activity = activity
break
# Check for any listening activity (including other music apps)
elif activity.type == discord.ActivityType.listening:
music_activity = activity
if spotify_activity:
# Create rich embed for Spotify
embed = discord.Embed(
title="Now Playing · Spotify",
description=f"{target_user.display_name}",
color=0x000000
)
# Song details
embed.add_field(
name="Track",
value=f"**[{profanity.censor(spotify_activity.title)}]({spotify_activity.track_url})**",
inline=False
)
embed.add_field(
name="Artist",
value=profanity.censor(", ".join(spotify_activity.artists)),
inline=True
)
embed.add_field(
name="Album",
value=profanity.censor(spotify_activity.album),
inline=True
)
# Duration
duration = spotify_activity.duration
current = (discord.utils.utcnow() - spotify_activity.start).total_seconds()
duration_str = f"{int(duration.total_seconds() // 60)}:{int(duration.total_seconds() % 60):02d}"
current_str = f"{int(current // 60)}:{int(current % 60):02d}"
# Progress bar
progress = min(current / duration.total_seconds(), 1.0)
bar_length = 20
filled = int(bar_length * progress)
bar = "━" * filled + "○" + "─" * (bar_length - filled - 1)
embed.add_field(
name="Duration",
value=f"`{current_str}` {bar} `{duration_str}`",
inline=False
)
# Add album art if available
if spotify_activity.album_cover_url:
embed.set_thumbnail(url=spotify_activity.album_cover_url)
embed.set_footer(text=f"Requested by {ctx.author.display_name}")
elif music_activity:
# Found other music activity (not Spotify)
# Generic music activity
embed = discord.Embed(
title="Now Listening",
description=f"{target_user.display_name}",
color=0x000000
)
embed.add_field(
name="Activity",
value=f"**{profanity.censor(music_activity.name)}**",
inline=False
)
# Use getattr to safely access optional attributes
details = getattr(music_activity, 'details', None)
if details:
embed.add_field(name="Details", value=profanity.censor(details), inline=False)
state = getattr(music_activity, 'state', None)
if state:
embed.add_field(name="State", value=profanity.censor(state), inline=False)
embed.set_footer(text=f"Requested by {ctx.author.display_name}", icon_url=ctx.author.display_avatar.url)
else:
# No music activity found - show debug info
if target_user == ctx.author:
# Show what activities were detected
activities_list = []
for activity in target_user.activities:
activities_list.append(f"• **{activity.name}** (Type: {activity.type.name})")
if activities_list:
debug_info = "\n".join(activities_list)
message = (
"❌ **No music activity detected!**\n\n"
f"**Your current activities:**\n{debug_info}\n\n"
"**Possible solutions:**\n"
"• Make sure you're listening to music on Spotify, Apple Music, YouTube Music, etc.\n"
"• Enable 'Display current activity' in Discord Settings → Activity Privacy\n"
"• Restart your Discord client\n"
"• Make sure the music app is connected to Discord (check User Settings → Connections)"
)
else:
message = (
"❌ **You are not currently listening to any music!**\n\n"
"**To use this command:**\n"
"• Be listening to Spotify or another music app\n"
"• Enable 'Display current activity' in Discord Settings → Activity Privacy\n"
"• Have your Discord client open and showing your activity\n"
"• Connect your music app in Discord Settings → Connections (for Spotify)"
)
else:
message = (
f"❌ **{target_user.display_name} is not currently listening to any music!**\n\n"
"They must be listening to Spotify or another music app with activity status enabled."
)
embed = discord.Embed(
title="No Music Playing",
description=message,
color=0x000000
)
embed.set_footer(text="Activity Privacy must be enabled")
await ctx.send(embed=embed)
@commands.command(name='uptime', hidden=True)
async def uptime(self, ctx: commands.Context):
"""Show the bot's uptime."""
start_time = getattr(self.bot, 'start_time', None)
if not start_time:
await ctx.send("Start time not tracked.")
return
now = discord.utils.utcnow()
delta = now - start_time
days = delta.days
hours, remainder = divmod(delta.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
uptime_str = f"{days}d {hours}h {minutes}m {seconds}s"
await ctx.send(f"⏱️ **Uptime:** {uptime_str}")
@commands.command(name='diagnose', hidden=True)
@commands.has_permissions(administrator=True)
async def diagnose(self, ctx: commands.Context):
"""Show diagnostic information (Admin only)."""
# Slash commands count
slash_commands = len(self.bot.tree.get_commands())
# Prefix commands count
prefix_commands = len(self.bot.commands)
# Guilds
guilds = len(self.bot.guilds)
# Users
users = sum(g.member_count for g in self.bot.guilds if g.member_count)
# Latency
latency = round(self.bot.latency * 1000)
embed = discord.Embed(title="Diagnostic Info", color=0x000000)
embed.add_field(name="Slash Commands", value=str(slash_commands), inline=True)
embed.add_field(name="Prefix Commands", value=str(prefix_commands), inline=True)
embed.add_field(name="Guilds", value=str(guilds), inline=True)
embed.add_field(name="Users", value=str(users), inline=True)
embed.add_field(name="Latency", value=f"{latency}ms", inline=True)
start_time = getattr(self.bot, 'start_time', None)
if start_time:
embed.add_field(name="Start Time", value=discord.utils.format_dt(start_time, 'R'), inline=True)
await ctx.send(embed=embed)
@commands.hybrid_command(name='bug', description='Report a bug to the bot dev - Only for small bugs')
@app_commands.describe(bug='Describe the bug you encountered')
async def bug_report(self, ctx: commands.Context, *, bug: str):
"""Report a bug to the support server."""
# Support server channel ID
SUPPORT_CHANNEL_ID = 1452739906525728828
user = ctx.author
guild = ctx.guild
try:
# Get the support channel
support_channel = self.bot.get_channel(SUPPORT_CHANNEL_ID)
if not support_channel or not isinstance(support_channel, discord.TextChannel):
response = "❌ Could not access the support channel. Please join our [support server](https://discord.gg/4TkQYz7qea) and report the bug there."
if ctx.interaction:
await ctx.interaction.response.send_message(response, ephemeral=True)
else:
await ctx.send(response)
return
# Create bug report embed
embed = discord.Embed(
title="Bug Report",
color=0x000000
)
# Add bug details
embed.add_field(name="Details", value="*"+bug+"*", inline=False)
# Add reporter and server info inline
reporter_info = f"{user.mention} · `{user.id}`"
location_info = f"{guild.name} · `{guild.id}`" if guild else "Direct Message"
embed.add_field(name="Reported by", value=reporter_info, inline=True)
embed.add_field(name="Server", value=location_info, inline=True)
# Send to support channel
await support_channel.send(embed=embed)
# Confirm to user
response = (
"✅ Your bug report has been submitted to our support team. Thank you for helping us improve!\n\n"
"**Want to track your report or get faster support?**\n"
"Join our support server: https://discord.gg/4TkQYz7qea"
)
if ctx.interaction:
if not ctx.interaction.response.is_done():
await ctx.interaction.response.send_message(response, ephemeral=True)
else:
await ctx.interaction.followup.send(response, ephemeral=True)
else:
await ctx.send(response)
except Exception as e:
response = (
f"❌ An error occurred while submitting your bug report: {str(e)}\n\n"
"Please report this directly in our [support server](https://discord.gg/4TkQYz7qea)."
)
if ctx.interaction:
if not ctx.interaction.response.is_done():
await ctx.interaction.response.send_message(response, ephemeral=True)
else:
await ctx.interaction.followup.send(response, ephemeral=True)
else:
await ctx.send(response)
@commands.hybrid_command(name='support', description='Get the support server invite link')
async def support(self, ctx: commands.Context):
"""Send the support server invite link."""
content = "Join our support server: https://discord.gg/4TkQYz7qea"
if ctx.interaction:
await ctx.interaction.response.send_message(content, ephemeral=True)
else:
try:
await ctx.author.send(content)
try:
await ctx.message.add_reaction("✅")
except:
pass
except:
await ctx.send(content, delete_after=10)
@app_commands.command(name='newfeature', description='Suggest a new feature for the bot')
@app_commands.describe(feature='Describe the feature you would like to see')
async def new_feature(self, interaction: discord.Interaction, feature: str):
"""Submit a feature request to the support server."""
# Feature requests channel ID
FEATURE_CHANNEL_ID = 1452740031419777096
try:
# Get the feature requests channel
feature_channel = self.bot.get_channel(FEATURE_CHANNEL_ID)
if not feature_channel or not isinstance(feature_channel, discord.TextChannel):
await interaction.response.send_message(
"❌ Could not access the feature requests channel. Please join our [support server](https://discord.gg/4TkQYz7qea) and submit your request there.",
ephemeral=True
)
return
# Create feature request embed
embed = discord.Embed(
title="Feature Request",
color=0x000000
)
# Add feature details
embed.add_field(name="Details", value="*"+feature+"*", inline=False)
# Add requester and server info inline
requester_info = f"{interaction.user.mention} · `{interaction.user.id}`"
location_info = f"{interaction.guild.name} · `{interaction.guild.id}`" if interaction.guild else "Direct Message"
embed.add_field(name="Requested By", value=requester_info, inline=True)
embed.add_field(name="Location", value=location_info, inline=True)
# Send to feature requests channel
await feature_channel.send(embed=embed)
# Confirm to user
await interaction.response.send_message(
"✅ Your feature request has been submitted! Our team will review it soon.\n\n"
"**Want to discuss your idea or see other requests?**\n"
"Join our support server: https://discord.gg/4TkQYz7qea",
ephemeral=True
)
except Exception as e:
await interaction.response.send_message(
f"❌ An error occurred while submitting your feature request: {str(e)}\n\n"
"Please submit it directly in our [support server](https://discord.gg/4TkQYz7qea).",
ephemeral=True
)
@app_commands.command(name='feedback', description='Share your feedback about the bot')
@app_commands.describe(
rating='Rate your experience (1-5 stars)',
feedback='Share your thoughts, suggestions, or testimonial'
)
@app_commands.choices(rating=[
app_commands.Choice(name='⭐ 1 Star - Poor', value=1),
app_commands.Choice(name='⭐⭐ 2 Stars - Fair', value=2),
app_commands.Choice(name='⭐⭐⭐ 3 Stars - Good', value=3),
app_commands.Choice(name='⭐⭐⭐⭐ 4 Stars - Very Good', value=4),
app_commands.Choice(name='⭐⭐⭐⭐⭐ 5 Stars - Excellent', value=5)
])
async def feedback_command(self, interaction: discord.Interaction, rating: int, feedback: str):
"""Submit feedback/testimonial to the support server."""
# Feedback/testimonials channel ID
FEEDBACK_CHANNEL_ID = 1453356371952275527
try:
# Get the feedback channel
feedback_channel = self.bot.get_channel(FEEDBACK_CHANNEL_ID)
if not feedback_channel or not isinstance(feedback_channel, discord.TextChannel):
await interaction.response.send_message(
"❌ Could not access the feedback channel. Please join our [support server](https://discord.gg/4TkQYz7qea) and share your feedback there.",
ephemeral=True
)
return
# Create star rating display
stars = "⭐" * rating
rating_text = ["Poor", "Fair", "Good", "Very Good", "Excellent"][rating - 1]
# Create feedback embed with professional black design
embed = discord.Embed(
title=f"{stars} {rating}/5 · {rating_text}",
color=0x000000
)
# Add feedback content
embed.add_field(name="Feedback", value="*"+feedback+"*", inline=False)
# Add reviewer and server info inline
reviewer_info = f"{interaction.user.mention} · `{interaction.user.id}`"
location_info = f"{interaction.guild.name} · `{interaction.guild.id}`" if interaction.guild else "Direct Message"
embed.add_field(name="User", value=reviewer_info, inline=True)
embed.add_field(name="Server", value=location_info, inline=True)
# Send to feedback channel
await feedback_channel.send(embed=embed)
# Confirm to user with different messages based on rating
if rating >= 4:
message = (
"✅ Thank you for your positive feedback! We're thrilled you're enjoying the bot! 🎉\n\n"
"**Help us grow:**\n"
"Share your experience with others in our [support server](https://discord.gg/4TkQYz7qea)!"
)
else:
message = (
"✅ Thank you for your feedback! We appreciate your honesty and will work on improvements.\n\n"
"**Want to discuss further?**\n"
"Join our support server: https://discord.gg/4TkQYz7qea"
)
await interaction.response.send_message(message, ephemeral=True)
except Exception as e:
await interaction.response.send_message(
f"❌ An error occurred while submitting your feedback: {str(e)}\n\n"
"Please share it directly in our [support server](https://discord.gg/4TkQYz7qea).",
ephemeral=True
)
@app_commands.command(name='timestamp', description='Generate Discord timestamps for any date/time')
@app_commands.describe(
year='Year (e.g., 2025)',
month='Month (1-12)',
day='Day of month (1-31)',
hour='Hour in 24-hour format (0-23, optional)',
minute='Minute (0-59, optional)',
utc_offset='UTC offset in hours (e.g., -5 for EST, 5.5 for IST, optional)'
)
async def timestamp_command(
self,
interaction: discord.Interaction,
year: int,
month: app_commands.Range[int, 1, 12],
day: app_commands.Range[int, 1, 31],
hour: Optional[app_commands.Range[int, 0, 23]] = None,
minute: Optional[app_commands.Range[int, 0, 59]] = None,
utc_offset: float = 0.0
):
"""Generate Discord timestamps with all available formats."""
# Set defaults if None
if hour is None:
hour = 0
if minute is None:
minute = 0
try:
# Validate UTC offset range
if utc_offset < -12 or utc_offset > 14:
await interaction.response.send_message(
"❌ UTC offset must be between -12 and +14 hours!",
ephemeral=True
)
return
# Validate the date
if day > calendar.monthrange(year, month)[1]:
await interaction.response.send_message(
f"❌ Invalid date: {month}/{day}/{year} does not exist!",
ephemeral=True
)
return
# Create datetime object in UTC
# User provides time in their timezone, convert to UTC
offset_hours = int(utc_offset)
offset_minutes = int((utc_offset - offset_hours) * 60)
# Create the datetime in user's timezone
user_dt = datetime(year, month, day, hour, minute)
# Convert to UTC by subtracting the offset
utc_dt = user_dt.replace(tzinfo=None)
# Subtract offset to get UTC time
utc_dt = utc_dt - timedelta(hours=offset_hours, minutes=offset_minutes)
# Get Unix timestamp
unix_timestamp = int(utc_dt.replace(tzinfo=timezone.utc).timestamp())
# Create embed with all timestamp formats
embed = discord.Embed(
title="Discord Timestamps",
description=f"{month}/{day}/{year} {hour:02d}:{minute:02d} (UTC{utc_offset:+.1f})",
color=0x000000
)
# Add all timestamp formats
formats = [
("Short Time", "t", f"<t:{unix_timestamp}:t>"),
("Long Time", "T", f"<t:{unix_timestamp}:T>"),
("Short Date", "d", f"<t:{unix_timestamp}:d>"),
("Long Date", "D", f"<t:{unix_timestamp}:D>"),
("Short Date/Time", "f", f"<t:{unix_timestamp}:f>"),
("Long Date/Time", "F", f"<t:{unix_timestamp}:F>"),
("Relative Time", "R", f"<t:{unix_timestamp}:R>"),
]
format_text = ""
for name, code, timestamp_code in formats:
# Show both the code and how it renders
format_text += f"**{name}** (`{code}`)\n`{timestamp_code}` → {timestamp_code}\n\n"
embed.add_field(
name="Available Formats",
value=format_text.strip(),
inline=False
)
# Add copy-paste section
embed.add_field(
name="Quick Copy",
value=(
f"**Unix Timestamp:** `{unix_timestamp}`\n"
f"**Default:** `<t:{unix_timestamp}>`\n"
f"**Relative:** `<t:{unix_timestamp}:R>`"
),
inline=False
)
embed.set_footer(text="Click 'Copy' on any code block to use it")
await interaction.response.send_message(embed=embed, ephemeral=True)
except ValueError as e:
await interaction.response.send_message(
f"❌ Invalid date/time: {str(e)}",
ephemeral=True
)
except Exception as e:
await interaction.response.send_message(
f"❌ An error occurred: {str(e)}",
ephemeral=True
)
@app_commands.command(name='say', description='Make the bot say something (Admin only)')
@app_commands.describe(text='The text you want the bot to say')
@app_commands.default_permissions(administrator=True)
async def say(self, interaction: discord.Interaction, text: str):
"""Make the bot send a message (admin only to prevent abuse)."""
# Double-check permissions (extra safety)
if not interaction.guild:
await interaction.response.send_message(
"❌ This command can only be used in a server.",
ephemeral=True
)
return
if not isinstance(interaction.user, discord.Member) or not interaction.user.guild_permissions.administrator:
await interaction.response.send_message(
"❌ This command is restricted to administrators only.",
ephemeral=True
)
return
# Check if channel is messageable
if not isinstance(interaction.channel, discord.abc.Messageable):
await interaction.response.send_message(
"❌ Cannot send messages in this channel type.",
ephemeral=True
)
return
# Send the text in the channel
await interaction.channel.send(text)
# Confirm to admin (ephemeral so only they see it)
await interaction.response.send_message(
"✅ Message sent!",
ephemeral=True
)
@commands.command(name='dm', help='Explains why you should not DM members for help')
async def dm_command(self, ctx: commands.Context):
"""Explains why questions should be asked in the server instead of DMs."""
message = (
"Please keep questions and answers within CVH. Do not DM them to other members. "
"By sending your questions in the server, you maximize the number of people that see it, "
"which can give you a higher quality response faster than if you were to DM an individual person. "
"By DM-ing someone, you're also putting unfair pressure on that person to answer you, "
"when they may not be in a position to do so at the moment."
)
await ctx.send(message)
async def setup(bot):
"""Setup the misc cog."""
config = bot.config
await bot.add_cog(Misc(bot, config))