Compare commits
4 Commits
59a501c0a6
...
feature/in
| Author | SHA1 | Date | |
|---|---|---|---|
| faba475d67 | |||
| 5c8c45518c | |||
| 8cbb77be3c | |||
| 6692c43102 |
11
.dockerignore
Normal file
11
.dockerignore
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
.git/
|
||||||
|
tests/
|
||||||
|
*.log
|
||||||
|
.env
|
||||||
|
config/
|
||||||
|
/.vscode/
|
||||||
|
*.log
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -164,4 +164,6 @@ data/
|
|||||||
|
|
||||||
*.disabled
|
*.disabled
|
||||||
|
|
||||||
config/
|
config/
|
||||||
|
|
||||||
|
tests/
|
||||||
35
Dockerfile
35
Dockerfile
@@ -1,19 +1,36 @@
|
|||||||
FROM python:3.13.14-alpine
|
FROM python:3.13.14-alpine
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
build-base \
|
||||||
|
libffi-dev \
|
||||||
|
musl-dev \
|
||||||
|
openssl-dev \
|
||||||
|
python3-dev \
|
||||||
|
geckodriver \
|
||||||
|
firefox-esr
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt .
|
|
||||||
RUN pip install --no-cache-dir -r requirements.txt && \
|
|
||||||
apk add --no-cache firefox geckodriver
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
ENV TOKEN=""
|
ENV TOKEN=""
|
||||||
ENV URL=""
|
|
||||||
ENV CONFIG_PATH="/config"
|
ENV CONFIG_PATH="/config"
|
||||||
ENV COGS=""
|
|
||||||
ENV GECKODRIVER_PATH="/usr/bin/geckodriver"
|
ENV GECKODRIVER_PATH="/usr/bin/geckodriver"
|
||||||
|
|
||||||
RUN mkdir ${CONFIG_PATH}
|
RUN adduser -D bot && \
|
||||||
|
mkdir /logs && \
|
||||||
|
chown -R bot:bot /logs && \
|
||||||
|
chmod 755 /logs && \
|
||||||
|
mkdir -p ${CONFIG_PATH} && \
|
||||||
|
chown -R bot:bot ${CONFIG_PATH} && \
|
||||||
|
chmod 755 ${CONFIG_PATH}
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN chown -R bot:bot /app && \
|
||||||
|
chmod -R 755 /app && \
|
||||||
|
chmod +x /app/main.py
|
||||||
|
|
||||||
|
USER bot
|
||||||
|
|
||||||
ENTRYPOINT ["python", "main.py"]
|
ENTRYPOINT ["python", "main.py"]
|
||||||
17
compose.yaml
17
compose.yaml
@@ -6,15 +6,30 @@ networks:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
botmafieux:
|
botmafieux:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
image: nebulo9/botmafieux:latest
|
image: nebulo9/botmafieux:latest
|
||||||
container_name: botmafieux
|
container_name: botmafieux
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- internal
|
||||||
- outbound
|
- outbound
|
||||||
env_file: ./.env
|
env_file:
|
||||||
|
- ./.env
|
||||||
volumes:
|
volumes:
|
||||||
- ./config:/config
|
- ./config:/config
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "pgrep", "-f", "main.py"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 30s
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
|
|||||||
6778
config/hltv.html
6778
config/hltv.html
File diff suppressed because one or more lines are too long
@@ -1,27 +0,0 @@
|
|||||||
Ta gueule.
|
|
||||||
Qui a demandé ?
|
|
||||||
Mais tais-toi!
|
|
||||||
zZzZzZzZ......
|
|
||||||
Tout ça ?
|
|
||||||
On peut se passer du message je pense.
|
|
||||||
C'est chiant le message là.
|
|
||||||
Mdr on s'en fout.
|
|
||||||
Pas lu.
|
|
||||||
Trop long j'ai décroché.
|
|
||||||
Il faut quitter le serveur, vous gênez l'espace s'il vous plaît.
|
|
||||||
Gênant...
|
|
||||||
Si je devais noter la pertinence du message ce serait genre 1/10.
|
|
||||||
Tu es ridicule, arrête d'écrire.
|
|
||||||
Ça a intéréssé quelqu'un ?
|
|
||||||
Franchement c'était nécessaire d'écrire ça ?
|
|
||||||
Honestly the most useless thing I read today.
|
|
||||||
Dommage que les hommes soient cons…
|
|
||||||
Ta mère mérite la prison pour avoir mis au monde un HOMME.
|
|
||||||
T'as pas beaucoup de neurones.
|
|
||||||
Arrêtons de normaliser les hommes svp.
|
|
||||||
🚮🚮
|
|
||||||
Ton message me donne envie de vomir.
|
|
||||||
J'ai pas ri perso.
|
|
||||||
Tiens tiens encore une raison de détester les hommes !
|
|
||||||
Y'a moyen ton père c'est Macron.
|
|
||||||
Tu préfères devenir un être humain sympa ou rester un homme ?
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
[{"mentor_id": 264189554582355969, "guild_id": 897157935006900254, "next_roll": "2026-07-22T00:00:00"}]
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
target;weight;take
|
|
||||||
any;1.0;Tu as besoin d'un café ?
|
|
||||||
any;1.0;Je peux te faire un café si tu veux ?
|
|
||||||
any;1.0;Tu as besoin d'un thé ?
|
|
||||||
any;1.0;Je peux te faire un thé si tu veux ?
|
|
||||||
any;1.0;Tu as besoin d'un matcha latte?
|
|
||||||
any;1.0;Je peux te faire un matcha latte si tu veux ?
|
|
||||||
any;1.0;Tu peux m'aider sur un truc ?
|
|
||||||
any;1.0;Désolé, j'ai pas compris.
|
|
||||||
any;1.0;Attends, tu peux réexpliquer ?
|
|
||||||
any;1.0;J'ai fait une bêtise je crois...
|
|
||||||
nebulo;2.0;J'ai un bug dans mon code tu peux regarder ?
|
|
||||||
bluebro;2.0;J'ai un bug dans mon code tu peux regarder ?
|
|
||||||
viebah;2.0;J'ai un bug dans mon code tu peux regarder ?
|
|
||||||
merdix;2.0;Mon modèle 3D est cassé, je fais quoi ?
|
|
||||||
goupzy;2.0;Mon modèle 3D est cassé, je fais quoi ?
|
|
||||||
viebah;2.0;Mon modèle 3D est cassé, je fais quoi ?
|
|
||||||
goupzy;2.0;Mon modèle 3D est cassé, je fais quoi ?
|
|
||||||
nino274;2.0;Mon modèle 3D est cassé, je fais quoi ?
|
|
||||||
cemesah;2.0;J'ai fait une erreur, il faut réimprimer les cartes...
|
|
||||||
cemesah;2.0;J'ai pas sauvegardé et InDesign a planté...
|
|
||||||
cemesah;2.0;Tu veux du bouillon ?
|
|
||||||
|
@@ -1,10 +1,13 @@
|
|||||||
aiohappyeyeballs==2.6.2
|
aiohappyeyeballs==2.7.1
|
||||||
aiohttp==3.14.1
|
aiohttp==3.14.1
|
||||||
aiosignal==1.4.0
|
aiosignal==1.4.0
|
||||||
asarPy==1.0.1
|
asarPy==1.0.1
|
||||||
|
async-timeout==5.0.1
|
||||||
attrs==26.1.0
|
attrs==26.1.0
|
||||||
|
audioop-lts==0.2.2
|
||||||
beautifulsoup4==4.15.0
|
beautifulsoup4==4.15.0
|
||||||
certifi==2026.5.20
|
certifi==2026.5.20
|
||||||
|
cffi==2.1.0
|
||||||
charset-normalizer==3.4.7
|
charset-normalizer==3.4.7
|
||||||
frozenlist==1.8.0
|
frozenlist==1.8.0
|
||||||
h11==0.16.0
|
h11==0.16.0
|
||||||
@@ -15,6 +18,8 @@ outcome==1.3.0.post0
|
|||||||
propcache==0.5.2
|
propcache==0.5.2
|
||||||
psycopg2-binary==2.9.12
|
psycopg2-binary==2.9.12
|
||||||
py-cord==2.8.0
|
py-cord==2.8.0
|
||||||
|
pycparser==3.0
|
||||||
|
PyNaCl==1.6.2
|
||||||
PySocks==1.7.1
|
PySocks==1.7.1
|
||||||
python-dotenv==1.2.2
|
python-dotenv==1.2.2
|
||||||
requests==2.34.2
|
requests==2.34.2
|
||||||
@@ -24,8 +29,9 @@ sortedcontainers==2.4.0
|
|||||||
soupsieve==2.8.4
|
soupsieve==2.8.4
|
||||||
trio==0.33.0
|
trio==0.33.0
|
||||||
trio-websocket==0.12.2
|
trio-websocket==0.12.2
|
||||||
typing_extensions==4.15.0
|
typing_extensions==4.16.0
|
||||||
urllib3==2.7.0
|
urllib3==2.7.0
|
||||||
|
wavelink==3.5.2
|
||||||
websocket-client==1.9.0
|
websocket-client==1.9.0
|
||||||
wsproto==1.3.2
|
wsproto==1.3.2
|
||||||
yarl==1.24.2
|
yarl==1.24.2
|
||||||
|
|||||||
23
setup/bot.py
23
setup/bot.py
@@ -1,7 +1,5 @@
|
|||||||
import discord
|
import discord
|
||||||
from discord.ext import bridge
|
from discord.ext import commands
|
||||||
# from cogs.birthday import BirthdayCog
|
|
||||||
# from cogs.productivity import ProductivityCog
|
|
||||||
from cogs.cs import CSCog
|
from cogs.cs import CSCog
|
||||||
from cogs.insult import InsultsCog
|
from cogs.insult import InsultsCog
|
||||||
from cogs.roulette import RouletteCog
|
from cogs.roulette import RouletteCog
|
||||||
@@ -15,8 +13,9 @@ bot_intents.members = True
|
|||||||
bot_intents.presences = True
|
bot_intents.presences = True
|
||||||
bot_intents.guilds = True
|
bot_intents.guilds = True
|
||||||
bot_intents.reactions = True
|
bot_intents.reactions = True
|
||||||
|
bot_intents.voice_states = True
|
||||||
|
|
||||||
bot = bridge.Bot(command_prefix='$', intents=bot_intents)
|
bot = commands.Bot(command_prefix='$', intents=bot_intents)
|
||||||
|
|
||||||
COG_REGISTRY = {
|
COG_REGISTRY = {
|
||||||
'cs': CSCog,
|
'cs': CSCog,
|
||||||
@@ -29,6 +28,22 @@ COG_REGISTRY = {
|
|||||||
from discord import option as discord_option
|
from discord import option as discord_option
|
||||||
|
|
||||||
|
|
||||||
|
@bot.slash_command(name="reload", description="Reload a feature (cog) by name, or 'all')")
|
||||||
|
@discord_option(name="feature", description="Feature to reload (e.g. cs, insult, roles, roulette, all)", input_type=str, required=True)
|
||||||
|
async def reload(ctx: discord.ApplicationContext, feature: str):
|
||||||
|
# Only allow administrators
|
||||||
|
if not ctx.author or not getattr(ctx.author, 'guild_permissions', None) or not ctx.author.guild_permissions.administrator:
|
||||||
|
await ctx.respond("You must be a server administrator to use this command.", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
await ctx.defer()
|
||||||
|
reload_feature(feature)
|
||||||
|
await ctx.followup.send(f"Reload requested for feature: {feature}", ephemeral=True)
|
||||||
|
|
||||||
|
# Register a global admin slash command directly on the bot to avoid circular imports.
|
||||||
|
from discord import option as discord_option
|
||||||
|
|
||||||
|
|
||||||
@bot.slash_command(name="reload", description="Reload a feature (cog) by name, or 'all')")
|
@bot.slash_command(name="reload", description="Reload a feature (cog) by name, or 'all')")
|
||||||
@discord_option(name="feature", description="Feature to reload (e.g. cs, insult, roles, roulette, all)", input_type=str, required=True)
|
@discord_option(name="feature", description="Feature to reload (e.g. cs, insult, roles, roulette, all)", input_type=str, required=True)
|
||||||
async def reload(ctx: discord.ApplicationContext, feature: str):
|
async def reload(ctx: discord.ApplicationContext, feature: str):
|
||||||
|
|||||||
@@ -7,19 +7,11 @@ class Config:
|
|||||||
|
|
||||||
TOKEN = str(os.getenv("TOKEN", ""))
|
TOKEN = str(os.getenv("TOKEN", ""))
|
||||||
CONFIG_PATH = str(os.getenv("CONFIG_PATH"))
|
CONFIG_PATH = str(os.getenv("CONFIG_PATH"))
|
||||||
COGS = os.getenv("COGS", "")
|
|
||||||
|
|
||||||
GUILDS_IDS:list[int] = []
|
GUILDS_IDS:list[int] = []
|
||||||
|
|
||||||
GUILD_CONFIGS:dict[int,dict] = {}
|
GUILD_CONFIGS:dict[int,dict] = {}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_cogs(cls):
|
|
||||||
raw_value = cls.COGS.strip()
|
|
||||||
if not raw_value:
|
|
||||||
return None
|
|
||||||
return [item.strip().lower() for item in raw_value.split(",") if item.strip()]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def load_guilds_configs(cls):
|
def load_guilds_configs(cls):
|
||||||
with os.scandir(cls.CONFIG_PATH) as d:
|
with os.scandir(cls.CONFIG_PATH) as d:
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import tempfile
|
||||||
|
import sys
|
||||||
|
|
||||||
# Determine log level from environment variable `LOG_LEVEL` (e.g. DEBUG, INFO)
|
# Determine log level from environment variable `LOG_LEVEL` (e.g. DEBUG, INFO)
|
||||||
raw_level = os.getenv("LOG_LEVEL", "INFO").upper()
|
raw_level = os.getenv("LOG_LEVEL", "INFO").upper()
|
||||||
@@ -15,7 +17,26 @@ else:
|
|||||||
logging.basicConfig(level=level, format='[%(levelname)s] %(asctime)s: %(name)s: %(message)s')
|
logging.basicConfig(level=level, format='[%(levelname)s] %(asctime)s: %(name)s: %(message)s')
|
||||||
LOGGER = logging.getLogger('botmafieux')
|
LOGGER = logging.getLogger('botmafieux')
|
||||||
LOGGER.setLevel(level)
|
LOGGER.setLevel(level)
|
||||||
# File handler (append)
|
|
||||||
handler = logging.FileHandler(filename='botmafieux.log', encoding='utf-8', mode='a')
|
# Decide log file path: prefer LOG_FILE, then CONFIG_PATH/botmafieux.log, then /tmp
|
||||||
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
|
preferred = os.getenv('LOG_FILE')
|
||||||
LOGGER.addHandler(handler)
|
if not preferred:
|
||||||
|
cfg_path = "/logs"
|
||||||
|
if cfg_path:
|
||||||
|
preferred = os.path.join(cfg_path, 'botmafieux.log')
|
||||||
|
else:
|
||||||
|
preferred = os.path.join(tempfile.gettempdir(), 'botmafieux.log')
|
||||||
|
|
||||||
|
formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s')
|
||||||
|
|
||||||
|
try:
|
||||||
|
handler = logging.FileHandler(filename=preferred, encoding='utf-8', mode='a')
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
LOGGER.addHandler(handler)
|
||||||
|
except (PermissionError, OSError) as e:
|
||||||
|
# Fall back to console logging if file cannot be opened
|
||||||
|
stream_handler = logging.StreamHandler(sys.stdout)
|
||||||
|
stream_handler.setFormatter(formatter)
|
||||||
|
LOGGER.addHandler(stream_handler)
|
||||||
|
# Print a warning directly to stderr in case logging isn't yet configured elsewhere
|
||||||
|
print(f"[WARN] Could not open log file '{preferred}' for writing: {e}. Falling back to stdout.", file=sys.stderr)
|
||||||
Reference in New Issue
Block a user