Calendar cache system
This commit is contained in:
parent
3e3e0369fb
commit
cd3710b49d
2 changed files with 35 additions and 12 deletions
|
@ -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:
|
||||||
|
|
|
@ -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):
|
||||||
|
|
Reference in a new issue