├── .gitignore ├── LICENSE ├── Procfile ├── README.md ├── main.py ├── pypi.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | **/__pycache__ 2 | **/venv 3 | *.session 4 | *.session-journal 5 | *.pyc 6 | *.env 7 | test.py 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Fayas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python3 main.py 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## PyPi Bot 2 | A pypi search telegram bot 3 | 4 | --- 5 | 6 | ## Variables 7 | 8 | - `API_HASH` Your API Hash from my.telegram.org 9 | - `API_ID` Your API ID from my.telegram.org 10 | - `BOT_TOKEN` Your bot token from @BotFather 11 | 12 | --- 13 | 14 | ## Commands 15 | 16 | ``` 17 | start - For start bot 18 | ``` 19 | 20 | --- 21 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Author: Fayas (https://github.com/FayasNoushad) 2 | 3 | import os 4 | from dotenv import load_dotenv 5 | from pyrogram import Client, filters 6 | from pyrogram.enums import ChatType 7 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 8 | from pypi import pypi_text, pypi_buttons 9 | 10 | 11 | load_dotenv() 12 | 13 | START_TEXT = """ 14 | Hello {}, 15 | I am a pypi package search telegram bot. 16 | 17 | - Send a pypi package name. 18 | - I will send the information of package. 19 | """ 20 | 21 | BUTTONS = [InlineKeyboardButton('⚙ Feedback ⚙', url='https://telegram.me/FayasNoushad')] 22 | 23 | Bot = Client( 24 | "PyPi-Bot", 25 | bot_token = os.environ["BOT_TOKEN"], 26 | api_id = int(os.environ["API_ID"]), 27 | api_hash = os.environ["API_HASH"] 28 | ) 29 | 30 | 31 | @Bot.on_message(filters.private & filters.command(["start", "help", "about"])) 32 | async def start(bot, update): 33 | text = START_TEXT.format(update.from_user.mention) 34 | reply_markup = InlineKeyboardMarkup([BUTTONS]) 35 | await update.reply_text( 36 | text=text, 37 | disable_web_page_preview=True, 38 | reply_markup=reply_markup, 39 | quote=True 40 | ) 41 | 42 | 43 | @Bot.on_message(filters.text) 44 | async def pypi_info(bot, update): 45 | 46 | message = await update.reply_text( 47 | text="Checking...", 48 | quote=True 49 | ) 50 | 51 | try: 52 | 53 | chat_type = update.chat.type 54 | text = update.text 55 | 56 | # Check chat type private or not 57 | if (chat_type==ChatType.PRIVATE): 58 | query = text 59 | else: 60 | query = text.split()[1] 61 | 62 | # get text and buttons from pypi.py file 63 | text = pypi_text(query) 64 | buttons = pypi_buttons(query) 65 | 66 | # reply package informations 67 | await message.edit_text( 68 | text=text, 69 | disable_web_page_preview=True, 70 | reply_markup=buttons 71 | ) 72 | 73 | except Exception as e: 74 | # print(e) 75 | await message.edit_text( 76 | text="Something went wrong" 77 | ) 78 | 79 | 80 | Bot.run() 81 | -------------------------------------------------------------------------------- /pypi.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from requests.utils import requote_uri 3 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton 4 | 5 | 6 | def details(query): 7 | try: 8 | # request to get json data 9 | r = requests.get(f"https://pypi.org/pypi/{requote_uri(query)}/json") 10 | r.raise_for_status() 11 | info = r.json()['info'] 12 | # error=False, because no error here 13 | info['error'] = False 14 | return info 15 | 16 | except requests.exceptions.RequestException as e: 17 | # if any error found, returns error message as json data 18 | return {'error': f"Error fetching information for {query}: {e}"} 19 | 20 | 21 | def pypi_text(query): 22 | 23 | info = details(query) 24 | 25 | if info['error']: 26 | return info.get['error'] 27 | 28 | text = "--**Informations**--\n" 29 | 30 | text += f"\n**Package Name:** `{info['name']}`" 31 | text += f"\n**Author:** `{info['author']}`" 32 | 33 | if info['author_email']: 34 | text += f"\n**Author Email:** {info['author_email']}" 35 | 36 | text += f"\n**Summary:** `{info['summary']}`" 37 | text += f"\n**Required Python Version:** {info['requires_python']}" 38 | text += f"\n**Latest Version:** `{str(info['version'])}`" 39 | 40 | if info['license']: 41 | text += f"\n**License:** `{info['license']}`" 42 | 43 | return text 44 | 45 | 46 | def pypi_buttons(query): 47 | 48 | info = details(query) 49 | feedback_button = [ 50 | InlineKeyboardButton('⚙ Feedback ⚙', url='https://telegram.me/FayasNoushad') 51 | ] 52 | buttons = [] 53 | 54 | # To checking error 55 | if info['error']: 56 | return InlineKeyboardMarkup([feedback_button]) 57 | 58 | if info['home_page']: 59 | buttons.append(InlineKeyboardButton(text="Home Page", url=info['home_page'])) 60 | 61 | if info['bugtrack_url']: 62 | buttons.append(InlineKeyboardButton(text="Bugtrack URL", url=info['bugtrack_url'])) 63 | 64 | buttons.extend([ 65 | InlineKeyboardButton(text="Package URL", url=info['package_url']), 66 | InlineKeyboardButton(text="Project URL", url=info['project_url']) 67 | ]) 68 | 69 | project_urls = info['project_urls'] 70 | 71 | # May be one or more project urls 72 | for i in project_urls: 73 | buttons.append(InlineKeyboardButton(text=i, url=project_urls[i])) 74 | 75 | # To arranging buttons 76 | arranged_buttons = [] 77 | 78 | line = [] 79 | for button in buttons: 80 | if len(line) < 2: 81 | line.append(button) 82 | # max no. of buttons in a line 83 | button_limit = 2 84 | if (len(line) == button_limit) or (button == buttons[-1]): 85 | arranged_buttons.append(line) 86 | line = [] 87 | else: 88 | line = [button] 89 | 90 | # adding feedback button on last 91 | arranged_buttons.append(feedback_button) 92 | 93 | all_buttons = InlineKeyboardMarkup(arranged_buttons) 94 | 95 | # return all buttons 96 | return all_buttons 97 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyrogram 2 | tgcrypto 3 | requests 4 | python-dotenv 5 | --------------------------------------------------------------------------------