-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathbot.py
More file actions
119 lines (96 loc) · 4.04 KB
/
Copy pathbot.py
File metadata and controls
119 lines (96 loc) · 4.04 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
import asyncio
import csv
import discord
import logging
from discord.ext import commands
from datetime import datetime
from configuration import Config
from utils import read_csv_dicts
# Add cogs
from comandos.ping import Ping
from comandos.moderacion import Moderacion, ApproveButton, RejectButton
from comandos.ayuda import Ayuda
from comandos.flood import FloodSpam
from comandos.limpia import Limpia
from comandos.archivar import Archivar
from comandos.enviar import Enviar
from comandos.retencion import Retencion
from comandos.exportar import Exportar
# Every cog to register on startup. Add a class here (and to the imports
# above) to wire up a new command/listener group - nothing else needs to
# change.
COGS = (Ping, Ayuda, Limpia, Archivar, Moderacion, FloodSpam, Enviar, Retencion, Exportar)
# Global instance of the server
guild = None
# Configuration
config = Config()
# Use '%' as command prefix.
# Only request the privileged intent we actually use (Message Content -
# every spam/moderation check reads message.content). Members and
# Presences are also privileged but nothing in this codebase uses guild
# member chunking, join/leave/update events, or presence data, so we don't
# request them: fewer privileged intents means less to justify/review
# under Discord's developer policy as the bot grows.
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix="%", intents=intents)
file_handler = logging.FileHandler(filename="bot.log", encoding="utf-8", mode="w")
discord.utils.setup_logging(level=logging.INFO, handler=file_handler)
# Also mirror everything to the console - previously bot.log was the *only*
# handler, so running the bot attached to a terminal/screen session showed
# nothing there; every message only ever went to the file.
discord.utils.setup_logging(level=logging.INFO, handler=logging.StreamHandler())
logger = logging.getLogger(__name__)
@bot.event
async def on_message(message: discord.Message):
# Main log. Uses csv.writer (not hand-built quoting) so a message
# containing a literal '"' or a newline - both common in real messages -
# doesn't silently corrupt the row.
with open(config.log_main_file, "a", newline="") as f:
date_str = f"{datetime.now()}"
csv.writer(f, delimiter=";").writerow([
date_str,
"", # command - this log covers every message, not just commands
message.id,
message.channel,
message.author.id,
message.author,
message.content,
])
@bot.event
async def on_ready():
logger.info("Syncing tree...")
# await bot.tree.sync()
@bot.event
async def on_command_error(msg, error):
if isinstance(error, (commands.MissingRole, commands.MissingAnyRole)):
logger.warning("MissingRole ERROR: %s", error)
else:
logger.error("Unhandled command error", exc_info=error)
async def main():
# Reading data
data_mod = read_csv_dicts(config.log_mod_file)
data_accepted = read_csv_dicts(config.log_accepted_file)
data_rejected = read_csv_dicts(config.log_rejected_file)
# Pending moderation
# Get 'message_id' from the 'accepted' and 'rejected' files
ready_ids = {row["message_id"] for row in data_accepted} | {
row["message_id"] for row in data_rejected
}
# keeping the data in the bot instance, keyed by message_id
bot.data_mod = { # type: ignore[attr-defined]
row["message_id"]: row for row in data_mod if row["message_id"] not in ready_ids
}
# Registers the Aprobar/Rechazar buttons as persistent - required for
# clicks on messages sent before this process started to keep working
# (see comandos/moderacion.py's ApproveButton docstring for why
# timeout=None alone doesn't already do this).
bot.add_dynamic_items(ApproveButton, RejectButton)
for cog_cls in COGS:
await bot.add_cog(cog_cls(bot))
# Removing the help command
# bot.remove_command("help")
logger.info("Running...")
await bot.start(config.TOKEN)
if __name__ == "__main__":
asyncio.run(main())