diff --git a/db/Calendar.py b/db/Calendar.py new file mode 100644 index 0000000..dfb0989 --- /dev/null +++ b/db/Calendar.py @@ -0,0 +1,17 @@ +from db import Base +from sqlalchemy import Column, Integer, String, BigInteger + + +class Calendar(Base): + __tablename__ = "calendars" + id = Column(Integer, primary_key=True) + name = Column(String, nullable=False) + resources = Column(Integer, nullable=False) + project_id = Column(Integer, nullable=False) + server = Column(BigInteger, nullable=False) + + def __init__(self, name: str, resources: int, project_id: int, server: int): + self.name = name + self.resources = resources + self.project_id = project_id + self.server = server diff --git a/db/__init__.py b/db/__init__.py index 96eaebb..3fd40b3 100644 --- a/db/__init__.py +++ b/db/__init__.py @@ -1,12 +1,8 @@ -from administrator.config import config +from bot_bde.config import config from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base -db = config.get("db") -args = {"pool_pre_ping": True, "pool_recycle": 3600} -if not db.startswith("sqlite:"): - args.update({"pool_size": 0, "max_overflow": -1}) -engine = create_engine(db, **args) +engine = create_engine(config.get("db")) Session = sessionmaker(bind=engine) Base = declarative_base() from db.Task import Task @@ -20,4 +16,5 @@ from db.InviteRole import InviteRole from db.Tomuss import Tomuss from db.PCP import PCP from db.Extension import Extension, ExtensionState +from db.Calendar import Calendar Base.metadata.create_all(engine) diff --git a/extensions/__init__.py b/extensions/__init__.py index 2c84dbe..7418384 100644 --- a/extensions/__init__.py +++ b/extensions/__init__.py @@ -1,6 +1,7 @@ -from administrator import bot +from bot_bde import bot bot.load_extension("extensions.help") +bot.load_extension("extensions.speak") bot.load_extension("extensions.extension") bot.load_extension("extensions.purge") bot.load_extension("extensions.poll") @@ -15,3 +16,4 @@ bot.load_extension("extensions.invite") bot.load_extension("extensions.speak") bot.load_extension("extensions.utils") bot.load_extension("extensions.tomuss") +bot.load_extension("extensions.calendar") diff --git a/extensions/calendar.py b/extensions/calendar.py new file mode 100644 index 0000000..1e93a66 --- /dev/null +++ b/extensions/calendar.py @@ -0,0 +1,107 @@ +import ics +import re +import requests +from discord import Embed +from discord.ext import commands +from discord.ext.commands import CommandNotFound, BadArgument, MissingRequiredArgument + +from bot_bde import db +from bot_bde.logger import logger + +extension_name = "calendar" +logger = logger.getChild(extension_name) +url_re = re.compile(r"http:\/\/adelb\.univ-lyon1\.fr\/jsp\/custom\/modules\/plannings\/anonymous_cal\.jsp\?resources=" + r"([0-9]+)&projectId=([0-9]+)") + + +class Calendar(commands.Cog): + def __init__(self, bot: commands.Bot): + self.bot = bot + + @commands.group("calendar", pass_context=True) + async def calendar(self, ctx: commands.Context): + if ctx.invoked_subcommand is None: + await ctx.invoke(self.calendar_help) + + @calendar.group("help", pass_context=True) + async def calendar_help(self, ctx: commands.Context): + embed = Embed(title="Calendar help") + embed.add_field(name="calendar define ", value="Define a calendar\n", inline=False) + await ctx.send(embed=embed) + + @calendar.group("define", pass_context=True) + async def calendar_define(self, ctx: commands.Context, name: str, url: str): + try: + ics.Calendar(requests.get(url).text) + except Exception: + raise BadArgument() + m = url_re.findall(url) + if not m: + raise BadArgument() + + s = db.Session() + if s.query(db.Calendar).filter(db.Calendar.server == ctx.guild.id and db.Calendar.name == name).first(): + s.close() + raise BadArgument() + s.add(db.Calendar(name, int(m[0][0]), int(m[0][0]), ctx.guild.id)) + s.commit() + s.close() + await ctx.message.add_reaction("\U0001f44d") + + @calendar.group("list", pass_context=True) + async def calendar_list(self, ctx: commands.Context): + embed = Embed(title="Calendar list") + s = db.Session() + for c in s.query(db.Calendar).filter(db.Calendar.server == ctx.guild.id).all(): + embed.add_field(name=c.name, value=f"resources: {c.resources} | project id: {c.project_id}", inline=False) + s.close() + await ctx.send(embed=embed) + + @calendar.group("remove", pass_context=True) + async def calendar_remove(self, ctx: commands.Context, name: str = None): + if name is None: + await ctx.invoke(self.calendar_list) + else: + s = db.Session() + c = s.query(db.Calendar).filter(db.Calendar.server == ctx.guild.id and db.Calendar.name == name).first() + if c: + s.delete(c) + s.commit() + s.close() + await ctx.message.add_reaction("\U0001f44d") + else: + s.close() + raise BadArgument() + + @commands.Cog.listener() + async def on_command_error(self, ctx: commands.Context, error): + if ctx.invoked_with == extension_name or \ + (ctx.command.root_parent and ctx.command.root_parent.name == extension_name): + if isinstance(error, CommandNotFound) \ + or isinstance(error, BadArgument) \ + or isinstance(error, MissingRequiredArgument): + await ctx.message.add_reaction("\u2753") + await ctx.message.delete(delay=30) + else: + await ctx.send("An error occurred !") + raise error + + +def setup(bot): + logger.info(f"Loading...") + try: + bot.add_cog(Calendar(bot)) + except Exception as e: + logger.error(f"Error loading: {e}") + else: + logger.info(f"Load successful") + + +def teardown(bot): + logger.info(f"Unloading...") + try: + bot.remove_cog("Calendar") + except Exception as e: + logger.error(f"Error unloading: {e}") + else: + logger.info(f"Unload successful") diff --git a/requirements.txt b/requirements.txt index 8f95633..8f11747 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -aiohttp==3.6.3 +aiohttp==3.6.2 async-timeout==3.0.1 -attrs==20.2.0 +attrs==19.3.0 chardet==3.0.4 discord==1.0.1 discord-py-slash-command==1.0.8.5 @@ -11,3 +11,6 @@ multidict==4.7.6 sgmllib3k==1.0.0 SQLAlchemy==1.3.20 yarl==1.5.1 +websockets==8.1 +ics~=0.7 +requests~=2.23.0