Make bot
Some checks failed
continuous-integration/drone Build is failing

This commit is contained in:
Dryusdan 2024-01-04 17:13:21 +01:00
parent 49ecf081f0
commit 2603be0b5e
Signed by: Dryusdan
GPG key ID: EC1438DDE24E27D7
16 changed files with 1543 additions and 0 deletions

20
.drone.yml Normal file
View 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
View file

@ -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
View 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
View 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

File diff suppressed because it is too large Load diff

24
pyproject.toml Normal file
View 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
View 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
View 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
View 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

View 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
View 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

View 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
View 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
View 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

View 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")

View 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