Rework calendar and edt function
This commit is contained in:
parent
c0a5f37215
commit
0d97422850
2 changed files with 86 additions and 60 deletions
38
EDTcalendar.py
Normal file
38
EDTcalendar.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import datetime
|
||||||
|
import ics
|
||||||
|
import requests
|
||||||
|
from ics.timeline import Timeline
|
||||||
|
from aiogram.utils import markdown
|
||||||
|
|
||||||
|
|
||||||
|
class Calendar(ics.Calendar):
|
||||||
|
def __init__(self, url: list, firstdate: datetime.date, lastdate: datetime.date):
|
||||||
|
super().__init__(requests.get(
|
||||||
|
f"{url[0]}?resources={url[1]}&projectId={url[2]}&calType=ical&firstDate={firstdate}&lastDate={lastdate}"
|
||||||
|
).text)
|
||||||
|
events = set()
|
||||||
|
for e in self.events:
|
||||||
|
events.add(Event(e))
|
||||||
|
self.events = events
|
||||||
|
|
||||||
|
self.timeline = Timeline(self)
|
||||||
|
|
||||||
|
|
||||||
|
class Event(ics.Event):
|
||||||
|
def __init__(self, event: ics.Event):
|
||||||
|
super().__init__()
|
||||||
|
for v in event.__dict__:
|
||||||
|
setattr(self, v, event.__dict__[v])
|
||||||
|
|
||||||
|
self.begin = self.begin.datetime.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None)
|
||||||
|
self.end = self.end.datetime.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None)
|
||||||
|
self.organizer = self.description.split('\n')[3]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return markdown.text(
|
||||||
|
markdown.bold(f"<{str(self.begin.date())[5:]}>"),
|
||||||
|
markdown.code(f"📓[{self.name}]:"),
|
||||||
|
markdown.text(f"⌚️ {str(self.begin.time())[:-3]} -> {str(self.end.time())[:-3]}"),
|
||||||
|
markdown.italic(f"📍 {self.location} 👨🏫 {self.organizer}"),
|
||||||
|
sep="\n"
|
||||||
|
)
|
108
bot.py
108
bot.py
|
@ -12,9 +12,8 @@ from aiogram import Bot, Dispatcher, executor, types
|
||||||
from aiogram.types import InlineQuery, InputTextMessageContent, InlineQueryResultArticle, ParseMode, reply_keyboard
|
from aiogram.types import InlineQuery, InputTextMessageContent, InlineQueryResultArticle, ParseMode, reply_keyboard
|
||||||
from aiogram.utils import markdown
|
from aiogram.utils import markdown
|
||||||
from aiogram.utils.exceptions import MessageIsTooLong
|
from aiogram.utils.exceptions import MessageIsTooLong
|
||||||
from ics import Calendar
|
from EDTcalendar import Calendar
|
||||||
from ics.parse import ParseError
|
from ics.parse import ParseError
|
||||||
from requests import get
|
|
||||||
from requests.exceptions import ConnectionError, InvalidSchema, MissingSchema
|
from requests.exceptions import ConnectionError, InvalidSchema, MissingSchema
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,50 +33,47 @@ if not isfile("token.ini"):
|
||||||
exit(1)
|
exit(1)
|
||||||
API_TOKEN = open("token.ini").read()
|
API_TOKEN = open("token.ini").read()
|
||||||
ADMIN_ID = 148441652
|
ADMIN_ID = 148441652
|
||||||
|
TIMES = ["", "day", "next", "week", "next week"]
|
||||||
|
URL = "http://adelb.univ-lyon1.fr/jsp/custom/modules/plannings/anonymous_cal.jsp"
|
||||||
|
PROJECT_ID = 4
|
||||||
|
|
||||||
bot = Bot(token=API_TOKEN)
|
bot = Bot(token=API_TOKEN)
|
||||||
dp = Dispatcher(bot)
|
dp = Dispatcher(bot)
|
||||||
dbL = RLock()
|
dbL = RLock()
|
||||||
|
|
||||||
|
|
||||||
def edt(text, user_id):
|
def edt(time: str, user_id: int):
|
||||||
with dbL:
|
with dbL:
|
||||||
with shelve.open("edt", writeback=True) as db:
|
with shelve.open("edt", writeback=True) as db:
|
||||||
if str(user_id) not in db or "url" not in db[str(user_id)]:
|
if str(user_id) not in db or "resources" not in db[str(user_id)]:
|
||||||
return markdown.bold("Your EDT is not set ! ❌")
|
return markdown.bold("Your EDT is not set ! ❌")
|
||||||
now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
|
now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
|
||||||
if text.lower() == "week":
|
|
||||||
firstdate = now.date() - datetime.timedelta(days=now.isoweekday()-1)
|
if now.isoweekday() in [6, 7]:
|
||||||
lastdate = now.date() + datetime.timedelta(days=(7 - now.isoweekday()))
|
now += datetime.timedelta(days=(7 - (now.isoweekday() - 1)))
|
||||||
elif text.lower() == "next":
|
|
||||||
now += datetime.timedelta(days=7)
|
dates = {
|
||||||
firstdate = now.date() - datetime.timedelta(days=now.isoweekday())
|
"": [0, 0],
|
||||||
lastdate = now.date() + datetime.timedelta(days=(7 - now.isoweekday()))
|
"day": [0, 0],
|
||||||
elif text == "" or text.lower() == "day":
|
"next": [1, 1],
|
||||||
firstdate, lastdate = now.date(), now.date()
|
"week": [-(now.isoweekday() - 1), 7 - now.isoweekday()],
|
||||||
else:
|
"next week": [7-(now.isoweekday() - 1), 7 + (7 - now.isoweekday())]
|
||||||
|
}
|
||||||
|
if time not in TIMES:
|
||||||
return markdown.bold("Invalid choice ! ❌")
|
return markdown.bold("Invalid choice ! ❌")
|
||||||
|
|
||||||
url = f"{db[str(user_id)]['url']}&firstDate={firstdate}&lastDate={lastdate}"
|
firstdate = now.date() + datetime.timedelta(days=dates[time][0])
|
||||||
c = Calendar(get(url).text)
|
lastdate = now.date() + datetime.timedelta(days=dates[time][1])
|
||||||
msg = list()
|
|
||||||
days = list()
|
c = Calendar([URL, db[str(user_id)]["resources"], PROJECT_ID], firstdate, lastdate)
|
||||||
|
msg = str()
|
||||||
|
|
||||||
for e in list(c.timeline):
|
for e in list(c.timeline):
|
||||||
begin = e.begin.datetime.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None)
|
msg += (str(e)[10:] if str(e.begin.date())[5:] in msg else str(e)) + "\n\n"
|
||||||
end = e.end.datetime.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None)
|
|
||||||
if begin.date() not in days:
|
|
||||||
days.append(begin.date())
|
|
||||||
msg.append(markdown.bold(f"<{str(begin.date())[5:]}>"))
|
|
||||||
|
|
||||||
msg.append(markdown.code(f"📓[{e.name}]:"))
|
|
||||||
msg.append(markdown.text(f"⌚️ {str(begin.time())[:-3]} -> {str(end.time())[:-3]}"))
|
|
||||||
prof = markdown.text(e.description.split('\n')[3])
|
|
||||||
msg.append(markdown.italic(f"📍 {e.location} 👨🏫 {prof}" + "\n"))
|
|
||||||
|
|
||||||
if len(msg) == 0:
|
if len(msg) == 0:
|
||||||
msg.append(markdown.italic("but nobody came..."))
|
msg += markdown.italic("but nobody came...")
|
||||||
return markdown.text(*msg, sep="\n")
|
return msg
|
||||||
|
|
||||||
|
|
||||||
async def notif():
|
async def notif():
|
||||||
|
@ -85,12 +81,11 @@ async def notif():
|
||||||
with dbL:
|
with dbL:
|
||||||
with shelve.open("edt", writeback=True) as db:
|
with shelve.open("edt", writeback=True) as db:
|
||||||
for u in db:
|
for u in db:
|
||||||
if ("url" in db[u]) and ("notif" in db[u]) and (db[u]["notif"]["state"]):
|
if ("resources" in db[u]) and ("notif" in db[u]) and (db[u]["notif"]["state"]):
|
||||||
now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
|
now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
|
||||||
c = Calendar(get(f"{db[u]['url']}&firstDate={now.date()}&lastDate={now.date()}").text)
|
c = Calendar([URL, db[u]["resources"], PROJECT_ID], now.date(), now.date())
|
||||||
for e in c.events:
|
for e in c.events:
|
||||||
event = e.begin.datetime.replace(tzinfo=datetime.timezone.utc).astimezone(tz=None)
|
if (e.begin - now).seconds/60 <= db[u]["notif"]["time"] and\
|
||||||
if (event - now).seconds/60 <= db[u]["notif"]["time"] and\
|
|
||||||
(now - db[u]["notif"]["last"]).seconds/60 >= db[u]["notif"]["cooldown"]:
|
(now - db[u]["notif"]["last"]).seconds/60 >= db[u]["notif"]["cooldown"]:
|
||||||
db[u]["notif"]["last"] = now
|
db[u]["notif"]["last"] = now
|
||||||
|
|
||||||
|
@ -98,7 +93,7 @@ async def notif():
|
||||||
markdown.text("🔔"),
|
markdown.text("🔔"),
|
||||||
markdown.code(e.name),
|
markdown.code(e.name),
|
||||||
markdown.text("in"),
|
markdown.text("in"),
|
||||||
markdown.bold((event - now).seconds//60),
|
markdown.bold((e.begin - now).seconds//60),
|
||||||
markdown.text("minutes !"),
|
markdown.text("minutes !"),
|
||||||
sep="\n"
|
sep="\n"
|
||||||
)
|
)
|
||||||
|
@ -108,8 +103,8 @@ async def notif():
|
||||||
|
|
||||||
@dp.inline_handler()
|
@dp.inline_handler()
|
||||||
async def inline_echo(inline_query: InlineQuery):
|
async def inline_echo(inline_query: InlineQuery):
|
||||||
text = inline_query.query
|
text = inline_query.query.lower()
|
||||||
if text not in ["day", "week", "next", ""]:
|
if text not in TIMES:
|
||||||
text = "invalid"
|
text = "invalid"
|
||||||
res = edt(text, inline_query.from_user.id)
|
res = edt(text, inline_query.from_user.id)
|
||||||
input_content = InputTextMessageContent(res, parse_mode=ParseMode.MARKDOWN)
|
input_content = InputTextMessageContent(res, parse_mode=ParseMode.MARKDOWN)
|
||||||
|
@ -136,7 +131,7 @@ async def send_welcome(message: types.Message):
|
||||||
markdown.text("💠 Welcome to the TelegramEDT, a calendar bot for the Lyon 1 University ! 💠\n"),
|
markdown.text("💠 Welcome to the TelegramEDT, a calendar bot for the Lyon 1 University ! 💠\n"),
|
||||||
markdown.text(
|
markdown.text(
|
||||||
markdown.text("🗓"),
|
markdown.text("🗓"),
|
||||||
markdown.code("/edt [day | week | next]"),
|
markdown.code("/edt [day | next | week | next week]"),
|
||||||
markdown.text(", for show your next course")
|
markdown.text(", for show your next course")
|
||||||
),
|
),
|
||||||
markdown.text(
|
markdown.text(
|
||||||
|
@ -146,8 +141,8 @@ async def send_welcome(message: types.Message):
|
||||||
),
|
),
|
||||||
markdown.text(
|
markdown.text(
|
||||||
markdown.text("⚙️"),
|
markdown.text("⚙️"),
|
||||||
markdown.code("/setedt <url>"),
|
markdown.code("/setedt <resources>"),
|
||||||
markdown.text(", to setup your calendar")
|
markdown.text(", to setup your calendar\nThe resources can be get on the url of exported calendar")
|
||||||
),
|
),
|
||||||
markdown.text(
|
markdown.text(
|
||||||
markdown.text("🔗"),
|
markdown.text("🔗"),
|
||||||
|
@ -165,18 +160,19 @@ async def send_welcome(message: types.Message):
|
||||||
|
|
||||||
|
|
||||||
@dp.message_handler(commands=["edt"])
|
@dp.message_handler(commands=["edt"])
|
||||||
@dp.message_handler(lambda msg: msg.text.lower() in ["day", "week", "next"])
|
@dp.message_handler(lambda msg: msg.text.lower() in TIMES[1:])
|
||||||
async def edt_cmd(message: types.Message):
|
async def edt_cmd(message: types.Message):
|
||||||
await message.chat.do(types.ChatActions.TYPING)
|
await message.chat.do(types.ChatActions.TYPING)
|
||||||
logger.info(f"{message.from_user.username} do edt command: {message.text}")
|
logger.info(f"{message.from_user.username} do edt command: {message.text}")
|
||||||
text = message.text
|
text = message.text.lower()
|
||||||
if message.text[:4] == "/edt":
|
if text[:4] == "/edt":
|
||||||
text = message.text[5:]
|
text = text[5:]
|
||||||
resp = edt(text, message.from_user.id)
|
resp = edt(text, message.from_user.id)
|
||||||
key = reply_keyboard.ReplyKeyboardMarkup()
|
key = reply_keyboard.ReplyKeyboardMarkup()
|
||||||
key.add(reply_keyboard.KeyboardButton("Day"))
|
key.add(reply_keyboard.KeyboardButton("Day"))
|
||||||
key.add(reply_keyboard.KeyboardButton("Week"))
|
|
||||||
key.add(reply_keyboard.KeyboardButton("Next"))
|
key.add(reply_keyboard.KeyboardButton("Next"))
|
||||||
|
key.add(reply_keyboard.KeyboardButton("Week"))
|
||||||
|
key.add(reply_keyboard.KeyboardButton("Next week"))
|
||||||
await message.reply(resp, parse_mode=ParseMode.MARKDOWN, reply_markup=key)
|
await message.reply(resp, parse_mode=ParseMode.MARKDOWN, reply_markup=key)
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,25 +180,17 @@ async def edt_cmd(message: types.Message):
|
||||||
async def edt_set(message: types.Message):
|
async def edt_set(message: types.Message):
|
||||||
await message.chat.do(types.ChatActions.TYPING)
|
await message.chat.do(types.ChatActions.TYPING)
|
||||||
logger.info(f"{message.from_user.username} do setedt command: {message.text}")
|
logger.info(f"{message.from_user.username} do setedt command: {message.text}")
|
||||||
url_http = message.text.find("http")
|
resources = message.text[8:]
|
||||||
url_end = message.text.find(" ", url_http)
|
now_test = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
|
||||||
if url_end == -1:
|
|
||||||
url_end = None
|
|
||||||
url = message.text[url_http:url_end]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
Calendar(get(url).text)
|
Calendar([URL, int(resources), PROJECT_ID], now_test.date(), now_test.date())
|
||||||
except (ParseError, ConnectionError, InvalidSchema, MissingSchema, ValueError):
|
except (ParseError, ConnectionError, InvalidSchema, MissingSchema, ValueError):
|
||||||
msg = markdown.bold("Invalid URL ! ❌")
|
msg = markdown.bold("Invalid resources ! ❌")
|
||||||
else:
|
else:
|
||||||
if "calType=vcal" in url:
|
|
||||||
url = url[:url.find("vcal")] + "ical"
|
|
||||||
elif "firstDate" in url:
|
|
||||||
url = url[:url.find("&firstDate")]
|
|
||||||
|
|
||||||
with dbL:
|
with dbL:
|
||||||
with shelve.open("edt", writeback=True) as db:
|
with shelve.open("edt", writeback=True) as db:
|
||||||
db[str(message.from_user.id)]["url"] = url
|
db[str(message.from_user.id)]["resources"] = int(resources)
|
||||||
msg = markdown.text("EDT set ✅")
|
msg = markdown.text("EDT set ✅")
|
||||||
|
|
||||||
await message.reply(msg, parse_mode=ParseMode.MARKDOWN)
|
await message.reply(msg, parse_mode=ParseMode.MARKDOWN)
|
||||||
|
@ -214,8 +202,8 @@ async def edt_geturl(message: types.Message):
|
||||||
logger.info(f"{message.from_user.username} do getedt command: {message.text}")
|
logger.info(f"{message.from_user.username} do getedt command: {message.text}")
|
||||||
with dbL:
|
with dbL:
|
||||||
with shelve.open("edt", writeback=True) as db:
|
with shelve.open("edt", writeback=True) as db:
|
||||||
if (str(message.from_user.id) in db) and ("url" in db[str(message.from_user.id)]):
|
if (str(message.from_user.id) in db) and ("resources" in db[str(message.from_user.id)]):
|
||||||
await message.reply(db[str(message.from_user.id)]["url"])
|
await message.reply(db[str(message.from_user.id)]["resources"])
|
||||||
else:
|
else:
|
||||||
await message.reply("No EDT set ! ❌")
|
await message.reply("No EDT set ! ❌")
|
||||||
|
|
||||||
|
|
Reference in a new issue