This commit is contained in:
parent
49ecf081f0
commit
2603be0b5e
20
.drone.yml
Normal file
20
.drone.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
kind: pipeline
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: docker
|
||||
image: plugins/docker
|
||||
settings:
|
||||
repo: git.dryusdan.fr/dryusdan/discord-pschitt
|
||||
tags: latest
|
||||
no_cache: true
|
||||
dry_run: false
|
||||
force_tag: true
|
||||
registry: git.dryusdan.fr
|
||||
username:
|
||||
from_secret: gitea_login
|
||||
password:
|
||||
from_secret: gitea_docker_secret
|
||||
when:
|
||||
branch: stable
|
||||
event: push
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -160,3 +160,4 @@ cython_debug/
|
|||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
config.yml
|
||||
|
|
16
Dockerfile
Normal file
16
Dockerfile
Normal file
|
@ -0,0 +1,16 @@
|
|||
FROM python:3.11-alpine
|
||||
|
||||
COPY ./ /app
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV TZ Europe/Paris
|
||||
|
||||
RUN cp /usr/share/zoneinfo/$TZ /etc/localtime \
|
||||
&& echo $TZ > /etc/timezone \
|
||||
&& apk add -U --no-cache --virtual builds gcc musl-dev libffi-dev \
|
||||
&& pip3 install poetry \
|
||||
&& poetry install --only main \
|
||||
&& apk del builds
|
||||
|
||||
CMD poetry run python3 src/main.py
|
5
db.sql
Normal file
5
db.sql
Normal file
|
@ -0,0 +1,5 @@
|
|||
CREATE TABLE pschitt (
|
||||
id BIGINT NOT NULL PRIMARY KEY,
|
||||
guild_id BIGINT NOT NULL,
|
||||
datetime timestamp with time zone DEFAULT now()
|
||||
);
|
1043
poetry.lock
generated
Normal file
1043
poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
24
pyproject.toml
Normal file
24
pyproject.toml
Normal file
|
@ -0,0 +1,24 @@
|
|||
[tool.poetry]
|
||||
name = "-"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Dryusdan <contact@dryusdan.fr>"]
|
||||
license = "GPL-3"
|
||||
readme = "README.md"
|
||||
packages = [{include = "src"}]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.11"
|
||||
discord-py = "^2.3.2"
|
||||
python-dotenv = "^1.0.0"
|
||||
emoji = "^2.9.0"
|
||||
pydantic = "^2.5.3"
|
||||
sqlalchemy = "^2.0.25"
|
||||
psycopg2-binary = "^2.9.9"
|
||||
pendulum = "^3.0.0"
|
||||
pyyaml = "^6.0.1"
|
||||
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
16
src/logs.py
Normal file
16
src/logs.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
import logging
|
||||
|
||||
|
||||
class Log:
|
||||
def __new__(self, name):
|
||||
log = logging.getLogger(name=name)
|
||||
log.setLevel(logging.DEBUG)
|
||||
formatter = logging.Formatter(
|
||||
"%(asctime)s - [%(name)s] [%(levelname)s] - %(message)s"
|
||||
)
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(formatter)
|
||||
|
||||
log.addHandler(handler)
|
||||
|
||||
return log
|
76
src/main.py
Normal file
76
src/main.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import discord
|
||||
import emoji
|
||||
import pendulum
|
||||
import sqlalchemy
|
||||
|
||||
from discord import app_commands
|
||||
from discord.ext import commands
|
||||
from discord.utils import get
|
||||
from src.sql.database import engine_rw as engine
|
||||
from src.sql.controllers.pschitt_user import PschittUser
|
||||
from src.sql.models.pschitt import PschittUserBase, PschittUserModel, PschittBase
|
||||
from src.logs import Log
|
||||
from src.settings import Settings
|
||||
|
||||
|
||||
import pprint
|
||||
|
||||
log = Log("main")
|
||||
settings = Settings().get_config()
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
intents.reactions = True
|
||||
|
||||
class DiscordClient(discord.Client):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
intents=discord.Intents.all(), application_id=settings["discord"]["app_id"]
|
||||
)
|
||||
self.synced = False
|
||||
if not sqlalchemy.inspect(engine).has_table("pschitt_datetime"):
|
||||
log.warning("Creating table")
|
||||
log.info("Load tables")
|
||||
from src.sql.schemas.pschitt import Pschitt, PschittUser
|
||||
log.info("Create PschittUser")
|
||||
PschittUser.__table__.create(bind=engine, checkfirst=True)
|
||||
log.info("Create Pschitt")
|
||||
Pschitt.__table__.create(bind=engine, checkfirst=True)
|
||||
|
||||
|
||||
async def on_ready(self):
|
||||
await self.wait_until_ready()
|
||||
if not self.synced:
|
||||
await tree.sync(guild=discord.Object(id=settings["discord"]["guild_id"]))
|
||||
self.synced = True
|
||||
|
||||
|
||||
client = DiscordClient()
|
||||
tree = app_commands.CommandTree(client)
|
||||
|
||||
|
||||
@tree.command(
|
||||
name="pschitt",
|
||||
description="Ajout d'une crevaison",
|
||||
guild=discord.Object(id=settings["discord"]["guild_id"]),
|
||||
)
|
||||
async def pschitt(interaction: discord.Interaction):
|
||||
member_id = interaction.user.id
|
||||
pschitt_user = PschittUser(user_id=member_id, guild_id=interaction.guild_id)
|
||||
if not pschitt_user.is_registered():
|
||||
if pschitt_user.register():
|
||||
log.info(f"User {member_id} is now registered")
|
||||
else:
|
||||
pass
|
||||
pschitt_user.get()
|
||||
pschitt_user.add_point()
|
||||
total_pschitt = len(pschitt_user.pschitt)
|
||||
await interaction.response.send_message(
|
||||
f"<@{member_id}> à crevé-e ! :pschitt: "
|
||||
)
|
||||
await interaction.followup.send(f"Ça fait un total de {total_pschitt} crevaison(s)")
|
||||
|
||||
|
||||
client.run(token=settings["discord"]["token"])
|
52
src/settings.py
Normal file
52
src/settings.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
from src.logs import Log
|
||||
from os import path
|
||||
|
||||
log = Log("settings")
|
||||
|
||||
|
||||
class Settings:
|
||||
def get_config(self):
|
||||
if path.exists("config.yml"):
|
||||
import yaml
|
||||
|
||||
log.info("Found config.yml. Load it")
|
||||
with open("config.yml", "r") as yamlfile:
|
||||
config = yaml.load(yamlfile, Loader=yaml.FullLoader)
|
||||
log.info("Config read successful")
|
||||
else:
|
||||
log.warning("Config file not found, fallback to environment var")
|
||||
from dotenv import load_dotenv
|
||||
from os import environ, getenv
|
||||
|
||||
load_dotenv()
|
||||
if "DB_HOST" not in environ:
|
||||
log.critical("DB_HOST environment variable don't exist")
|
||||
if "DB_PORT" not in environ:
|
||||
log.critical("DB_PORT environment variable don't exist")
|
||||
if "DB_NAME" not in environ:
|
||||
log.critical("DB_NAME environment variable don't exist")
|
||||
if "DB_USER" not in environ:
|
||||
log.critical("DB_USER environment variable don't exist")
|
||||
if "DB_PASS" not in environ:
|
||||
log.critical("DB_PASS environment variable don't exist")
|
||||
if "DISCORD_TOKEN" not in environ:
|
||||
log.critical("DISCORD_TOKEN environment variable don't exist")
|
||||
if "DISCORD_APP_ID" not in environ:
|
||||
log.critical("DISCORD_APP_ID environment variable don't exist")
|
||||
if "DISCORD_GUILD_ID" not in environ:
|
||||
log.critical("DISCORD_GUILD_ID environment variable don't exist")
|
||||
config = {
|
||||
"db": {
|
||||
"host": getenv("DB_HOST"),
|
||||
"port": getenv("DB_PORT"),
|
||||
"dbname": getenv("DB_NAME"),
|
||||
"user": getenv("DB_USER"),
|
||||
"password": getenv("DB_PASS"),
|
||||
},
|
||||
"discord": {
|
||||
"token": getenv("DISCORD_TOKEN"),
|
||||
"app_id": getenv("DISCORD_APP_ID"),
|
||||
"guild_id": getenv("DISCORD_GUILD_ID"),
|
||||
},
|
||||
}
|
||||
return config
|
66
src/sql/controllers/pschitt_user.py
Normal file
66
src/sql/controllers/pschitt_user.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
import pendulum
|
||||
import sys
|
||||
|
||||
from src.sql.cruds.pschitt import PschittCrud
|
||||
from src.sql.cruds.pschitt_user import PschittUserCrud
|
||||
from src.sql.models.pschitt import PschittUserBase, PschittUserModel, PschittBase
|
||||
from src.logs import Log
|
||||
from src.settings import Settings
|
||||
|
||||
import pprint
|
||||
|
||||
log = Log("controllers_pschitt")
|
||||
config = Settings().get_config()
|
||||
|
||||
|
||||
class PschittUser(object):
|
||||
def __init__(self, user_id, guild_id):
|
||||
self.id = None
|
||||
self.user_id = user_id
|
||||
self.guild_id = guild_id
|
||||
self.pschitt = []
|
||||
return
|
||||
|
||||
def get(self):
|
||||
if self.is_registered():
|
||||
pschitt_user = PschittUserBase(user_id=self.user_id, guild_id=self.guild_id)
|
||||
user = PschittUserCrud.get_user(pschitt_user)
|
||||
self.id = user.id
|
||||
self.user_id = user.user_id
|
||||
self.guild_id = user.guild_id
|
||||
self.pschitt = user.pschitt
|
||||
else:
|
||||
return PschittBase(user_id=self.user_id, guild_id=self.guild_id)
|
||||
|
||||
def is_registered(self):
|
||||
pschitt_user = PschittUserBase(user_id=self.user_id, guild_id=self.guild_id)
|
||||
if PschittUserCrud.get_user(pschitt_user):
|
||||
return True
|
||||
else:
|
||||
log.error(f"This user ({self.user_id}) doesn't exist.")
|
||||
return False
|
||||
|
||||
def register(self):
|
||||
pschitt_user = PschittUserBase(user_id=self.user_id, guild_id=self.guild_id)
|
||||
request = PschittUserCrud.create_user(pschitt_user)
|
||||
if request:
|
||||
log.info(f"User {self.user_id} registered")
|
||||
return True
|
||||
else:
|
||||
log.error(f"An error occured to register user {id}")
|
||||
return False
|
||||
|
||||
def add_point(self):
|
||||
pschitt = PschittBase(pschitt_user_id=self.id)
|
||||
PschittCrud.create_pschitt(pschitt)
|
||||
self.get()
|
||||
return
|
||||
|
||||
def delete(self):
|
||||
guild = guildBase(guild_id=self.guild_id, channel_id=self.channel_id)
|
||||
request = guildCrud.delete_guild(guild)
|
||||
if request["deleted"] > 0:
|
||||
log.info(f"Guild {self.guild_id} was correctly remove")
|
||||
else:
|
||||
log.error(f"An error occured on guild {self.guild_id} deletion")
|
||||
return
|
20
src/sql/cruds/pschitt.py
Normal file
20
src/sql/cruds/pschitt.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
from src.logs import Log
|
||||
from src.settings import Settings
|
||||
from src.sql.models.pschitt import PschittUserBase, PschittUserModel, PschittBase
|
||||
from src.sql.schemas.pschitt import Pschitt, PschittUser
|
||||
from src.sql.database import SessionLocalRo, SessionLocalRw
|
||||
from sqlalchemy import desc, text
|
||||
|
||||
log = Log("crud_PschittUser")
|
||||
config = Settings().get_config()
|
||||
|
||||
|
||||
class PschittCrud:
|
||||
@staticmethod
|
||||
def create_pschitt(pschitt: PschittBase):
|
||||
pschitt_schema = Pschitt(pschitt_user_id=pschitt.pschitt_user_id)
|
||||
with SessionLocalRw() as session:
|
||||
session.add(pschitt_schema)
|
||||
session.commit()
|
||||
return True
|
||||
|
68
src/sql/cruds/pschitt_user.py
Normal file
68
src/sql/cruds/pschitt_user.py
Normal file
|
@ -0,0 +1,68 @@
|
|||
from src.logs import Log
|
||||
from src.settings import Settings
|
||||
from src.sql.models.pschitt import PschittUserBase, PschittUserModel, PschittBase
|
||||
from src.sql.schemas.pschitt import Pschitt, PschittUser
|
||||
from src.sql.database import SessionLocalRo, SessionLocalRw
|
||||
from sqlalchemy import desc, text
|
||||
|
||||
log = Log("crud_PschittUser")
|
||||
config = Settings().get_config()
|
||||
|
||||
|
||||
class PschittUserCrud:
|
||||
@staticmethod
|
||||
def get_user_by_id(user_id: int):
|
||||
"""get_user_by_id.
|
||||
|
||||
:param user_id:
|
||||
:type user_id: int
|
||||
"""
|
||||
with SessionLocalRo() as session:
|
||||
return session.query(PschittUser).filter(id == user_id).first()
|
||||
return user
|
||||
|
||||
@staticmethod
|
||||
def get_all_users():
|
||||
"""get_all_users"""
|
||||
with SessionLocalRo() as session:
|
||||
return session.query(PschittUser).order_by(desc("point")).all()
|
||||
|
||||
@staticmethod
|
||||
def get_user(user: PschittUserBase):
|
||||
"""get_user.
|
||||
|
||||
:param user:
|
||||
:type user: PschittUserBase
|
||||
"""
|
||||
with SessionLocalRo() as session:
|
||||
return session.query(PschittUser).filter(PschittUser.user_id == user.user_id).first()
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_users():
|
||||
return user
|
||||
|
||||
@staticmethod
|
||||
def create_user(user: PschittUserBase):
|
||||
user_schema = PschittUser(user_id=user.user_id, guild_id=user.guild_id)
|
||||
with SessionLocalRw() as session:
|
||||
session.add(user_schema)
|
||||
session.commit()
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def update_user(user: PschittUserModel):
|
||||
with SessionLocalRw() as session:
|
||||
biketag_user = (
|
||||
session.query(PschittUser).filter(PschittUser.user_id == user.id).first()
|
||||
)
|
||||
biketag_user.point = user.point
|
||||
session.commit()
|
||||
session.refresh(biketag_user)
|
||||
return biketag_user
|
||||
return
|
||||
|
||||
@staticmethod
|
||||
def delete_user(user: PschittUserBase):
|
||||
return user
|
||||
|
51
src/sql/database.py
Normal file
51
src/sql/database.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from src.logs import Log
|
||||
from src.settings import Settings
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.pool import NullPool
|
||||
|
||||
log = Log("database")
|
||||
config = Settings().get_config()
|
||||
|
||||
SQLALCHEMY_DATABASE_URL_RW = "postgresql://{user}:{password}@{host}:{port}/{db}".format(
|
||||
user=config["db"]["user"],
|
||||
password=config["db"]["password"],
|
||||
host=config["db"]["host"],
|
||||
port=config["db"]["port"],
|
||||
db=config["db"]["dbname"],
|
||||
autoconnect=False,
|
||||
)
|
||||
|
||||
engine_rw = create_engine(
|
||||
SQLALCHEMY_DATABASE_URL_RW,
|
||||
echo=False,
|
||||
poolclass=NullPool,
|
||||
)
|
||||
|
||||
SessionLocalRw = sessionmaker(
|
||||
autocommit=False, autoflush=False, expire_on_commit=False, bind=engine_rw
|
||||
)
|
||||
|
||||
SQLALCHEMY_DATABASE_URL_RO = "postgresql://{user}:{password}@{host}:{port}/{db}".format(
|
||||
user=config["db"]["user"],
|
||||
password=config["db"]["password"],
|
||||
host=config["db"]["host"],
|
||||
port=config["db"]["port"],
|
||||
db=config["db"]["dbname"],
|
||||
autoconnect=False,
|
||||
)
|
||||
|
||||
engine_ro = create_engine(
|
||||
SQLALCHEMY_DATABASE_URL_RO,
|
||||
echo=False,
|
||||
poolclass=NullPool,
|
||||
)
|
||||
|
||||
SessionLocalRo = sessionmaker(
|
||||
autocommit=False, autoflush=False, expire_on_commit=False, bind=engine_ro
|
||||
)
|
||||
|
||||
Base = declarative_base()
|
29
src/sql/models/pschitt.py
Normal file
29
src/sql/models/pschitt.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class PschittUserBase(BaseModel):
|
||||
user_id: int
|
||||
guild_id: int
|
||||
|
||||
class Config:
|
||||
"""Config."""
|
||||
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class PschittUserModel(PschittUserBase):
|
||||
id: int
|
||||
pschitt: list
|
||||
pass
|
||||
|
||||
class PschittBase(BaseModel):
|
||||
pschitt_user_id: int
|
||||
class Config:
|
||||
"""Config."""
|
||||
|
||||
orm_mode = True
|
||||
|
||||
class PschittModel(PschittBase):
|
||||
id: int
|
||||
datetime: datetime
|
49
src/sql/schemas/pschitt.py
Normal file
49
src/sql/schemas/pschitt.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
import pendulum
|
||||
from sqlalchemy import Column, BigInteger, DateTime, ForeignKey, Table
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy.sql import func
|
||||
from typing import List, Optional
|
||||
|
||||
from src.sql.database import Base
|
||||
|
||||
#pschitt_association_table = Table(
|
||||
# "pschitt",
|
||||
# Base.metadata,
|
||||
# Column("pschitt_user_id", ForeignKey("pschitt_user.id")),
|
||||
# Column("pschitt_datetime_id", ForeignKey("pschitt_datetime.id")),
|
||||
#)
|
||||
|
||||
#association_table = Table(
|
||||
# "association_table",
|
||||
# Base.metadata,
|
||||
# Column("pschitt_user_id", ForeignKey("pschitt_user.id"), primary_key=True),
|
||||
# Column("pschitt_datetime_id", ForeignKey("pschitt_datetime.id"), primary_key=True),
|
||||
#)
|
||||
|
||||
#class PschittAssociation(Base):
|
||||
# """PschittAssociation"""
|
||||
#
|
||||
# __tablename__ = "pschitt"
|
||||
# __allow_unmapped__ = True
|
||||
# Base.metadata,
|
||||
# pschitt_user_id: Column(BigInteger, ForeignKey("pschitt_user.id"), primary_key=True)
|
||||
# pschitt_datetime_id: Column(BigInteger, ForeignKey("pschitt_datetime.id"), primary_key=True)
|
||||
|
||||
class Pschitt(Base):
|
||||
"""Pschitt"""
|
||||
|
||||
__tablename__ = "pschitt_datetime"
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
pschitt_user_id: Mapped[int] = mapped_column(ForeignKey("pschitt_user.id"))
|
||||
datetime = Column('date', DateTime(timezone=True), server_default=func.now(), nullable=False)
|
||||
pschitt_user: Mapped[List["PschittUser"]] = relationship(back_populates="pschitt")
|
||||
|
||||
class PschittUser(Base):
|
||||
"""Pschitt"""
|
||||
|
||||
__tablename__ = "pschitt_user"
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
user_id = Column(BigInteger, nullable=False, unique=True)
|
||||
guild_id = Column(BigInteger, nullable=False)
|
||||
pschitt: Mapped[List["Pschitt"]] = relationship(back_populates="pschitt_user", lazy="immediate")
|
||||
|
7
src/sql/schemas/pschitt_user.py
Normal file
7
src/sql/schemas/pschitt_user.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from sqlalchemy import Column, BigInteger, DateTime, ForeignKey
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from typing import List
|
||||
|
||||
from src.sql.database import Base
|
||||
|
||||
|
Loading…
Reference in a new issue