From dfb5ee5432e9e361037872e56ec3331000fad259 Mon Sep 17 00:00:00 2001 From: campi Date: Tue, 8 Mar 2022 21:53:36 +0100 Subject: [PATCH] first commit --- database_lib.py | 63 +++++++++++++ libreremo_bot.py | 227 +++++++++++++++++++++++++++++++++++++++++++++++ libreremo_res.py | 58 ++++++++++++ 3 files changed, 348 insertions(+) create mode 100644 database_lib.py create mode 100644 libreremo_bot.py create mode 100644 libreremo_res.py diff --git a/database_lib.py b/database_lib.py new file mode 100644 index 0000000..3102d4c --- /dev/null +++ b/database_lib.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import logging +import libreremo_res as res +import sqlite3 as sql3 + +logger = logging.getLogger(__name__) + +class Database(): + + TABLE_BOOKS="books" + COLUMN_TITLE="title" + COLUMN_AUTHOR="author_sort" + COLUMN_PATH="path" + + TABLE_AUTHOR="authors" + COLUMN_NAME="name" + COLUMN_SORT="sort" + + def __init__(self, filename): + self.filename = filename + self.con = None + self.cur = None + + def _execute(self, sql, factory): + result_list = None + try: + self.con = sql3.connect(self.filename) + self.con.row_factory = factory + self.cur = self.con.cursor() + logging.info("Connection to db open") + self.cur.execute(sql) + result_list = self.cur.fetchall() + except sql3.Error as error: + logging.info("an error occured", error) + finally: + if self.con: + self.con.close() + logging.info("Connection to db closed") + return result_list + + def select_books_by_title(self, query): + sql = f""" + SELECT title, author_sort, path + FROM books WHERE title LIKE '%{query}%'; + """ + return self._execute(sql, res.book_factory) + + def select_books_by_author(self, query): + sql = f""" + SELECT title, author_sort, path FROM books + WHERE books.author_sort LIKE + '%' || (SELECT sort FROM authors + WHERE sort = '{query}') || '%'; + """ + return self._execute(sql, res.book_factory) + + def select_authors(self, query): + sql = f""" + SELECT name, sort FROM authors + WHERE name LIKE '%{query}%'; + """ + return self._execute(sql, res.author_factory) diff --git a/libreremo_bot.py b/libreremo_bot.py new file mode 100644 index 0000000..1a44566 --- /dev/null +++ b/libreremo_bot.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from telegram.ext.updater import Updater +from telegram.update import Update +from telegram import InlineKeyboardButton, InlineKeyboardMarkup +from telegram.ext.callbackcontext import CallbackContext +from telegram.ext.commandhandler import CommandHandler +from telegram.ext.messagehandler import MessageHandler +from telegram.ext.conversationhandler import ConversationHandler +from telegram.ext.callbackqueryhandler import CallbackQueryHandler +from telegram.callbackquery import CallbackQuery +from telegram.ext.filters import Filters +import glob +import database_lib as DB +import logging + +logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.INFO) + +MIN_QUERY_LENGTH = 3 + +TOKEN="**********" +updater = Updater("**********************************************", + use_context=True, arbitrary_callback_data=True) + +CALIBRE_LIBRARY="/home/archino/LIBREREMO/" +db = DB.Database(CALIBRE_LIBRARY + "metadata.db") + + +def start(update: Update, context: CallbackContext): + update.message.reply_text(""" + Ciao, questo รจ il nuovo Bot di libreremo :), + al momento non funzionante e' attivo solo a scopo + di testing, ma restate connessi per aggiornamenti!! + """) +# qua puoi scaricare centinaia di testi +# universitari; /help se vuoi v.edere i +# comandi che puoi usare.""") + + +def help(update: Update, context: CallbackContext): + update.message.reply_text("""Available Commands : + /search + /search_by_author + /search_by_class + /""") + + +def _ask_resource_type(update, context): + keyboard = [[InlineKeyboardButton(text="Titolo", callback_data="titolo")], + [InlineKeyboardButton(text="Autore", callback_data="autore")], + [InlineKeyboardButton(text="Corso di studio", callback_data="cds")]] + reply_markup = InlineKeyboardMarkup(keyboard) + update.message.reply_text( + text="In base a cosa vuoi cercare il tuo libro?", + reply_markup=reply_markup) + return GET_RESOURCE_TYPE + + +def _get_resource_type(update, context): + query = update.callback_query + context.user_data["resource"] = query.data + context.bot.send_message( + chat_id = query.message.chat_id, + text = "quale {} stai cercando?" + .format(context.user_data["resource"])) + return GET_RESOURCE + + +def _get_resource(update, context): + resource = update.message.text + result_list = []; + if (len(resource) <= MIN_QUERY_LENGTH): + update.message.reply_text(""" + scusa non ho capito cosa vuoi cercare, prova + ad inserire il titolo del libro per esteso, + cosa stai cercando?""") + return GET_RESOURCE + + if (context.user_data["resource"] == "titolo"): + result_list = db.select_books_by_title(resource) + text = "Scegli uno di questi libri" + handler = GET_BOOK + + elif (context.user_data["resource"] == "autore"): + result_list = db.select_authors(resource) + text = "Scegli uno di questi autori" + handler = GET_AUTHOR + + elif (context.user_data["resource"] == "cds"): +# result_list = db.select_class(resource) + text = "Scegli uno di questi corsi di studio" + handler = GET_CDS + + logging.info("asked resource {res}: {txt}" + .format(res=context.user_data["resource"], txt=resource)) + + if not result_list: + logging.info("cannot found result for {}".format(resource)) + update.message.reply_text(""" + Mi dispiace non ho trovato niente, controlla....""") + return ConversationHandler.END + + reply_markup = __format_reply_markup(result_list) + + update.message.reply_text( + text=text, + reply_markup=reply_markup) + + return handler + + +def _get_author(update: Update, context: CallbackContext): + query = update.callback_query + result_list = db.select_books_by_author(query.data) + if not result_list: + logging.info("cannot find books for requested author") + context.bot.send_message( + chat_id = query.message.chat_id, + text = "Mi dispiace ma non riesco a trovare libri per questo autore") + return ConversationHandler.END + context.bot.send_message( + chat_id = query.message.chat_id, + text = "scegli uno di questi libri", + reply_markup = __format_reply_markup(result_list)) + return GET_BOOK + + +def _get_cds(update: Update, context: CallbackContext): + query = update.callback_query +# result_list = db.select_books_by_cds(query) + context.bot.send_message( + chat_id = query.message.chat_id, + text = "scegli uno di questi libri", + reply_markup = reply_markup) + return GET_BOOK + + +def _get_book(update: Update, context: CallbackContext): + query = update.callback_query + chat_id = query.message.chat_id + query.message.reply_text( + 'perfetto ti invio immediatamente il file! :)') + try: + filepath = CALIBRE_LIBRARY + query.data + "/*.pdf" + for file in glob.glob(filepath): + with open(file, 'rb') as doc_pdf: + context.bot.send_document(chat_id, doc_pdf) + except FileNotFoundError: + logging.info("cannot send {}".format(filepath)) + query.message.reply_text( + "Mi dispiace non rieco a trovare il file, prova piu' tardi") + return ConversationHandler.END + + +def _cnv_stop(update: Update, context: CallbackContext): + update.message.reply_text("ciao") + return ConversationHandler.END + + +def search_by_title(update: Update, context: CallbackContext): + update.message.reply_text("che libro stai cercando?") + context.user_data["resource"] = "titolo" + return GET_RESOURCE + + +def search_by_author(update: Update, context: CallbackContext): + update.message.reply_text("di quale autore stai cercando i libri?") + context.user_data["resource"] = "autore" + return GET_RESOURCE + + +def search_by_class(update: Update, context: CallbackContext): + update.message.reply_text("di quale corso di studio stai cercando i libri?") + context.user_data["resource"] = "cds" + return GET_RESOURCE + + +def unknown(update: Update, context: CallbackContext): + update.message.reply_text( + "Sorry '%s' is not a valid command" % update.message.text) + + +def unknown_text(update: Update, context: CallbackContext): + update.message.reply_text( + "Sorry I can't recognize you , you said '%s'" % update.message.text) + +def __format_reply_markup(list_of_res): + return InlineKeyboardMarkup([ + [InlineKeyboardButton( + text = res.format_text(), + callback_data = res.format_data())] + for res in list_of_res]) + +GET_RESOURCE_TYPE, ASK_RESOURCE, GET_RESOURCE, GET_BOOK, GET_AUTHOR, GET_CDS = range(6) + +cnv_handler = ConversationHandler( + entry_points = [CommandHandler('search', _ask_resource_type), + CommandHandler('search_by_title', search_by_title), + CommandHandler('search_by_author', search_by_author), + CommandHandler('search_by_class', search_by_class)], + states = { + GET_RESOURCE_TYPE: [CallbackQueryHandler(_get_resource_type)], + GET_RESOURCE: [MessageHandler(Filters.text, _get_resource)], + GET_AUTHOR: [CallbackQueryHandler(_get_author)], + GET_BOOK: [CallbackQueryHandler(_get_book)], + GET_CDS: [CallbackQueryHandler(_get_cds)] + }, + fallbacks=[CommandHandler('stop', _cnv_stop), + MessageHandler(Filters.command, _cnv_stop)], +) + + +updater.dispatcher.add_handler(cnv_handler) +updater.dispatcher.add_handler(CommandHandler('start', start)) +updater.dispatcher.add_handler(CommandHandler('help', help)) +#updater.dispatcher.add_handler(CommandHandler('search_by_author', search_by_author)) +#updater.dispatcher.add_handler(CommandHandler('search_by_class', search_by_class)) +updater.dispatcher.add_handler(MessageHandler(Filters.text, unknown)) +updater.dispatcher.add_handler(MessageHandler(Filters.command, unknown)) # Filters out unknown commands + +# Filters out unknown messages. +updater.dispatcher.add_handler(MessageHandler(Filters.text, unknown_text)) + +updater.start_polling() +updater.idle() diff --git a/libreremo_res.py b/libreremo_res.py new file mode 100644 index 0000000..1038f3b --- /dev/null +++ b/libreremo_res.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +class ResourceInterface: + @classmethod + def __subclasshook__(cls, subclass): + return (hasattr(subclass, 'format_text') and + callable(subclass.format_text) and + hasattr(subclass, 'format_data') and + callable(subclass.format_data) or + NotImplemented) + +class Author(ResourceInterface): + + def __init__(self, author, sort): + self.author = author + self.sort = sort + + def format_text(self): + return self.author + + def format_data(self): + return self.sort + +class Book(ResourceInterface): + + def __init__(self, title, author, file): + self.title = title + self.author = author + self.file = file + + def format_text(self): + return self.title + " - " + self.author + + def format_data(self): + return self.file + +class CorsoDiStudio(ResourceInterface): + + def __init__(self, cds): + self.cds = cds + + def format_text(self): + return self.cds + + def format_data(self): + return self.cds + + +def book_factory(cursor, row): + return Book(row[0], row[1], row[2]) + +def author_factory(cursor, row): + return Author(row[0], row[1]) + +#def cds_factory(cursor, row): +# pass +