1
0
Fork 0

Calendar cache system

This commit is contained in:
Ethanell 2020-05-28 16:52:23 +02:00
parent 3e3e0369fb
commit cd3710b49d
2 changed files with 35 additions and 12 deletions

View file

@ -1,5 +1,5 @@
import re import re
from datetime import datetime, timezone from datetime import datetime, timezone, timedelta
from discord import Embed from discord import Embed
from discord.ext.commands import Bot from discord.ext.commands import Bot
@ -8,7 +8,7 @@ import requests
from sqlalchemy.orm import relationship, Session from sqlalchemy.orm import relationship, Session
from db import Base from db import Base
from sqlalchemy import Column, Integer, String, BigInteger, ForeignKey from sqlalchemy import Column, Integer, String, BigInteger, ForeignKey, Text, DateTime
name_re = re.compile(r"([A-Z]+ [A-Z]+)") name_re = re.compile(r"([A-Z]+ [A-Z]+)")
@ -27,6 +27,8 @@ class Calendar(Base):
resources = Column(Integer, nullable=False) resources = Column(Integer, nullable=False)
project_id = Column(Integer, nullable=False) project_id = Column(Integer, nullable=False)
server = Column(BigInteger, nullable=False) server = Column(BigInteger, nullable=False)
calendar = Column(Text)
calendar_update = Column(DateTime)
calendars_notify = relationship("CalendarNotify", backref="calendar", lazy="subquery") calendars_notify = relationship("CalendarNotify", backref="calendar", lazy="subquery")
@ -36,17 +38,24 @@ class Calendar(Base):
self.project_id = project_id self.project_id = project_id
self.server = server self.server = server
def cal(self, first_date: datetime, last_date: datetime) -> ics.Calendar: def cal(self) -> ics.Calendar:
return ics.Calendar(requests.get(url(self.resources, self.project_id, first_date, last_date)).text) now = datetime.now()
if not self.calendar or self.calendar_update <= now - timedelta(minutes=30):
first_date = now - timedelta(days=now.weekday())
last_date = now + timedelta(days=31)
self.calendar = requests.get(url(self.resources, self.project_id, first_date, last_date)).text
self.calendar_update = now
def events(self, first_date: datetime, last_date: datetime) -> [ics.Event]: return ics.Calendar(self.calendar)
def events(self, first_date: datetime.date, last_date: datetime.date) -> [ics.Event]:
events = [] events = []
for e in sorted(list(self.cal(first_date, last_date).events), key=lambda x: x.begin): for e in sorted(list(self.cal().events), key=lambda x: x.begin):
e.begin = e.begin.replace(tzinfo=timezone.utc).astimezone(tz=None) e.begin = e.begin.replace(tzinfo=timezone.utc).astimezone(tz=None)
e.end = e.begin.replace(tzinfo=timezone.utc).astimezone(tz=None) e.end = e.begin.replace(tzinfo=timezone.utc).astimezone(tz=None)
e.organizer = name_re.findall(e.description)[0] e.organizer = name_re.findall(e.description)[0]
events.append(e) events.append(e)
return events return list(filter(lambda x: x.begin.date() >= first_date and x.end.date() <= last_date, events))
async def notify(self, bot: Bot, event: ics.Event): async def notify(self, bot: Bot, event: ics.Event):
for n in self.calendars_notify: for n in self.calendars_notify:

View file

@ -118,16 +118,21 @@ class Calendar(commands.Cog):
async def calendar_day(self, ctx: commands.Context, name: str, day: str = None): async def calendar_day(self, ctx: commands.Context, name: str, day: str = None):
c = query_calendar(name, ctx.guild.id) c = query_calendar(name, ctx.guild.id)
if day is None: if day is None:
date = datetime.now() date = datetime.now().date()
else: else:
try: try:
date = datetime.strptime(day, "%d/%m/%Y") date = datetime.strptime(day, "%d/%m/%Y").date()
except ValueError: except ValueError:
raise BadArgument() raise BadArgument()
embed = Embed(title=f"Day calendar: {c.name}", description=date.strftime("%d/%m/%Y")) embed = Embed(title=f"Day calendar: {c.name}", description=date.strftime("%d/%m/%Y"))
for e in c.events(date, date): for e in c.events(date, date):
embed.add_field(name=f"{e.begin.strftime('%H:%M')} - {e.end.strftime('%H:%M')}", embed.add_field(name=f"{e.begin.strftime('%H:%M')} - {e.end.strftime('%H:%M')}",
value=f"{e.name} | {e.location} - {e.organizer}", inline=False) value=f"{e.name} | {e.location} - {e.organizer}", inline=False)
s = db.Session()
if s.is_modified(c):
s.add(c)
s.commit()
s.close()
await ctx.send(embed=embed) await ctx.send(embed=embed)
@calendar.group("week", pass_context=True) @calendar.group("week", pass_context=True)
@ -135,10 +140,10 @@ class Calendar(commands.Cog):
async def calendar_week(self, ctx: commands.Context, name: str, day: str = None): async def calendar_week(self, ctx: commands.Context, name: str, day: str = None):
c = query_calendar(name, ctx.guild.id) c = query_calendar(name, ctx.guild.id)
if day is None: if day is None:
date = datetime.now() date = datetime.now().date()
else: else:
try: try:
date = datetime.strptime(day, "%d/%m/%Y") date = datetime.strptime(day, "%d/%m/%Y").date()
except ValueError: except ValueError:
raise BadArgument() raise BadArgument()
date -= timedelta(days=date.weekday()) date -= timedelta(days=date.weekday())
@ -151,6 +156,11 @@ class Calendar(commands.Cog):
f"**{e.name}** | {e.location} - {e.organizer}") f"**{e.name}** | {e.location} - {e.organizer}")
embed.add_field(name=date.strftime("%d/%m/%Y"), value="\n".join(events) or "Nothing !", inline=False) embed.add_field(name=date.strftime("%d/%m/%Y"), value="\n".join(events) or "Nothing !", inline=False)
date = date + timedelta(days=1) date = date + timedelta(days=1)
s = db.Session()
if s.is_modified(c):
s.add(c)
s.commit()
s.close()
await ctx.send(embed=embed) await ctx.send(embed=embed)
@calendar.group("notify", pass_context=True) @calendar.group("notify", pass_context=True)
@ -231,9 +241,13 @@ class Calendar(commands.Cog):
s = db.Session() s = db.Session()
now = datetime.now().replace(tzinfo=timezone.utc).astimezone(tz=None) now = datetime.now().replace(tzinfo=timezone.utc).astimezone(tz=None)
for c in s.query(db.Calendar).all(): for c in s.query(db.Calendar).all():
for e in c.events(now, now): for e in c.events(now.date(), now.date()):
if xor(e.begin >= now - timedelta(minutes=30), e.begin >= now - timedelta(minutes=10)): if xor(e.begin >= now - timedelta(minutes=30), e.begin >= now - timedelta(minutes=10)):
self.bot.loop.create_task(await c.notify(self.bot, e)) self.bot.loop.create_task(await c.notify(self.bot, e))
if s.is_modified(c):
s.add(c)
s.commit()
s.close()
@commands.Cog.listener() @commands.Cog.listener()
async def on_command_error(self, ctx: commands.Context, error): async def on_command_error(self, ctx: commands.Context, error):