diff --git a/README.md b/README.md index df1455a..75ff99d 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,26 @@ Provide easy way for create number pagination with inline keyboard for telegram bot on python. +**InlineKeyboardPaginator** + [Example](https://github.com/ksinn/python-telegram-bot-pagination/blob/master/examples/example.py) with [pyTelegramBotAPI](https://github.com/eternnoir/pyTelegramBotAPI) [Example](https://github.com/ksinn/python-telegram-bot-pagination/blob/master/examples/example2.py) with [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) ![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/ex1.png) ![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/f1.jpg) +**InlineKeyboardSimplePaginator** + +This paginator can be used similarly to InlineKeyboardPaginator. + +It is suitable when page numbers are not as important to us as the ability to quickly view them and scroll around page +(e.g. when you click the next page button on the last one, the first page will open). + +[Example](https://github.com/ksinn/python-telegram-bot-pagination/blob/master/examples/example3.py) with [python-telegram-bot](https://github.com/python-telegram-bot/python-telegram-bot) + +![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/simple_2.png) ![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/simple_1.png) + +--- * [Installation.](#installation) * [Usage.](#usage) * [Button render controlling.](#button-render-controlling) @@ -21,20 +35,30 @@ Provide easy way for create number pagination with inline keyboard for telegram pip install python-telegram-bot-pagination #### Usage - from telegram_bot_pagination import InlineKeyboardPaginator - - paginator = InlineKeyboardPaginator( - page_count, - current_page=page, - data_pattern='page#{page}' - ) - - bot.send_message( - chat_id, - text, - reply_markup=paginator.markup, - ) +```python3 +from telegram_bot_pagination import InlineKeyboardPaginator, InlineKeyboardSimplePaginator + +paginator = InlineKeyboardPaginator( + page_count, + current_page=page, + data_pattern='page#{page}' +) + +# you can use two types of Pagianators in a similar way +simple_paginator = InlineKeyboardSimplePaginator( + page_count, + current_page=page, + data_pattern='page#{page}' +) +``` +```python3 +bot.send_message( + chat_id, + text, + reply_markup=paginator.markup, +) +``` Init arguments: * page_count - integer, total 1-based pages count. @@ -48,28 +72,45 @@ Properties: #### Button render controlling For edit button render, use paginator object properties: -* first_page_label -* previous_page_label -* current_page_label -* next_page_label -* last_page_label +| InlineKeyboardPaginator | InlineKeyboardSimplePaginator | +|-------------------------|-------------------------------| +| previous_page_label | previous_page_label | +| current_page_label | current_page_label | + | next_page_label | next_page_label | + | first_page_label | - | + | last_page_label | - | + All of them can by python style formatting string with one arg, or simple string. For example: +```python3 +class MyPaginator(InlineKeyboardPaginator): + first_page_label = '<<' + previous_page_label = '<' + current_page_label = '-{}-' + next_page_label = '>' + last_page_label = '>>' + +paginator = MyPaginator(page_count) +``` +```python3 +class MyPaginator(InlineKeyboardSimplePaginator): + previous_page_label = '<' + current_page_label = '{}-{}' + next_page_label = '>' + +paginator = MyPaginator(page_count) +``` +Results: + +InlineKeyboardPaginator - class MyPaginator(InlineKeyboardPaginator): - first_page_label = '<<' - previous_page_label = '<' - current_page_label = '-{}-' - next_page_label = '>' - last_page_label = '>>' +![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/m2.jpg) - paginator = MyPaginator(page_count) +InlineKeyboardSimplePaginator -Result: - -![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/m2.jpg) +![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/simple_3.png) #### Adding extra button For adding button line before and after pagination use methods: @@ -80,16 +121,16 @@ For adding button line before and after pagination use methods: Each argument mast provide property 'text' and 'callback_data' For example: +```python3 +paginator.add_before( + InlineKeyboardButton('Like', callback_data='like#{}'.format(page)), + InlineKeyboardButton('Dislike', callback_data='dislike#{}'.format(page)) +) +paginator.add_after(InlineKeyboardButton('Go back', callback_data='back')) - paginator.add_before( - InlineKeyboardButton('Like', callback_data='like#{}'.format(page)), - InlineKeyboardButton('Dislike', callback_data='dislike#{}'.format(page)) - ) - paginator.add_after(InlineKeyboardButton('Go back', callback_data='back')) +``` Result: ![](https://github.com/ksinn/python-telegram-bot-pagination/raw/master/examples/media/ex1.png) - - diff --git a/examples/example3.py b/examples/example3.py new file mode 100644 index 0000000..ebbf21f --- /dev/null +++ b/examples/example3.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os +import logging + +from telegram import InlineKeyboardButton +from telegram.ext import Updater, CommandHandler, CallbackQueryHandler +from telegram_bot_pagination import InlineKeyboardSimplePaginator + +from data import character_pages + +logging.basicConfig( + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + level=logging.INFO +) + + +def start(update, context): + + paginator = InlineKeyboardSimplePaginator( + len(character_pages), + data_pattern='character#{page}' + ) + + update.message.reply_text( + text=character_pages[0], + reply_markup=paginator.markup, + parse_mode='Markdown' + ) + + +def characters_page_callback(update, context): + query = update.callback_query + + query.answer() + + page = int(query.data.split('#')[1]) + + paginator = InlineKeyboardSimplePaginator( + len(character_pages), + current_page=page, + data_pattern='character#{page}' + ) + + paginator.add_before( + InlineKeyboardButton('Like', callback_data='like#{}'.format(page)), + InlineKeyboardButton('Dislike', callback_data='dislike#{}'.format(page)) + ) + paginator.add_after(InlineKeyboardButton('Go back', callback_data='back')) + + query.edit_message_text( + text=character_pages[page - 1], + reply_markup=paginator.markup, + parse_mode='Markdown' + ) + + +updater = Updater(os.getenv('BOT_TOKEN'), use_context=True) + +updater.dispatcher.add_handler(CommandHandler('start', start)) +updater.dispatcher.add_handler(CallbackQueryHandler(characters_page_callback, pattern='^character#')) + +updater.start_polling() +updater.idle() + diff --git a/examples/media/simple_1.png b/examples/media/simple_1.png new file mode 100644 index 0000000..15e573d Binary files /dev/null and b/examples/media/simple_1.png differ diff --git a/examples/media/simple_2.png b/examples/media/simple_2.png new file mode 100644 index 0000000..f25c1c0 Binary files /dev/null and b/examples/media/simple_2.png differ diff --git a/examples/media/simple_3.png b/examples/media/simple_3.png new file mode 100644 index 0000000..b797bb6 Binary files /dev/null and b/examples/media/simple_3.png differ diff --git a/telegram_bot_pagination/__init__.py b/telegram_bot_pagination/__init__.py index c40ef7d..5dcab9e 100644 --- a/telegram_bot_pagination/__init__.py +++ b/telegram_bot_pagination/__init__.py @@ -20,16 +20,15 @@ def __init__(self, page_count, current_page=1, data_pattern='{page}'): self._keyboard_before = list() self._keyboard_after = list() - if current_page is None or current_page < 1: - current_page = 1 - if current_page > page_count: - current_page = page_count self.current_page = current_page - self.page_count = page_count - self.data_pattern = data_pattern + if current_page is None or current_page < 1: + self.current_page = 1 + if current_page > page_count: + self.current_page = page_count + def _build(self): keyboard_dict = dict() @@ -139,10 +138,8 @@ def __str__(self): def add_before(self, *inline_buttons): """ Add buttons as line above pagination buttons. - Args: inline_buttons (:object:`iterable`): List of object with attributes `text` and `callback_data`. - Returns: None """ @@ -151,16 +148,67 @@ def add_before(self, *inline_buttons): def add_after(self, *inline_buttons): """ Add buttons as line under pagination buttons. - Args: inline_buttons (:object:`iterable`): List of object with attributes 'text' and 'callback_data'. - Returns: None """ self._keyboard_after.append(_buttons_to_dict(inline_buttons)) +class InlineKeyboardSimplePaginator(InlineKeyboardPaginator): + previous_page_label = '‹‹' + next_page_label = '››' + current_page_label = '{}/{}' + + def __init__(self, page_count, current_page=1, data_pattern='{page}'): + super().__init__(page_count, current_page, data_pattern) + + if current_page is None or current_page < 1: + self.current_page = page_count + + if current_page > page_count: + self.current_page = 1 + + def _build(self): + if self.page_count == 1: + self._keyboard = list() + else: + keyboard_dict = self._build_keyboard() + self._keyboard = self._to_button_array(keyboard_dict) + + def _build_keyboard(self): + keyboard_dict = dict() + + if self.current_page - 1 < 1: + keyboard_dict[self.page_count] = self.previous_page_label + else: + keyboard_dict[self.current_page-1] = self.previous_page_label + + keyboard_dict[self.current_page] = self.current_page_label.format(self.current_page, self.page_count) + + if self.current_page + 1 > self.page_count: + keyboard_dict[1] = self.next_page_label + else: + keyboard_dict[self.current_page+1] = self.next_page_label + + return keyboard_dict + + def _to_button_array(self, keyboard_dict): + keyboard = list() + + keys = list(keyboard_dict.keys()) + + for key in keys: + keyboard.append( + InlineKeyboardButton( + text=str(keyboard_dict[key]), + callback_data=self.data_pattern.format(page=key) + ) + ) + return _buttons_to_dict(keyboard) + + def _buttons_to_dict(buttons): return [ {