send unread links with buttons to mark as read or delete
This commit is contained in:
parent
5d7698462a
commit
a8014e363c
27
main.py
27
main.py
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
from functools import wraps
|
||||
import logging
|
||||
import os
|
||||
|
|
@ -8,7 +9,7 @@ from datetime import datetime
|
|||
from pprint import pprint
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from telegram import Update, user
|
||||
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ParseMode
|
||||
import telegram
|
||||
from telegram.ext import (CallbackContext, CommandHandler, MessageHandler,
|
||||
Updater)
|
||||
|
|
@ -25,12 +26,13 @@ link_regex = re.compile(
|
|||
|
||||
def private_only(f):
|
||||
@wraps(f)
|
||||
def cb(update: Update, *args, **kwargs):
|
||||
def cb(self, update: Update, *args, **kwargs):
|
||||
if update.effective_chat.type != 'private':
|
||||
return
|
||||
return f(update, *args, **kwargs)
|
||||
return f(self, update, *args, **kwargs)
|
||||
return cb
|
||||
|
||||
|
||||
@dataclass
|
||||
class BotSettings:
|
||||
token: str
|
||||
|
|
@ -51,7 +53,7 @@ class Bot:
|
|||
for f in dir(self):
|
||||
if f.startswith("cmd_"):
|
||||
self.dispatcher.add_handler(
|
||||
CommandHandler(f[4:], private_only(getattr(self, f))))
|
||||
CommandHandler(f[4:], getattr(self, f)))
|
||||
|
||||
def _register_handlers(self):
|
||||
self.dispatcher.add_handler(MessageHandler(
|
||||
|
|
@ -75,11 +77,13 @@ class Bot:
|
|||
);
|
||||
""")
|
||||
|
||||
@private_only
|
||||
def cmd_start(self, update: Update, context: CallbackContext):
|
||||
context.bot.send_message(chat_id=update.effective_chat.id, text='Hi!')
|
||||
# TODO: timezones
|
||||
# TODO: ask to set time or something
|
||||
|
||||
@private_only
|
||||
def cmd_test(self, update: Update, context: CallbackContext):
|
||||
l = Link(
|
||||
link="2137",
|
||||
|
|
@ -88,6 +92,7 @@ class Bot:
|
|||
with self.db as db:
|
||||
l.create(db)
|
||||
|
||||
@private_only
|
||||
def cmd_unread(self, update: Update, context: CallbackContext):
|
||||
# TODO: ignore messages from group
|
||||
user_id = update.effective_user.id
|
||||
|
|
@ -98,10 +103,16 @@ class Bot:
|
|||
unread = Link.get_unread(db, user_id)
|
||||
|
||||
bot.send_message(
|
||||
user_id, f"**Your unread links as of {datetime.now().isoformat()}:", parse_mode="MARKDOWN")
|
||||
user_id, f"*Your unread links as of {datetime.now().isoformat()}:*", parse_mode=ParseMode.MARKDOWN)
|
||||
for link in unread:
|
||||
bot.send_message(user_id, link.link)
|
||||
# TODO: button to read or postpone
|
||||
keyboard = [
|
||||
[InlineKeyboardButton(text='Mark as read',
|
||||
callback_data=f"mark_as_read:{link.id}"),
|
||||
InlineKeyboardButton(text='Delete', callback_data=f"delete:{link.id}")]
|
||||
]
|
||||
bot.send_message(user_id, link.link,
|
||||
reply_markup=InlineKeyboardMarkup(keyboard))
|
||||
# TODO: button to postpone
|
||||
# TODO: button to mark all as read or postpone
|
||||
|
||||
def _natural_count(self, n, singular, plural):
|
||||
|
|
@ -111,8 +122,6 @@ class Bot:
|
|||
|
||||
@private_only
|
||||
def message(self, update: Update, context: CallbackContext):
|
||||
if update.effective_chat.type != 'private':
|
||||
return
|
||||
user_id = update.effective_user.id
|
||||
links = re.findall(link_regex, update.message.text)
|
||||
with self.db as db:
|
||||
|
|
|
|||
50
models.py
50
models.py
|
|
@ -1,7 +1,7 @@
|
|||
import sqlite3
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Tuple
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -12,6 +12,39 @@ class Link:
|
|||
read_at: datetime = None
|
||||
added_at: datetime = None
|
||||
|
||||
def as_dict(self):
|
||||
def timestamp(t): return t.timestamp() if t is not None else None
|
||||
return {
|
||||
"id": self.id,
|
||||
"user_id": self.user_id,
|
||||
"read_at": timestamp(self.read_at),
|
||||
"added_at": timestamp(self.added_at),
|
||||
"link": self.link,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, dict: Dict) -> 'Link':
|
||||
def convert_date(t): return datetime.fromtimestamp(
|
||||
t) if t is not None else None
|
||||
return Link(
|
||||
id=dict.get('id', None),
|
||||
user_id=dict["user_id"],
|
||||
read_at=convert_date(dict.get("read_at", None)),
|
||||
added_at=convert_date(dict.get("added_at", None)),
|
||||
link=dict["link"]
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _from_tuple(cls, tuple) -> 'Link':
|
||||
id, link, user_id, read_at, added_at = tuple
|
||||
return cls(
|
||||
id=id,
|
||||
link=link,
|
||||
user_id=user_id,
|
||||
read_at=read_at,
|
||||
added_at=added_at
|
||||
)
|
||||
|
||||
def create(self, db: sqlite3.Connection):
|
||||
self.added_at = datetime.now()
|
||||
cur = db.cursor()
|
||||
|
|
@ -26,22 +59,11 @@ class Link:
|
|||
self.id = r[0][0]
|
||||
|
||||
@classmethod
|
||||
def _from_tuple(cls, tuple) -> 'Link':
|
||||
id, link, user_id, read_at, added_at = tuple
|
||||
return cls(
|
||||
id=id,
|
||||
link=link,
|
||||
user_id=user_id,
|
||||
read_at=read_at,
|
||||
added_at=added_at
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _get(cls, db: sqlite3.Connection, where: str, values: Tuple = ()) -> 'Link':
|
||||
def _get(cls, db: sqlite3.Connection, where: str, values: Tuple = ()) -> List['Link']:
|
||||
cur = db.cursor()
|
||||
rows = cur.execute(f"SELECT * FROM links WHERE {where}", values)
|
||||
return map(cls._from_tuple, rows)
|
||||
|
||||
@classmethod
|
||||
def get_unread(cls, db: sqlite3.Connection, user_id: str):
|
||||
def get_unread(cls, db: sqlite3.Connection, user_id: str) -> List['Link']:
|
||||
return cls._get(db, "user_id = ? AND read_at IS NULL", (user_id,))
|
||||
|
|
|
|||
Loading…
Reference in New Issue