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.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)
if now.isoweekday() in [6, 7] and pass_week:
now += datetime.timedelta(days=(7 - (now.isoweekday() - 1)))
@ -43,7 +44,6 @@ class Calendar(ics.Calendar):
return msg
class Event(ics.Event):
def __init__(self, event: ics.Event):
super().__init__()
@ -57,8 +57,8 @@ class Event(ics.Event):
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}"),
markdown.code(f"\uD83D\uDCD3[{self.name}]:"),
markdown.text(f"\u231A{str(self.begin.time())[:-3]} -> {str(self.end.time())[:-3]}"),
markdown.italic(f"\uD83D\uDCCD{self.location} \uD83D\uDC68\u200D\uD83C\uDFEB{self.organizer}"),
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"
}

181
bot.py
View file

@ -13,6 +13,8 @@ from aiogram.types import InlineQuery, InputTextMessageContent, InlineQueryResul
from aiogram.utils import markdown
from aiogram.utils.exceptions import MessageIsTooLong
from EDTcalendar import Calendar
from EDTuser import User
from lang import lang
from ics.parse import ParseError
from requests.exceptions import ConnectionError, InvalidSchema, MissingSchema
@ -40,14 +42,19 @@ dp = Dispatcher(bot)
dbL = RLock()
def get_now():
return datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
def calendar(time: str, user_id: int):
with dbL:
with shelve.open("edt", writeback=True) as db:
if str(user_id) not in db or "resources" not in db[str(user_id)]:
return markdown.bold("Your EDT is not set ! ❌")
user = db[str(user_id)]
if not user.resources:
return lang(user, "edt_err_set")
elif time not in TIMES:
return markdown.bold("Invalid choice ! ❌")
return str(Calendar(time, db[str(user_id)]["resources"]))
return lang(user, "edt_err_choice")
return str(user.calendar(time))
async def notif():
@ -55,16 +62,13 @@ async def notif():
with dbL:
with shelve.open("edt", writeback=True) as db:
for u in db:
if ("resources" in db[u]) and ("notif" in db[u]) and (db[u]["notif"]["state"]):
logger.info(f"notif check for {u}")
now = datetime.datetime.now(datetime.timezone.utc).astimezone(tz=None)
c = Calendar("day", db[u]["resources"], pass_week=False)
if db[u].resources and db[u].nt:
now = get_now()
c = db[u].calendar(pass_week=True)
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']}")
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 (e.begin - now).total_seconds().__abs__()//60 <= db[u]["notif"]["time"] and\
(now - db[u]["notif"]["last"]).total_seconds()//60 >= db[u]["notif"]["cooldown"]:
db[u]["notif"]["last"] = now
if 0 <= (e.begin - now).total_seconds().__abs__()//60 <= db[u].nt_time and \
0 <= (now - db[u].nt_last).total_seconds()//60 >= db[u].nt_cooldown:
db[u].nt_last = get_now()
await bot.send_message(int(u), e, parse_mode=ParseMode.MARKDOWN)
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)
@dp.message_handler(commands=["start", "help"])
async def send_welcome(message: types.Message):
@dp.message_handler(commands="Start")
async def start(message: types.Message):
user_id = str(message.from_user.id)
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 shelve.open("edt", writeback=True) as db:
if str(message.from_user.id) not in db:
db[str(message.from_user.id)] = dict()
logger.info(f"db creation for {message.from_user.username}")
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)
if user_id not in db:
db[user_id] = User(int(user_id), message.from_user.locale.language)
user = db[user_id]
await message.reply(lang(user, "welcome"), 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:])
async def edt_cmd(message: types.Message):
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)
@dp.message_handler(commands=["setedt"])
@dp.message_handler(commands="setedt")
async def edt_set(message: types.Message):
user_id = str(message.from_user.id)
await message.chat.do(types.ChatActions.TYPING)
logger.info(f"{message.from_user.username} do setedt command: {message.text}")
resources = message.text[8:]
with dbL:
with shelve.open("edt", writeback=True) as db:
try:
Calendar("", int(resources))
except (ParseError, ConnectionError, InvalidSchema, MissingSchema, ValueError):
msg = markdown.bold("Invalid resources ! ❌")
msg = lang(db[user_id], "setedt_err_res")
else:
with dbL:
with shelve.open("edt", writeback=True) as db:
db[str(message.from_user.id)]["resources"] = int(resources)
msg = markdown.text("EDT set ✅")
db[user_id].resources = int(resources)
msg = lang(db[user_id], "setedt")
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):
user_id = str(message.from_user.id)
await message.chat.do(types.ChatActions.TYPING)
logger.info(f"{message.from_user.username} do getedt command: {message.text}")
with dbL:
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)]):
await message.reply(db[str(message.from_user.id)]["resources"])
if db[user_id].resources:
await message.reply(db[user_id].resources)
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):
user_id = str(message.from_user.id)
await message.chat.do(types.ChatActions.TYPING)
logger.info(f"{message.from_user.username} do notif command: {message.text}")
with dbL:
with shelve.open("edt", writeback=True) as db:
if "notif" not in db[str(message.from_user.id)]:
db[str(message.from_user.id)]["notif"] = dict()
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"]:
if message.text[7:10] == "toggle":
if db[user_id].nt:
res = False
else:
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":
cut = 11 if message.text[7:11] == "time" else 15
try:
int(message.text[cut+1:])
except ValueError:
msg = markdown.bold("Invalid number ! ❌")
msg = lang(db[user_id], "notif_err_num")
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":
msg = markdown.text(
markdown.code("Notification:"),
markdown.text(
markdown.bold("State:"),
markdown.text(db[str(message.from_user.id)]["notif"]["state"])
),
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"
)
msg = lang(db[user_id], "notif_info").format(db[user_id].nt, db[user_id].nt_time,
db[user_id].nt_cooldown)
elif message.text[7:] == "":
msg = lang(db[user_id], "notif_help")
else:
msg = markdown.bold("Invalid action ! ❌")
msg = lang(db[user_id], "notif_err_act")
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):
await message.chat.do(types.ChatActions.TYPING)
logger.info(f"{message.from_user.username} do getid command: {message.text}")
await message.reply(message.from_user.id)
@dp.message_handler(commands=["getlogs"])
@dp.message_handler(commands="getlogs")
async def get_logs(message: types.Message):
logger.info(f"{message.from_user.username} do getlog command: {message.text}")
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 ! ❌"))
@dp.message_handler(commands=["getdb"])
@dp.message_handler(commands="getdb")
async def get_db(message: types.Message):
logger.info(f"{message.from_user.username} do getdb command: {message.text}")
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)
@dp.message_handler(commands=["eval"])
async def get_db(message: types.Message):
@dp.message_handler(commands="eval")
async def eval_cmd(message: types.Message):
logger.info(f"{message.from_user.username} do eval command: {message.text}")
if message.from_user.id == ADMIN_ID:
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]