-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbot.py
More file actions
204 lines (173 loc) · 7.49 KB
/
Copy pathbot.py
File metadata and controls
204 lines (173 loc) · 7.49 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
"""studybot - Main bot runner"""
import asyncio
import sys
import os
import time
import datetime
from dotenv import load_dotenv
from pathlib import Path
import discord
from discord.ext import commands
from utils.config import DISCORD_TOKEN, PREFIX
from utils.mongo import mongo # <-- IMPORT THIS
# --- JADOO IMPORT: Connect to the new powerful web server ---
import utils.web_server as web_server
try:
from discord import app_commands
except Exception:
class _AppCommandsShim:
def describe(self, **kwargs):
def decorator(func): return func
return decorator
app_commands = _AppCommandsShim()
from utils.chat_logger import ChatLogger
from utils.mod_logger import ModLogger
# 🔥 FIX: Removed 'DB_PATH' because MongoDB doesn't use file paths
from utils.db import DB
BASE_DIR = Path(__file__).parent
load_dotenv(BASE_DIR / '.env')
LOG_CHANNEL_ID = 1426420958222352496
LOG_FILE_DIR = str(BASE_DIR / 'log_files')
GLOBAL_PREFIX = os.getenv('PREFIX', '!')
def get_prefix(bot, message):
return GLOBAL_PREFIX
intents = discord.Intents.all()
class StudyBot(commands.Bot):
def __init__(self):
super().__init__(
command_prefix=get_prefix,
intents=intents,
case_insensitive=True,
help_command=None
)
self.start_time = None
self.bg_task = None
self.chat_logger = ChatLogger(LOG_FILE_DIR)
self.mod_logger = ModLogger(LOG_FILE_DIR)
async def setup_hook(self):
await load_cogs()
try:
print('Syncing application (slash) commands...')
synced = await self.tree.sync()
print(f'Slash commands synced: {len(synced)} commands')
for guild in self.guilds:
try:
await self.tree.sync(guild=guild)
except Exception as e:
print(f'Error syncing commands for guild {guild.id}: {e}')
except Exception as e:
print(f'Error in setup: {e}')
async def on_message(self, message):
if not message.author.bot:
self.chat_logger.log_message(message.author.name, message.content, message.channel, message.guild)
print(f"[USER] {message.author}: {message.content}")
elif message.author == self.user:
self.chat_logger.log_message(self.user.name, message.content, message.channel, message.guild, is_bot=True)
print(f"[BOT] {message.author}: {message.content}")
# --- JADOO FIX: Send Chat to Web Dashboard ---
web_server.log_message_to_web(message)
await super().on_message(message)
async def on_member_ban(self, guild, user):
async for entry in guild.audit_logs(limit=1, action=discord.AuditLogAction.ban):
self.mod_logger.log_action(entry.user.name, "ban", user.name, entry.reason)
async def on_member_kick(self, guild, user):
async for entry in guild.audit_logs(limit=1, action=discord.AuditLogAction.kick):
self.mod_logger.log_action(entry.user.name, "kick", user.name, entry.reason)
async def on_member_timeout(self, guild, user):
try:
async for entry in guild.audit_logs(limit=1, action=discord.AuditLogAction.member_update):
if entry.target == user and entry.changes.timeout:
self.mod_logger.log_action(entry.user.name, "timeout", user.name, entry.reason)
except Exception as e:
print(f'Error logging timeout: {e}')
async def on_ready(self):
print(f'\n{self.user} is ready!')
print(f'Using prefix: !')
self.start_time = time.time()
# --- JADOO FIX: Connect Bot to Web Server ---
web_server.bot = self
# --------------------------------------------
try:
await self.change_presence(activity=discord.Game(name="Deep Dey - The FUTURE IITIAN 🎯"))
except Exception:
pass
if not self.bg_task:
self.bg_task = self.loop.create_task(self.status_update_task())
async def on_command_error(self, ctx, error):
if isinstance(error, commands.CommandNotFound): return
elif isinstance(error, commands.MissingPermissions): await ctx.send("You don't have permission.")
elif isinstance(error, commands.MissingRequiredArgument): await ctx.send(f"Missing arg: {error.param.name}")
else: print(f'Error in command: {error}')
async def on_command(self, ctx):
print(f'Command executed: {ctx.command} by {ctx.author}')
self.chat_logger.log_command(ctx, ctx.command.name)
async def on_command_completion(self, ctx):
self.chat_logger.log_message(ctx.author, f"Completed command: {ctx.command}", ctx.channel, ctx.guild, "COMMAND_COMPLETE")
@commands.hybrid_command(name='sync', description='Sync slash commands (Admin only)')
@commands.has_permissions(administrator=True)
async def sync_commands(self, ctx):
try:
synced = await self.tree.sync()
await ctx.send(f'Successfully synced {len(synced)} commands!')
except Exception as e:
await ctx.send(f'Failed to sync: {str(e)}')
# --- DISCORD STATUS ACTIVITY ---
async def status_update_task(self):
await self.wait_until_ready()
ping_activity = discord.Game(name="Ping: 0ms | Uptime: 0:00:00")
credit_activity = discord.Game(name="Made With 🩷 Deep | qlynk.vercel.app")
last_ping_refresh = time.monotonic() - 15
show_ping = True
while not self.is_closed():
try:
now = time.monotonic()
if now - last_ping_refresh >= 15:
latency = round(self.latency * 1000) if self.latency is not None else 0
uptime_secs = int(time.time() - (self.start_time or time.time()))
uptime = str(datetime.timedelta(seconds=uptime_secs))
ping_activity = discord.Game(name=f"Ping: {latency}ms | Uptime: {uptime}")
last_ping_refresh = now
if show_ping: await self.change_presence(activity=ping_activity)
else: await self.change_presence(activity=credit_activity)
show_ping = not show_ping
await asyncio.sleep(4)
except Exception:
await asyncio.sleep(4)
bot = StudyBot()
bot.LOG_CHANNEL_ID = LOG_CHANNEL_ID
bot.active_focus_sessions = {}
@bot.event
async def on_connect():
bot.start_time = time.time()
print(f"Bot connected at {datetime.datetime.now()}")
async def load_cogs():
print("Loading cogs...")
for file in (BASE_DIR / 'cogs').glob('*.py'):
if file.name.startswith('_'): continue
ext = f"cogs.{file.stem}"
try:
await bot.load_extension(ext)
print(f"Loaded extension {ext}")
except Exception as e:
print(f"Failed to load {ext}: {e}")
async def main():
load_dotenv(BASE_DIR / '.env')
token = os.getenv('DISCORD_TOKEN')
if not token:
print('Error: DISCORD_TOKEN not found.')
return 1
try:
await mongo.connect() # <-- CONNECT HERE
await DB.init_db()
async with bot:
await bot.start(token)
except Exception as e:
print(f"Error starting bot: {e}")
return 1
if __name__ == '__main__':
try:
# --- START THE CORRECT WEB SERVER ---
web_server.keep_alive()
asyncio.run(main())
except KeyboardInterrupt:
print('Shutting down...')