Compare commits
No commits in common. "f15b12af2665a0de484a4181ee66754e0abcedbf" and "d955a7a80115978513a45f39bfe0a660e9ad63f2" have entirely different histories.
f15b12af26
...
d955a7a801
@ -1,33 +0,0 @@
|
||||
name: Build and publish Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Derive registry host and image name
|
||||
id: registry
|
||||
run: |
|
||||
host="$(printf '%s' "${{ gitea.server_url }}" | sed -E 's#^[a-zA-Z][a-zA-Z0-9+.-]*://##; s#/.*$##')"
|
||||
image="$(printf '%s' "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]')"
|
||||
echo "host=${host}" >> "$GITHUB_OUTPUT"
|
||||
echo "image=${image}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Log in to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ steps.registry.outputs.host }}
|
||||
username: ${{ gitea.repository_owner }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
- name: Build and push image
|
||||
run: |
|
||||
docker build -t "${{ steps.registry.outputs.host }}/${{ steps.registry.outputs.image }}:latest" .
|
||||
docker push "${{ steps.registry.outputs.host }}/${{ steps.registry.outputs.image }}:latest"
|
||||
31
Dockerfile
31
Dockerfile
@ -4,22 +4,29 @@ FROM python:3.9-slim
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Install Python dependencies
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
# Install git and clean up
|
||||
RUN apt-get update -q && \
|
||||
apt-get install -y git && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy application code
|
||||
COPY main.py fouras.py rhymes.py database.py ./
|
||||
COPY resources/ ./resources/
|
||||
|
||||
# Create data directory for persistent state
|
||||
# Create data directory with proper permissions
|
||||
RUN mkdir -p /app/data && chmod 755 /app/data
|
||||
|
||||
# Ensure Python output is not buffered (useful for logs)
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
# Set safe directory
|
||||
RUN git config --global --add safe.directory '*'
|
||||
|
||||
# Clone the repository
|
||||
RUN git init /app && git remote add origin https://git.epicsparrow.com/Anselme/perefouras.git && git fetch --depth 1 origin master && git reset --hard FETCH_HEAD
|
||||
|
||||
# Install dependencies
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# give exec permissions to main
|
||||
RUN chmod +x main.py
|
||||
|
||||
# Set data directory as volume mount point
|
||||
VOLUME /app/data
|
||||
|
||||
# Run the bot
|
||||
CMD ["python", "main.py"]
|
||||
# Command to update the repo and run the script
|
||||
CMD ["sh", "-c", "cd /app && git fetch --depth 1 origin master && git reset --hard FETCH_HEAD && python main.py"]
|
||||
52
database.py
52
database.py
@ -3,7 +3,7 @@ import sqlite3
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
DB_FILE = "data/database.db"
|
||||
|
||||
@ -52,7 +52,6 @@ SET nb_clues = nb_clues + 1
|
||||
|
||||
DELETE_RIDDLE_QUERY = "DELETE FROM active_riddles WHERE channel_id = ?"
|
||||
|
||||
|
||||
def ensure_db() -> None:
|
||||
"""Initialize SQLite database and create tables if needed."""
|
||||
Path(DB_FILE).parent.mkdir(parents=True, exist_ok=True)
|
||||
@ -91,14 +90,14 @@ def get_connection() -> sqlite3.Connection:
|
||||
def get_guild_state(guild_id: str) -> Dict[str, Any]:
|
||||
with get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(GET_GUILD_STATE_QUERY, (guild_id,))
|
||||
cursor.execute(GET_GUILD_STATE_QUERY,(guild_id,))
|
||||
row = cursor.fetchone()
|
||||
|
||||
if not row:
|
||||
cursor.execute(CREATE_GUILD_STATE_QUERY, (guild_id,))
|
||||
conn.commit()
|
||||
|
||||
cursor.execute(GET_GUILD_STATE_QUERY, (guild_id,))
|
||||
cursor.execute(GET_GUILD_STATE_QUERY,(guild_id,))
|
||||
row = cursor.fetchone()
|
||||
|
||||
if row:
|
||||
@ -114,13 +113,7 @@ def get_guild_state(guild_id: str) -> Dict[str, Any]:
|
||||
def rhyme_configure_cooldown_ratio(guild_id: str, cooldown_ratio: float) -> bool:
|
||||
with get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
CONFIGURE_COOLDOWN_RATIO_QUERY,
|
||||
(
|
||||
cooldown_ratio,
|
||||
guild_id,
|
||||
),
|
||||
)
|
||||
cursor.execute(CONFIGURE_COOLDOWN_RATIO_QUERY, (cooldown_ratio, guild_id,))
|
||||
conn.commit()
|
||||
|
||||
|
||||
@ -131,36 +124,25 @@ def rhyme_damage_self_control(guild_id: str) -> None:
|
||||
conn.commit()
|
||||
|
||||
|
||||
def rhyme_reset_cooldown(guild_id: str, ratio: float) -> None:
|
||||
def rhyme_reset_cooldown(
|
||||
guild_id: str,
|
||||
ratio: float
|
||||
) -> None:
|
||||
with get_connection() as conn:
|
||||
# Calculate new cooldown duration
|
||||
wait_time = (
|
||||
random.randint(900, 10800)
|
||||
if bool(random.getrandbits(1))
|
||||
else random.randint(0, 900)
|
||||
)
|
||||
wait_time = random.randint(900, 10800) if bool(random.getrandbits(1)) else random.randint(0, 900)
|
||||
wait_time = 0 if ratio < 0 else int(wait_time * ratio)
|
||||
cooldown_until = datetime.now().replace(second=0, microsecond=0) + timedelta(
|
||||
seconds=wait_time
|
||||
)
|
||||
cooldown_until = datetime.now().replace(second=0, microsecond=0) + timedelta(seconds=wait_time)
|
||||
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
RESET_COOLDOWN_QUERY,
|
||||
(
|
||||
cooldown_until.isoformat(),
|
||||
guild_id,
|
||||
),
|
||||
)
|
||||
cursor.execute(RESET_COOLDOWN_QUERY, (cooldown_until.isoformat(), guild_id,))
|
||||
conn.commit()
|
||||
|
||||
|
||||
def get_active_riddle(channel_id: str) -> Any:
|
||||
with get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"SELECT * FROM active_riddles WHERE channel_id = ?", (str(channel_id),)
|
||||
)
|
||||
cursor.execute("SELECT * FROM active_riddles WHERE channel_id = ?", (str(channel_id),))
|
||||
row = cursor.fetchone()
|
||||
|
||||
if row:
|
||||
@ -185,20 +167,14 @@ def save_active_riddle(
|
||||
) -> None:
|
||||
with get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
SAVE_RIDDLE_QUERY,
|
||||
(channel_id, riddle_index, nb_clues, message_id, solver_id),
|
||||
)
|
||||
cursor.execute(SAVE_RIDDLE_QUERY, (channel_id, riddle_index, nb_clues, message_id, solver_id))
|
||||
conn.commit()
|
||||
|
||||
|
||||
def increment_clue(channel_id: str) -> None:
|
||||
with get_connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
INCREMENT_CLUE_QUERY,
|
||||
(channel_id,),
|
||||
)
|
||||
cursor.execute(INCREMENT_CLUE_QUERY, (channel_id,),)
|
||||
conn.commit()
|
||||
|
||||
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
services:
|
||||
perefouras:
|
||||
image: git.epicsparrow.com/anselme/perefouras:latest
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
- DISCORD_TOKEN=${FOURAS_DISCORD_TOKEN}
|
||||
- MAINTAINER_ID=${FOURAS_MAINTAINER_ID:-151626081458192384}
|
||||
restart: always
|
||||
volumes:
|
||||
- ${FOURAS_DATA_DIR}:/app/data
|
||||
- ${FOURAS_DATA_DIR}:/app/data
|
||||
54
fouras.py
54
fouras.py
@ -166,7 +166,7 @@ def get_current_riddle(channel_id):
|
||||
"nbClues": riddle_data["nb_clues"],
|
||||
"riddle": riddles[riddle_data["riddle_index"]].strip(),
|
||||
"answer": answers[riddle_data["riddle_index"]],
|
||||
"data": riddle_data,
|
||||
"data": riddle_data
|
||||
}
|
||||
else:
|
||||
return None
|
||||
@ -174,7 +174,7 @@ def get_current_riddle(channel_id):
|
||||
|
||||
async def handle_riddle_solving(message, client: discord.Client) -> bool:
|
||||
current_riddle = get_current_riddle(message.channel.id)
|
||||
if not current_riddle:
|
||||
if(not current_riddle):
|
||||
return False
|
||||
answer = current_riddle["answer"]
|
||||
riddle_data = current_riddle["data"]
|
||||
@ -190,7 +190,9 @@ async def handle_riddle_solving(message, client: discord.Client) -> bool:
|
||||
solver_id=solver_id,
|
||||
)
|
||||
|
||||
await message.reply(SUCCESS.format(user=message.author.mention, answer=answer))
|
||||
await message.reply(
|
||||
SUCCESS.format(user=message.author.mention, answer=answer)
|
||||
)
|
||||
|
||||
try:
|
||||
original_msg = await message.channel.fetch_message(
|
||||
@ -276,7 +278,7 @@ async def new_riddle(interaction: Interaction, index: int) -> None:
|
||||
riddle_index=index,
|
||||
nb_clues=-1,
|
||||
message_id=msg.message_id,
|
||||
solver_id=None,
|
||||
solver_id=None
|
||||
)
|
||||
|
||||
|
||||
@ -290,20 +292,23 @@ async def update_riddle_message(channel, current_riddle):
|
||||
|
||||
|
||||
def setup_commands(client: discord.Client, tree) -> None:
|
||||
@tree.command(name="fouras", description="Demander une énigme au Père Fouras")
|
||||
@tree.command(
|
||||
name="fouras",
|
||||
description="Demander une énigme au Père Fouras"
|
||||
)
|
||||
async def fouras(
|
||||
interaction: discord.Interaction,
|
||||
):
|
||||
if len(riddles) == 0:
|
||||
await interaction.response.send_message(
|
||||
"Désolé, mais j'ai oublié mes énigmes", ephemeral=True
|
||||
)
|
||||
await interaction.response.send_message("Désolé, mais j'ai oublié mes énigmes", ephemeral=True)
|
||||
else:
|
||||
index = random.randint(0, len(riddles) - 1)
|
||||
await new_riddle(interaction, index)
|
||||
|
||||
|
||||
@tree.command(
|
||||
name="requete", description="Demander une énigme spécifique au Père Fouras"
|
||||
name="requete",
|
||||
description="Demander une énigme spécifique au Père Fouras"
|
||||
)
|
||||
@app_commands.describe(index="Numéro de l'énigme")
|
||||
async def requete(
|
||||
@ -312,24 +317,21 @@ def setup_commands(client: discord.Client, tree) -> None:
|
||||
):
|
||||
index = index - 1
|
||||
if not (0 <= index < len(riddles)):
|
||||
await interaction.response.send_message(
|
||||
INVALID_ID.format(len=len(riddles) + 1), ephemeral=True
|
||||
)
|
||||
await interaction.response.send_message(INVALID_ID.format(len=len(riddles)+1), ephemeral=True)
|
||||
return
|
||||
await new_riddle(interaction, index)
|
||||
|
||||
|
||||
@tree.command(
|
||||
name="repete",
|
||||
description="Demander au Père Fouras de répéter l'énigme en cours",
|
||||
description="Demander au Père Fouras de répéter l'énigme en cours"
|
||||
)
|
||||
async def repete(
|
||||
interaction: discord.Interaction,
|
||||
):
|
||||
current_riddle = get_current_riddle(interaction.channel.id)
|
||||
if not current_riddle:
|
||||
await interaction.response.send_message(
|
||||
"Aucune énigme en cours", ephemeral=True
|
||||
)
|
||||
if(not current_riddle):
|
||||
await interaction.response.send_message("Aucune énigme en cours", ephemeral=True)
|
||||
return
|
||||
riddle_data = current_riddle["data"]
|
||||
msg = await interaction.response.send_message(
|
||||
@ -343,17 +345,17 @@ def setup_commands(client: discord.Client, tree) -> None:
|
||||
solver_id=riddle_data["solver_id"],
|
||||
)
|
||||
|
||||
|
||||
@tree.command(
|
||||
name="indice", description="Demander un indice pour l'énigme en cours"
|
||||
name="indice",
|
||||
description="Demander un indice pour l'énigme en cours"
|
||||
)
|
||||
async def indice(
|
||||
interaction: discord.Interaction,
|
||||
):
|
||||
current_riddle = get_current_riddle(interaction.channel.id)
|
||||
if not current_riddle:
|
||||
await interaction.response.send_message(
|
||||
"Aucune énigme en cours", ephemeral=True
|
||||
)
|
||||
if(not current_riddle):
|
||||
await interaction.response.send_message("Aucune énigme en cours", ephemeral=True)
|
||||
return
|
||||
answer = current_riddle["answer"]
|
||||
riddle_data = current_riddle["data"]
|
||||
@ -364,7 +366,7 @@ def setup_commands(client: discord.Client, tree) -> None:
|
||||
await interaction.response.send_message(
|
||||
"Perdu ! La réponse était : `{0}`".format(answer)
|
||||
)
|
||||
if not await update_riddle_message(interaction.channel, current_riddle):
|
||||
if(not await update_riddle_message(interaction.channel, current_riddle)):
|
||||
return
|
||||
await finish_riddle(interaction.channel, client)
|
||||
else:
|
||||
@ -375,8 +377,6 @@ def setup_commands(client: discord.Client, tree) -> None:
|
||||
message_id=riddle_data["message_id"],
|
||||
solver_id=riddle_data["solver_id"],
|
||||
)
|
||||
if not await update_riddle_message(interaction.channel, current_riddle):
|
||||
if(not await update_riddle_message(interaction.channel, current_riddle)):
|
||||
return
|
||||
await interaction.response.send_message(
|
||||
"Nouvel indice : `{0}`".format(clue_string(answer, nb_clues))
|
||||
)
|
||||
await interaction.response.send_message("Nouvel indice : `{0}`".format(clue_string(answer, nb_clues)))
|
||||
|
||||
27
rhymes.py
27
rhymes.py
@ -76,12 +76,7 @@ async def handle_rhyme_logic(message, client) -> bool:
|
||||
message_content = message.content.lower()
|
||||
last_word = get_last_word(message_content)
|
||||
|
||||
if (
|
||||
not message.author.bot
|
||||
and message.author.id != client.user.id
|
||||
and message.guild
|
||||
and last_word
|
||||
):
|
||||
if not message.author.bot and message.author.id != client.user.id and message.guild and last_word:
|
||||
rhyme = find_rhyme(last_word)
|
||||
guild_id = str(message.guild.id)
|
||||
|
||||
@ -115,27 +110,23 @@ async def handle_message(message, client: discord.Client) -> bool:
|
||||
return await handle_rhyme_logic(message, client)
|
||||
|
||||
|
||||
def setup_rhymes_commands(
|
||||
client: discord.Client, tree: discord.app_commands.CommandTree
|
||||
) -> None:
|
||||
def setup_rhymes_commands(client: discord.Client, tree: discord.app_commands.CommandTree) -> None:
|
||||
@tree.command(
|
||||
name="config",
|
||||
description="Permet de configurer à quel point le Père Fouras est relou",
|
||||
description="Permet de configurer à quel point le Père Fouras est relou"
|
||||
)
|
||||
@app_commands.default_permissions(manage_guild=True)
|
||||
@app_commands.checks.has_permissions(manage_guild=True)
|
||||
@app_commands.describe(ratio="ratio de cooldown (0 = )")
|
||||
async def config(interaction: discord.Interaction, ratio: float):
|
||||
async def config(
|
||||
interaction: discord.Interaction,
|
||||
ratio: float
|
||||
):
|
||||
guild_id: str = str(interaction.guild_id)
|
||||
guild_state = database.get_guild_state(guild_id)
|
||||
database.rhyme_configure_cooldown_ratio(guild_id, ratio)
|
||||
msg = f"Le ratio de cooldown passe de {guild_state['cooldown_ratio']:.2f} à {ratio:.2f} pour le serveur {interaction.guild.name}"
|
||||
if ratio < 0:
|
||||
await interaction.response.send_message(
|
||||
f'{msg}\nLes "poil au" sont désormais désactivés.', ephemeral=True
|
||||
)
|
||||
await interaction.response.send_message(f"{msg}\nLes \"poil au\" sont désormais désactivés.", ephemeral=True)
|
||||
else:
|
||||
await interaction.response.send_message(
|
||||
f'{msg}\nLes "poil au" ont désormais un cooldown entre 0 et {int(180 * ratio)} minutes.',
|
||||
ephemeral=True,
|
||||
)
|
||||
await interaction.response.send_message(f"{msg}\nLes \"poil au\" ont désormais un cooldown entre 0 et {int(180*ratio)} minutes.", ephemeral=True)
|
||||
|
||||
@ -1,58 +1,47 @@
|
||||
```python
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import json
|
||||
|
||||
riddles = []
|
||||
|
||||
|
||||
def scrape_year_data(scrap_year):
|
||||
base_url = "https://www.fan-fortboyard.fr/pages/fanzone/enigmes-du-pere-fouras/"
|
||||
if scrap_year > 2019:
|
||||
url = f"{base_url}enigmes-{scrap_year}.html" # Replace with the actual URL pattern
|
||||
base_url = 'https://www.fan-fortboyard.fr/pages/fanzone/enigmes-du-pere-fouras/'
|
||||
if(scrap_year > 2019):
|
||||
url = f'{base_url}enigmes-{scrap_year}.html' # Replace with the actual URL pattern
|
||||
else:
|
||||
url = f"{base_url}{scrap_year}.html" # Replace with the actual URL pattern
|
||||
url = f'{base_url}{scrap_year}.html' # Replace with the actual URL pattern
|
||||
response = requests.get(url)
|
||||
|
||||
if response.status_code == 200:
|
||||
soup = BeautifulSoup(response.text, "html.parser")
|
||||
|
||||
paragraphs = soup.find_all("p")
|
||||
soup = BeautifulSoup(response.text, 'html.parser')
|
||||
|
||||
paragraphs = soup.find_all('p')
|
||||
|
||||
for paragraph in paragraphs:
|
||||
span = paragraph.find("span")
|
||||
if span and span.find("strong"):
|
||||
strong_tag = span.find("strong")
|
||||
span = paragraph.find('span')
|
||||
if span and span.find('strong'):
|
||||
strong_tag = span.find('strong')
|
||||
if strong_tag and strong_tag.text.strip().isdigit():
|
||||
riddle_count = strong_tag.text.strip()
|
||||
answer_span = paragraph.find_all("span", style=True)
|
||||
answer_span = paragraph.find_all('span', style=True)
|
||||
if answer_span:
|
||||
answer_text = answer_span[-1].get_text(strip=True)
|
||||
riddle_count = strong_tag.text.strip()
|
||||
riddle_text = paragraph.decode_contents()
|
||||
riddle_text = riddle_text.replace("<br/>", "\n").replace(
|
||||
"<br>", "\n"
|
||||
)
|
||||
riddle_text = BeautifulSoup(
|
||||
riddle_text, "html.parser"
|
||||
).get_text(strip=True)
|
||||
riddle_text = riddle_text.split(")", 1)[-1].strip()
|
||||
riddle_text = riddle_text.replace('<br/>', '\n').replace('<br>', '\n')
|
||||
riddle_text = BeautifulSoup(riddle_text, 'html.parser').get_text(strip=True)
|
||||
riddle_text = riddle_text.split(')', 1)[-1].strip()
|
||||
if "RÉPONSE" in riddle_text:
|
||||
riddle_text = riddle_text.split("RÉPONSE", 1)[0].strip()
|
||||
riddles.append(
|
||||
{
|
||||
"riddle": riddle_text,
|
||||
"answer": answer_text,
|
||||
"count": riddle_count,
|
||||
"year": scrap_year,
|
||||
}
|
||||
)
|
||||
riddles.append({'riddle': riddle_text, 'answer': answer_text, 'count': riddle_count, 'year': scrap_year})
|
||||
else:
|
||||
print(f"No answer found : {scrap_year}-{riddle_count}")
|
||||
print(f'No answer found : {scrap_year}-{riddle_count}')
|
||||
else:
|
||||
print(f"Failed to retrieve data for year {year}: {response.status_code}")
|
||||
|
||||
print(f'Failed to retrieve data for year {year}: {response.status_code}')
|
||||
|
||||
for year in range(2007, 2023):
|
||||
scrape_year_data(year)
|
||||
with open("riddles.json", "w", encoding="utf-8") as json_file:
|
||||
scrape_year_data(year)
|
||||
with open('riddles.json', 'w', encoding='utf-8') as json_file:
|
||||
json.dump(riddles, json_file, indent=4, ensure_ascii=False)
|
||||
```
|
||||
Loading…
x
Reference in New Issue
Block a user