1
0
Fork 0

Create and use of User object, fix of notif, start of multi languages support and start help on commands and errors

This commit is contained in:
Ethanell 2019-09-18 17:06:34 +02:00
parent b2ba8aecaf
commit fde9cdaf4e
5 changed files with 123 additions and 120 deletions

View file

@ -16,7 +16,8 @@ class Calendar(ics.Calendar):
self.events = events self.events = events
self.timeline = Timeline(self) self.timeline = Timeline(self)
def _url(self, time: str, url: list, pass_week: bool): @staticmethod
def _url(time: str, url: list, pass_week: bool):
now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None) now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
if now.isoweekday() in [6, 7] and pass_week: if now.isoweekday() in [6, 7] and pass_week:
now += datetime.timedelta(days=(7 - (now.isoweekday() - 1))) now += datetime.timedelta(days=(7 - (now.isoweekday() - 1)))
@ -43,7 +44,6 @@ class Calendar(ics.Calendar):
return msg return msg
class Event(ics.Event): class Event(ics.Event):
def __init__(self, event: ics.Event): def __init__(self, event: ics.Event):
super().__init__() super().__init__()
@ -57,8 +57,8 @@ class Event(ics.Event):
def __str__(self): def __str__(self):
return markdown.text( return markdown.text(
markdown.bold(f"<{str(self.begin.date())[5:]}>"), markdown.bold(f"<{str(self.begin.date())[5:]}>"),
markdown.code(f"📓[{self.name}]:"), markdown.code(f"\uD83D\uDCD3[{self.name}]:"),
markdown.text(f"⌚️ {str(self.begin.time())[:-3]} -> {str(self.end.time())[:-3]}"), markdown.text(f"\u231A{str(self.begin.time())[:-3]} -> {str(self.end.time())[:-3]}"),
markdown.italic(f"📍 {self.location} 👨‍🏫 {self.organizer}"), markdown.italic(f"\uD83D\uDCCD{self.location} \uD83D\uDC68\u200D\uD83C\uDFEB{self.organizer}"),
sep="\n" sep="\n"
) ) # surrogates not allowed

16
EDTuser.py Normal file
View file

@ -0,0 +1,16 @@
from EDTcalendar import Calendar
import datetime
class User:
def __init__(self, user_id: int, language: str):
self.id = user_id
self.language = language
self.resources = None
self.nt = False
self.nt_time = 20
self.nt_cooldown = 20
self.nt_last = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
def calendar(self, time: str = "", pass_week: bool = False):
return Calendar(time, self.resources, pass_week=pass_week)

15
Languages/en.json Normal file
View file

@ -0,0 +1,15 @@
{
"welcome": "\uD83D\uDCA0 *Welcome to the TelegramEDT bot !* \uD83D\uDCA0\n\uD83D\uDD39Please use the command /setedt to set your calendar\n\uD83D\uDD39Use /notif to configure events notification\n\u2139And /help for more commands",
"help": "\u2139 *Commands help* \u2139\n\uD83D\uDCC5/edt, show your next events\n\uD83D\uDD14/notif, set your events notifications\n\u2699/setedt, set your calendar",
"edt_err_set": "Your EDT is not set ! \u274C\n\u2139Use /setedt to fix that",
"edt_err_choice": "Invalid choice ! \u274C\n\u2139You can choose between: `day`, `next`, `week`, `next week`",
"setedt_err_res": "Invalid resources ! \u274C",
"setedt": "EDT set \u2705",
"getedt_err": "No EDT set ! \u274C",
"notif_set": "Notifications set on `{}` ! \u2705",
"notif_err_num": "Invalid number ! \u274C",
"notif_time_cooldown": "Notification `{}` set to `{}` ! \u2705",
"notif_info": "_Notification_\n*State:* {}\n*Time:* {}\n*Cooldown:* {}",
"notif_help": "\u2139 *Notif help* \u2139\n\uD83D\uDD39`toggle` to switch on/off notifications\n\uD83D\uDD39`time` to set time in minutes between notification and event\n\uD83D\uDD39`cooldown` set time in minutes between notification",
"notif_err_act": "Invalid action ! \u274C\n\u2139Use /notif to see help"
}

191
bot.py
View file

@ -13,6 +13,8 @@ from aiogram.types import InlineQuery, InputTextMessageContent, InlineQueryResul
from aiogram.utils import markdown from aiogram.utils import markdown
from aiogram.utils.exceptions import MessageIsTooLong from aiogram.utils.exceptions import MessageIsTooLong
from EDTcalendar import Calendar from EDTcalendar import Calendar
from EDTuser import User
from lang import lang
from ics.parse import ParseError from ics.parse import ParseError
from requests.exceptions import ConnectionError, InvalidSchema, MissingSchema from requests.exceptions import ConnectionError, InvalidSchema, MissingSchema
@ -40,14 +42,19 @@ dp = Dispatcher(bot)
dbL = RLock() dbL = RLock()
def get_now():
return datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
def calendar(time: str, user_id: int): def calendar(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 "resources" not in db[str(user_id)]: user = db[str(user_id)]
return markdown.bold("Your EDT is not set ! ❌") if not user.resources:
return lang(user, "edt_err_set")
elif time not in TIMES: elif time not in TIMES:
return markdown.bold("Invalid choice ! ❌") return lang(user, "edt_err_choice")
return str(Calendar(time, db[str(user_id)]["resources"])) return str(user.calendar(time))
async def notif(): async def notif():
@ -55,16 +62,13 @@ 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 ("resources" in db[u]) and ("notif" in db[u]) and (db[u]["notif"]["state"]): if db[u].resources and db[u].nt:
logger.info(f"notif check for {u}") now = get_now()
now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None) c = db[u].calendar(pass_week=True)
c = Calendar("day", db[u]["resources"], pass_week=False)
for e in c.timeline: for e in c.timeline:
logger.info(f"{(e.begin - now).total_seconds().__abs__()//60.} <= {db[u]['notif']['time']} and {(now - db[u]['notif']['last']).total_seconds()//60} | >= {db[u]['notif']['cooldown']}") if 0 <= (e.begin - now).total_seconds().__abs__()//60 <= db[u].nt_time and \
logger.info(f"{(e.begin - now).total_seconds().__abs__()//60 <= db[u]['notif']['time']} and {(now - db[u]['notif']['last']).total_seconds()//60 >= db[u]['notif']['cooldown']}") 0 <= (now - db[u].nt_last).total_seconds()//60 >= db[u].nt_cooldown:
if (e.begin - now).total_seconds().__abs__()//60 <= db[u]["notif"]["time"] and\ db[u].nt_last = get_now()
(now - db[u]["notif"]["last"]).total_seconds()//60 >= db[u]["notif"]["cooldown"]:
db[u]["notif"]["last"] = now
await bot.send_message(int(u), e, parse_mode=ParseMode.MARKDOWN) await bot.send_message(int(u), e, parse_mode=ParseMode.MARKDOWN)
await sleep(60) await sleep(60)
@ -83,49 +87,30 @@ async def inline_edt(inline_query: InlineQuery):
await bot.answer_inline_query(inline_query.id, results=[item], cache_time=1) await bot.answer_inline_query(inline_query.id, results=[item], cache_time=1)
@dp.message_handler(commands=["start", "help"]) @dp.message_handler(commands="Start")
async def send_welcome(message: types.Message): async def start(message: types.Message):
user_id = str(message.from_user.id)
await message.chat.do(types.ChatActions.TYPING) await message.chat.do(types.ChatActions.TYPING)
logger.info(f"{message.from_user.username} do start/help command: {message.text}") logger.info(f"{message.from_user.username} start : {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) not in db: if user_id not in db:
db[str(message.from_user.id)] = dict() db[user_id] = User(int(user_id), message.from_user.locale.language)
logger.info(f"db creation for {message.from_user.username}") user = db[user_id]
await message.reply(lang(user, "welcome"), parse_mode=ParseMode.MARKDOWN)
msg = markdown.text(
markdown.text("💠 Welcome to the TelegramEDT, a calendar bot for the Lyon 1 University ! 💠\n"),
markdown.text(
markdown.text("🗓"),
markdown.code("/edt [day | next | week | next week]"),
markdown.text(", for show your next course")
),
markdown.text(
markdown.text("🔔"),
markdown.code("/notif <set | info | time number | cooldown number>"),
markdown.text(", setup notifications")
),
markdown.text(
markdown.text("⚙️"),
markdown.code("/setedt <resources>"),
markdown.text(", to setup your calendar\nThe resources can be get on the url of exported calendar")
),
markdown.text(
markdown.text("🔗"),
markdown.code("/getedt"),
markdown.text(", to get your calendar url")
),
markdown.text(
markdown.text(""),
markdown.code("/help"),
markdown.text(", to show this command")
),
sep="\n"
)
await message.reply(msg, parse_mode=ParseMode.MARKDOWN)
@dp.message_handler(commands=["edt"]) @dp.message_handler(commands="help")
async def send_welcome(message: types.Message):
await message.chat.do(types.ChatActions.TYPING)
logger.info(f"{message.from_user.username} do help command: {message.text}")
with dbL:
with shelve.open("edt", writeback=True) as db:
user = db[str(message.from_user.id)]
await message.reply(lang(user, "help"), parse_mode=ParseMode.MARKDOWN)
@dp.message_handler(commands="edt")
@dp.message_handler(lambda msg: msg.text.lower() in TIMES[1:]) @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)
@ -142,111 +127,89 @@ async def edt_cmd(message: types.Message):
await message.reply(resp, parse_mode=ParseMode.MARKDOWN, reply_markup=key) await message.reply(resp, parse_mode=ParseMode.MARKDOWN, reply_markup=key)
@dp.message_handler(commands=["setedt"]) @dp.message_handler(commands="setedt")
async def edt_set(message: types.Message): async def edt_set(message: types.Message):
user_id = str(message.from_user.id)
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}")
resources = message.text[8:] resources = message.text[8:]
try: with dbL:
Calendar("", int(resources)) with shelve.open("edt", writeback=True) as db:
except (ParseError, ConnectionError, InvalidSchema, MissingSchema, ValueError): try:
msg = markdown.bold("Invalid resources ! ❌") Calendar("", int(resources))
else: except (ParseError, ConnectionError, InvalidSchema, MissingSchema, ValueError):
with dbL: msg = lang(db[user_id], "setedt_err_res")
with shelve.open("edt", writeback=True) as db: else:
db[str(message.from_user.id)]["resources"] = int(resources) db[user_id].resources = int(resources)
msg = markdown.text("EDT set ✅") msg = lang(db[user_id], "setedt")
await message.reply(msg, parse_mode=ParseMode.MARKDOWN) await message.reply(msg, parse_mode=ParseMode.MARKDOWN)
@dp.message_handler(commands=["getedt"]) @dp.message_handler(commands="getedt")
async def edt_geturl(message: types.Message): async def edt_geturl(message: types.Message):
user_id = str(message.from_user.id)
await message.chat.do(types.ChatActions.TYPING) await message.chat.do(types.ChatActions.TYPING)
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 ("resources" in db[str(message.from_user.id)]): if db[user_id].resources:
await message.reply(db[str(message.from_user.id)]["resources"]) await message.reply(db[user_id].resources)
else: else:
await message.reply("No EDT set ! ❌") await message.reply(lang(db[user_id], "getedt_err"))
@dp.message_handler(commands=["notif"]) @dp.message_handler(commands="notif")
async def notif_cmd(message: types.Message): async def notif_cmd(message: types.Message):
user_id = str(message.from_user.id)
await message.chat.do(types.ChatActions.TYPING) await message.chat.do(types.ChatActions.TYPING)
logger.info(f"{message.from_user.username} do notif command: {message.text}") logger.info(f"{message.from_user.username} do notif command: {message.text}")
with dbL: with dbL:
with shelve.open("edt", writeback=True) as db: with shelve.open("edt", writeback=True) as db:
if "notif" not in db[str(message.from_user.id)]: if message.text[7:10] == "toggle":
db[str(message.from_user.id)]["notif"] = dict() if db[user_id].nt:
db[str(message.from_user.id)]["notif"]["state"] = False
db[str(message.from_user.id)]["notif"]["time"] = 20
db[str(message.from_user.id)]["notif"]["cooldown"] = 20
last = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None) - datetime.timedelta(minutes=20)
db[str(message.from_user.id)]["notif"]["last"] = last
if message.text[7:10] == "set":
if db[str(message.from_user.id)]["notif"]["state"]:
res = False res = False
else: else:
res = True res = True
db[str(message.from_user.id)]["notif"]["state"] = res db[user_id].nt = res
msg = lang(db[user_id], "notif_set").format(res)
msg = markdown.text(
markdown.text("Notifications set on "),
markdown.code(res),
markdown.text("")
)
elif message.text[7:11] == "time" or message.text[7:15] == "cooldown": elif message.text[7:11] == "time" or message.text[7:15] == "cooldown":
cut = 11 if message.text[7:11] == "time" else 15 cut = 11 if message.text[7:11] == "time" else 15
try: try:
int(message.text[cut+1:]) int(message.text[cut+1:])
except ValueError: except ValueError:
msg = markdown.bold("Invalid number ! ❌") msg = lang(db[user_id], "notif_err_num")
else: else:
db[str(message.from_user.id)]["notif"][message.text[7:cut]] = int(message.text[cut+1:]) if cut == 11:
db[user_id]["notif"].nt_time = int(message.text[cut+1:])
else:
db[user_id]["notif"].nt_cooldown = int(message.text[cut + 1:])
msg = lang(db(user_id), "notif_time_cooldown").format(message.text[7:cut], message.text[cut + 1:])
msg = markdown.text(
markdown.text("Notification"),
markdown.code(message.text[7:cut]),
markdown.text("set to"),
markdown.bold(message.text[cut+1:]),
markdown.text("")
)
elif message.text[7:11] == "info": elif message.text[7:11] == "info":
msg = markdown.text( msg = lang(db[user_id], "notif_info").format(db[user_id].nt, db[user_id].nt_time,
markdown.code("Notification:"), db[user_id].nt_cooldown)
markdown.text(
markdown.bold("State:"), elif message.text[7:] == "":
markdown.text(db[str(message.from_user.id)]["notif"]["state"]) msg = lang(db[user_id], "notif_help")
),
markdown.text(
markdown.bold("Time:"),
markdown.text(db[str(message.from_user.id)]["notif"]["time"])
),
markdown.text(
markdown.bold("Cooldown:"),
markdown.text(db[str(message.from_user.id)]["notif"]["cooldown"])
),
sep="\n"
)
else: else:
msg = markdown.bold("Invalid action ! ❌") msg = lang(db[user_id], "notif_err_act")
await message.reply(msg, parse_mode=ParseMode.MARKDOWN) await message.reply(msg, parse_mode=ParseMode.MARKDOWN)
@dp.message_handler(commands=["getid"]) @dp.message_handler(commands="getid")
async def get_id(message: types.Message): async def get_id(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 getid command: {message.text}") logger.info(f"{message.from_user.username} do getid command: {message.text}")
await message.reply(message.from_user.id) await message.reply(message.from_user.id)
@dp.message_handler(commands=["getlogs"]) @dp.message_handler(commands="getlogs")
async def get_logs(message: types.Message): async def get_logs(message: types.Message):
logger.info(f"{message.from_user.username} do getlog command: {message.text}") logger.info(f"{message.from_user.username} do getlog command: {message.text}")
if message.from_user.id == ADMIN_ID: if message.from_user.id == ADMIN_ID:
@ -272,7 +235,7 @@ async def get_logs(message: types.Message):
await message.reply(markdown.bold("Too much logs ! ❌")) await message.reply(markdown.bold("Too much logs ! ❌"))
@dp.message_handler(commands=["getdb"]) @dp.message_handler(commands="getdb")
async def get_db(message: types.Message): async def get_db(message: types.Message):
logger.info(f"{message.from_user.username} do getdb command: {message.text}") logger.info(f"{message.from_user.username} do getdb command: {message.text}")
if message.from_user.id == ADMIN_ID: if message.from_user.id == ADMIN_ID:
@ -286,8 +249,8 @@ async def get_db(message: types.Message):
await message.reply(msg, parse_mode=ParseMode.MARKDOWN) await message.reply(msg, parse_mode=ParseMode.MARKDOWN)
@dp.message_handler(commands=["eval"]) @dp.message_handler(commands="eval")
async def get_db(message: types.Message): async def eval_cmd(message: types.Message):
logger.info(f"{message.from_user.username} do eval command: {message.text}") logger.info(f"{message.from_user.username} do eval command: {message.text}")
if message.from_user.id == ADMIN_ID: if message.from_user.id == ADMIN_ID:
msg = markdown.text( msg = markdown.text(

9
lang.py Normal file
View file

@ -0,0 +1,9 @@
import json
from EDTuser import User
LANG = ["en"]
def lang(user: User, message: str):
language = user.language if user.language in LANG else LANG[0]
return json.loads(open(f"Languages/{language}.json", "r").read())[message]