diff --git a/nana/__init__.py b/nana/__init__.py index 3213a1ef..14aa38aa 100644 --- a/nana/__init__.py +++ b/nana/__init__.py @@ -4,10 +4,12 @@ import platform import sys import time +from inspect import getfullargspec import requests from pydrive.auth import GoogleAuth from pyrogram import Client, errors +from pyrogram.types import Message from sqlalchemy import create_engine, exc from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, scoped_session @@ -56,7 +58,7 @@ device_model = platform.machine() app_version = "💝 Nana v{}".format(USERBOT_VERSION) system_version = platform.platform() - +time_country = get_var('time_country', None) # Must be filled api_id = get_var('api_id', None) api_hash = get_var('api_hash', None) @@ -97,6 +99,9 @@ remove_bg_api = get_var('remove_bg_api', None) HEROKU_API = get_var('HEROKU_API', None) BINDERBYTE_API = get_var('BINDERBYTE_API', None) +sw_api = get_var('sw_api', None) +IBM_WATSON_CRED_URL = get_var('IBM_WATSON_CRED_URL', None) +IBM_WATSON_CRED_PASSWORD = get_var('IBM_WATSON_CRED_PASSWORD', None) # Spotify SPOTIPY_CLIENT_ID = get_var('SPOTIPY_CLIENT_ID', None) SPOTIPY_CLIENT_SECRET = get_var('SPOTIPY_CLIENT_SECRET', None) @@ -213,3 +218,8 @@ async def get_bot(): app = Client(APP_SESSION, api_id=api_id, api_hash=api_hash, app_version=app_version, device_model=device_model, system_version=system_version, lang_code=lang_code, workers=NANA_WORKER, test_mode=TEST_MODE) + +async def edrep(msg: Message, **kwargs): + func = msg.edit_text if msg.from_user.is_self else msg.reply + spec = getfullargspec(func.__wrapped__).args + await func(**{k: v for k, v in kwargs.items() if k in spec}) \ No newline at end of file diff --git a/nana/__main__.py b/nana/__main__.py index ae91e73c..38ab6985 100644 --- a/nana/__main__.py +++ b/nana/__main__.py @@ -117,6 +117,8 @@ async def start_bot(): if not imported_module.__MODULE__.lower() in HELP_COMMANDS: HELP_COMMANDS[imported_module.__MODULE__.lower()] = imported_module else: + print(HELP_COMMANDS[imported_module.__MODULE__.lower()]) + pass raise Exception("Can't have two modules with the same name! Please change one") if hasattr(imported_module, "__HELP__") and imported_module.__HELP__: HELP_COMMANDS[imported_module.__MODULE__.lower()] = imported_module diff --git a/nana/assistant/stickers.py b/nana/assistant/stickers.py index dae312c6..92ccd088 100644 --- a/nana/assistant/stickers.py +++ b/nana/assistant/stickers.py @@ -65,9 +65,8 @@ def get_stickerlist(message): global TEMP_KEYBOARD, USER_SET if message.from_user and message.from_user.id in list(USER_SET): return True - else: - TEMP_KEYBOARD = [] - USER_SET = {} + TEMP_KEYBOARD = [] + USER_SET = {} @setbot.on_message(get_stickerlist) diff --git a/nana/helpers/expand.py b/nana/helpers/expand.py new file mode 100644 index 00000000..c21ee4a4 --- /dev/null +++ b/nana/helpers/expand.py @@ -0,0 +1,9 @@ +import aiohttp + + +async def expand_url(url): + async with aiohttp.ClientSession() as session: + async with session.get(f"http://expandurl.com/api/v1/?url={url}") as resp: + expanded = await resp.text() + + return expanded if expanded != "false" and expanded[:-1] != url else None \ No newline at end of file diff --git a/nana/modules/__init__.py b/nana/modules/__init__.py index 8d707fa2..ee6bef64 100644 --- a/nana/modules/__init__.py +++ b/nana/modules/__init__.py @@ -1,34 +1,37 @@ -from nana import USERBOT_LOAD, USERBOT_NOLOAD, log - - -def __list_all_modules(): - from os.path import dirname, basename, isfile - import glob - # This generates a list of modules in this folder for the * in __main__ to work. - mod_paths = glob.glob(dirname(__file__) + "/*.py") - all_modules = [basename(f)[:-3] for f in mod_paths if isfile(f) - and f.endswith(".py") - and not f.endswith('__init__.py')] - - if USERBOT_LOAD or USERBOT_NOLOAD: - to_load = USERBOT_LOAD - if to_load: - if not all(any(mod == module_name for module_name in all_modules) for mod in to_load): - log.error("Invalid Module name for userbot!") - quit(1) - - else: - to_load = all_modules - - if USERBOT_NOLOAD: - log.info("Userbot No load: {}".format(USERBOT_NOLOAD)) - return [item for item in to_load if item not in USERBOT_NOLOAD] - - return to_load - - return all_modules - - -ALL_MODULES = sorted(__list_all_modules()) -log.info("Userbot module loaded: %s", str(ALL_MODULES)) -__all__ = ALL_MODULES + ["ALL_MODULES"] +""" +Directory for modules. +""" +from nana import USERBOT_LOAD, USERBOT_NOLOAD, log + + +def __list_all_modules(): + from os.path import dirname, basename, isfile + import glob + # This generates a list of modules in this folder for the * in __main__ to work. + mod_paths = glob.glob(dirname(__file__) + "/*.py") + all_modules = [basename(f)[:-3] for f in mod_paths if isfile(f) + and f.endswith(".py") + and not f.endswith('__init__.py')] + + if USERBOT_LOAD or USERBOT_NOLOAD: + to_load = USERBOT_LOAD + if to_load: + if not all(any(mod == module_name for module_name in all_modules) for mod in to_load): + log.error("Invalid Module name for userbot!") + quit(1) + + else: + to_load = all_modules + + if USERBOT_NOLOAD: + log.info("Userbot No load: {}".format(USERBOT_NOLOAD)) + return [item for item in to_load if item not in USERBOT_NOLOAD] + + return to_load + + return all_modules + + +ALL_MODULES = sorted(__list_all_modules()) +log.info("Userbot module loaded: %s", str(ALL_MODULES)) +__all__ = ALL_MODULES + ["ALL_MODULES"] diff --git a/nana/modules/afk.py b/nana/modules/afk.py index 5e19dfad..b1d038b7 100644 --- a/nana/modules/afk.py +++ b/nana/modules/afk.py @@ -3,7 +3,7 @@ from pyrogram import filters from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton -from nana import app, setbot, Owner, OwnerName, Command, DB_AVAILABLE +from nana import app, setbot, Owner, OwnerName, Command, DB_AVAILABLE, edrep from nana.helpers.msg_types import Types, get_message_type from nana.helpers.parser import mention_markdown, escape_markdown @@ -33,7 +33,7 @@ DELAY_TIME = 60 # seconds -@app.on_message(filters.me & (filters.command(["afk"], Command) | filters.regex("^brb "))) +@app.on_message(filters.me & (filters.command("afk", Command))) async def afk(_client, message): if not DB_AVAILABLE: await message.edit("Your database is not avaiable!") @@ -64,22 +64,19 @@ async def afk_mentioned(_client, message): else: cid = str(message.chat.id) - if cid in list(AFK_RESTIRECT): - if int(AFK_RESTIRECT[cid]) >= int(time.time()): - return + if cid in list(AFK_RESTIRECT) and int(AFK_RESTIRECT[cid]) >= int( + time.time() + ): + return AFK_RESTIRECT[cid] = int(time.time()) + DELAY_TIME if get['reason']: - await message.reply( - "Sorry, {} is AFK!\nBecause of {}".format(mention_markdown(Owner, OwnerName), get['reason'])) + await edrep(message, text=f"Sorry, {mention_markdown(Owner, OwnerName)} is AFK!\nBecause of {get['reason']}") else: - await message.reply("Sorry, {} is AFK!".format(mention_markdown(Owner, OwnerName))) + await edrep(message, text=f"Sorry, {mention_markdown(Owner, OwnerName)} is AFK!") _, message_type = get_message_type(message) if message_type == Types.TEXT: - if message.text: - text = message.text - else: - text = message.caption + text = message.text if message.text else message.caption else: text = message_type.name diff --git a/nana/modules/alive.py b/nana/modules/alive.py new file mode 100644 index 00000000..27530905 --- /dev/null +++ b/nana/modules/alive.py @@ -0,0 +1,56 @@ + +import time + +from pyrogram import filters + +from nana import setbot, AdminSettings, BotUsername, app, Command, OwnerUsername, StartTime +from nana.helpers.PyroHelpers import ReplyCheck + + +def get_readable_time(seconds: int) -> str: + count = 0 + ping_time = "" + time_list = [] + time_suffix_list = ["s", "m", "h", "days"] + + while count < 4: + count += 1 + remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24) + if seconds == 0 and remainder == 0: + break + time_list.append(int(result)) + seconds = int(remainder) + + for x in range(len(time_list)): + time_list[x] = str(time_list[x]) + time_suffix_list[x] + if len(time_list) == 4: + ping_time += time_list.pop() + ", " + + time_list.reverse() + ping_time += ":".join(time_list) + + return ping_time + + +@setbot.on_callback_query(filters.regex("^alive_message")) +async def alivemsg_callback(client, query): + start_time = time.time() + uptime = get_readable_time((time.time() - StartTime)) + reply_msg = f"{OwnerUsername}@nana-remix\n" + reply_msg += "------------------\n" + end_time = time.time() + ping_time = round((end_time - start_time) * 1000, 3) + reply_msg += f"Ping: {ping_time}ms\n" + reply_msg += f"Userbot uptime: {uptime}" + await client.answer_callback_query(query.id, reply_msg, show_alert=True) + + +@app.on_message(filters.user(AdminSettings) & filters.command("alive", Command)) +async def google_search(client, message): + x = await client.get_inline_bot_results(f"{BotUsername}", "alive") + await message.delete() + await client.send_inline_bot_result(chat_id=message.chat.id, + query_id=x.query_id, + result_id=x.results[0].id, + reply_to_message_id=ReplyCheck(message), + hide_via=True) \ No newline at end of file diff --git a/nana/modules/animelist.py b/nana/modules/animelist.py index 30f4ee7f..926a79cd 100644 --- a/nana/modules/animelist.py +++ b/nana/modules/animelist.py @@ -1,21 +1,25 @@ +import requests import asyncio +import re -from jikanpy import Jikan -from jikanpy.exceptions import APIException +import requests from pyrogram import filters -from nana import app, Command -from nana.helpers.string import replace_text +from nana import app, Command, AdminSettings, BotUsername, edrep, Owner, setbot +from nana.helpers.PyroHelpers import ReplyCheck +from nana.modules.database import anime_db as sql -__MODULE__ = "MyAnimeList" +__MODULE__ = "Anilist" __HELP__ = """ -Get information about anime, manga or characters from [MyAnimeList](https://myanimelist.net). +Get information about anime, manga or characters from [Anilist](https://anilist.co). ──「 **Anime** 」── -> `anime ` returns information about the anime. +__Original Module by @Zero_cooll7870__ + ──「 **Character** 」── -> `character ` returns information about the character. @@ -24,183 +28,306 @@ -> `manga ` returns information about the manga. -──「 **Upcoming Anime** 」── --> `upcoming` -returns a list of new anime in the upcoming seasons. +──「 **Airing** 」── +-> `airing ` +To get airing time of the anime. + +──「 **Favourite List** 」── +-> `favourite` +Get your favourite Anime list. + """ -jikan = Jikan() -@app.on_message(filters.me & filters.command(["anime"], Command)) -async def anime(_client, message): - cmd = message.command - query = "" - if len(cmd) > 1: - query = " ".join(cmd[1:]) - elif message.reply_to_message and len(cmd) == 1: - query = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`cant find anime.`") - await asyncio.sleep(2) - await message.delete() - return - res = "" - try: - res = jikan.search("anime", query) - except APIException: - await message.edit("Error connecting to the API. Please try again!") - return "" - try: - res = res.get("results")[0].get("mal_id") # Grab first result - except APIException: - await message.edit("Error connecting to the API. Please try again!") - return "" - if res: - anime = jikan.anime(res) - title = anime.get("title") - japanese = anime.get("title_japanese") - type = anime.get("type") - duration = anime.get("duration") - synopsis = anime.get("synopsis") - source = anime.get("source") - status = anime.get("status") - episodes = anime.get("episodes") - score = anime.get("score") - rating = anime.get("rating") - genre_lst = anime.get("genres") - genres = "" - for genre in genre_lst: - genres += genre.get("name") + ", " - genres = genres[:-2] - studios = "" - studio_lst = anime.get("studios") - for studio in studio_lst: - studios += studio.get("name") + ", " - studios = studios[:-2] - duration = anime.get("duration") - premiered = anime.get("premiered") - image_url = anime.get("image_url") - url = anime.get("url") +def shorten(description, info='anilist.co'): + ms_g = "" + if len(description) > 700: + description = description[0:500] + '....' + ms_g += f"\n**Description**: __{description}__[Read More]({info})" else: - await message.edit("No results found!") + ms_g += f"\n**Description**: __{description}__" + return ( + ms_g.replace("
", "") + .replace("
", "") + .replace("", "") + .replace("", "") + ) + + +# time formatter from uniborg +def t(milliseconds: int) -> str: + """Inputs time in milliseconds, to get beautified time, + as string""" + seconds, milliseconds = divmod(int(milliseconds), 1000) + minutes, seconds = divmod(seconds, 60) + hours, minutes = divmod(minutes, 60) + days, hours = divmod(hours, 24) + tmp = ((str(days) + " Days, ") if days else "") + \ + ((str(hours) + " Hours, ") if hours else "") + \ + ((str(minutes) + " Minutes, ") if minutes else "") + \ + ((str(seconds) + " Seconds, ") if seconds else "") + \ + ((str(milliseconds) + " ms, ") if milliseconds else "") + return tmp[:-2] + + +airing_query = ''' + query ($id: Int,$search: String) { + Media (id: $id, type: ANIME,search: $search) { + id + episodes + title { + romaji + english + native + } + nextAiringEpisode { + airingAt + timeUntilAiring + episode + } + } + } + ''' + +fav_query = """ +query ($id: Int) { + Media (id: $id, type: ANIME) { + id + title { + romaji + english + native + } + } +} +""" + +anime_query = ''' + query ($id: Int,$search: String) { + Media (id: $id, type: ANIME,search: $search) { + id + title { + romaji + english + native + } + description (asHtml: false) + startDate{ + year + } + episodes + season + type + format + status + duration + siteUrl + studios{ + nodes{ + name + } + } + trailer{ + id + site + thumbnail + } + averageScore + genres + bannerImage + } + } +''' +character_query = """ + query ($query: String) { + Character (search: $query) { + id + name { + first + last + full + } + siteUrl + image { + large + } + description + } + } +""" + +manga_query = """ +query ($id: Int,$search: String) { + Media (id: $id, type: MANGA,search: $search) { + id + title { + romaji + english + native + } + description (asHtml: false) + startDate{ + year + } + type + format + status + siteUrl + averageScore + genres + bannerImage + } + } +""" + + +url = 'https://graphql.anilist.co' + + +@app.on_message(filters.user(AdminSettings) & filters.command("airing", Command)) +async def anime_airing(_client, message): + search_str = message.text.split(' ', 1) + if len(search_str) == 1: + await edrep(message, text='Format: `airing `') return - rep = f"{title} ({japanese})\n" - rep += f"Type: {type}\n" - rep += f"Source: {source}\n" - rep += f"Status: {status}\n" - rep += f"Genres: {genres}\n" - rep += f"Episodes: {episodes}\n" - rep += f"Duration: {duration}\n" - rep += f"Score: {score}\n" - rep += f"Studio(s): {studios}\n" - rep += f"Premiered: {premiered}\n" - rep += f"Rating: {rating}\n\n" - rep += f"\u200c" - rep += f"{synopsis}\n" - rep += f'Read More: MyAnimeList' - await message.edit(rep) - -@app.on_message(filters.me & filters.command(["character"], Command)) -async def character(_client, message): - res = "" + variables = {'search': search_str[1]} + response = requests.post( + url, json={'query': airing_query, 'variables': variables}).json()['data']['Media'] + ms_g = f"**Name**: **{response['title']['romaji']}**(`{response['title']['native']}`)\n**ID**: `{response['id']}`" + if response['nextAiringEpisode']: + airing_time = response['nextAiringEpisode']['timeUntilAiring'] * 1000 + airing_time_final = t(airing_time) + ms_g += f"\n**Episode**: `{response['nextAiringEpisode']['episode']}`\n**Airing In**: `{airing_time_final}`" + else: + ms_g += f"\n**Episode**:{response['episodes']}\n**Status**: `N/A`" + await edrep(message, text=ms_g) + + +@app.on_message(filters.user(AdminSettings) & filters.command("anime", Command)) +async def anime_search(client, message): cmd = message.command - query = "" + mock = "" if len(cmd) > 1: - query = " ".join(cmd[1:]) - elif message.reply_to_message and len(cmd) == 1: - query = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`cant find character.`") + mock = " ".join(cmd[1:]) + elif len(cmd) == 1: + await edrep(message, text="`Format: anime `") await asyncio.sleep(2) await message.delete() return - try: - search = jikan.search("character", query).get("results")[0].get("mal_id") - except APIException: - message.edit("No results found!") - return "" - if search: - try: - res = jikan.character(search) - except APIException: - message.edit("Error connecting to the API. Please try again!") - return "" - if res: - name = res.get("name") - kanji = res.get("name_kanji") - about = res.get("about") - if len(about) > 4096: - about = about[:4000] + "..." - image = res.get("image_url") - url = res.get("url") - rep = f"{name} ({kanji})\n\n" - rep += f"\u200c" - rep += f"{about}\n" - rep += f'Read More: MyAnimeList' - await message.edit(replace_text(rep)) - -@app.on_message(filters.me & filters.command(["manga"], Command)) -async def manga(_client, message): - cmd = message.command - query = "" - if len(cmd) > 1: - query = " ".join(cmd[1:]) - elif message.reply_to_message and len(cmd) == 1: - query = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`cant find manga.`") - await asyncio.sleep(2) + x = await client.get_inline_bot_results(f"{BotUsername}", f"anime {mock}") + await message.delete() + await client.send_inline_bot_result(chat_id=message.chat.id, + query_id=x.query_id, + result_id=x.results[0].id, + reply_to_message_id=ReplyCheck(message), + hide_via=True) + + +@app.on_message(filters.user(AdminSettings) & filters.command("character", Command)) +async def character_search(client, message): + search = message.text.split(' ', 1) + if len(search) == 1: await message.delete() return - res = "" - manga = "" - try: - res = jikan.search("manga", query).get("results")[0].get("mal_id") - except APIException: - await message.edit("Error connecting to the API. Please try again!") - return "" - if res: - try: - manga = jikan.manga(res) - except APIException: - message.edit("Error connecting to the API. Please try again!") - return "" - title = manga.get("title") - japanese = manga.get("title_japanese") - type = manga.get("type") - status = manga.get("status") - score = manga.get("score") - volumes = manga.get("volumes") - chapters = manga.get("chapters") - genre_lst = manga.get("genres") - genres = "" - for genre in genre_lst: - genres += genre.get("name") + ", " - genres = genres[:-2] - synopsis = manga.get("synopsis") - image = manga.get("image_url") - url = manga.get("url") - rep = f"{title} ({japanese})\n" - rep += f"Type: {type}\n" - rep += f"Status: {status}\n" - rep += f"Genres: {genres}\n" - rep += f"Score: {score}\n" - rep += f"Volumes: {volumes}\n" - rep += f"Chapters: {chapters}\n\n" - rep += f"\u200c" - rep += f"{synopsis}" - rep += f'Read More: {url}' - await message.edit(rep) - -@app.on_message(filters.me & filters.command(["upcoming"], Command)) -async def upcoming(_client, message): - rep = "Upcoming anime\n" - later = jikan.season_later() - anime = later.get("anime") - for new in anime: - name = new.get("title") - url = new.get("url") - rep += f"• {name}\n" - if len(rep) > 1000: - break - await message.edit(rep, parse_mode='html') \ No newline at end of file + search = search[1] + variables = {'query': search} + json = requests.post(url, json={'query': character_query, 'variables': variables}).json()['data'].get('Character', None) + if json: + ms_g = f"**{json.get('name').get('full')}**(`{json.get('name').get('native')}`)\n" + description = f"{json['description']}" + site_url = json.get('siteUrl') + ms_g += shorten(description, site_url) + image = json.get('image', None) + if image: + image = image.get('large') + await message.delete() + await client.send_photo(message.chat.id, photo=image, caption=ms_g) + else: + await edrep(message, text=ms_g) + + +@app.on_message(filters.user(AdminSettings) & filters.command("manga", Command)) +async def manga_search(client, message): + search = message.text.split(' ', 1) + if len(search) == 1: + await message.delete() + return + search = search[1] + variables = {'search': search} + json = requests.post(url, json={'query': manga_query, 'variables': variables}).json()[ + 'data'].get('Media', None) + ms_g = '' + if json: + title, title_native = json['title'].get( + 'romaji', False), json['title'].get('native', False) + start_date, status, score = json['startDate'].get('year', False), json.get( + 'status', False), json.get('averageScore', False) + if title: + ms_g += f"**{title}**" + if title_native: + ms_g += f"(`{title_native}`)" + if start_date: + ms_g += f"\n**Start Date** - `{start_date}`" + if status: + ms_g += f"\n**Status** - `{status}`" + if score: + ms_g += f"\n**Score** - `{score}`" + ms_g += '\n**Genres** - ' + for x in json.get('genres', []): + ms_g += f"{x}, " + ms_g = ms_g[:-2] + + image = json.get("bannerImage", False) + ms_g += f"_{json.get('description', None)}_" + if image: + try: + await message.delete() + await client.send_photo(message.chat.id, photo=image, caption=ms_g) + except: + ms_g += f" [〽️]({image})" + await edrep(message, text=ms_g) + else: + await edrep(message, text=ms_g) + + +@app.on_message(filters.user(AdminSettings) & filters.command("favourite", Command)) +async def favourite_animelist(client, message): + x = await client.get_inline_bot_results(f"{BotUsername}", f"favourite") + await message.delete() + await client.send_inline_bot_result(chat_id=message.chat.id, + query_id=x.query_id, + result_id=x.results[0].id, + reply_to_message_id=ReplyCheck(message), + hide_via=True) + + +async def addfav_callback(_, __, query): + if re.match(r"addfav_", query.data): + return True + + +async def remfav_callback(_, __, query): + if re.match(r"remfav_", query.data): + return True + + +@setbot.on_callback_query(filters.create(addfav_callback)) +async def add_favorite(client, query): + if query.from_user.id in AdminSettings: + match = query.data.split("_")[1] + add = sql.add_fav(Owner, match) + if add: + await query.answer('Added to Favourites', show_alert=True) + else: + await query.answer('Anime already Exists in Favourites', show_alert=True) + else: + await query.answer('You are not Allowed to Press this', show_alert=True) + + +@setbot.on_callback_query(filters.create(remfav_callback)) +async def rem_favorite(client, query): + if query.from_user.id in AdminSettings: + sql.remove_fav(Owner) + await setbot.edit_inline_text(query.inline_message_id,'Removed from Favourites') + else: + await query.answer('You are not Allowed to Press this', show_alert=True) \ No newline at end of file diff --git a/nana/modules/bitly.py b/nana/modules/bitly.py index 1898eb66..4fe05e24 100644 --- a/nana/modules/bitly.py +++ b/nana/modules/bitly.py @@ -1,28 +1,37 @@ -from bitlyshortener import Shortener +from asyncio import sleep + from pyrogram import filters -from nana import app, Command, bitly_token +from nana import app, Command, AdminSettings, edrep +from nana.helpers.expand import expand_url -__MODULE__ = "Bitly" +__MODULE__ = "Link Expander" __HELP__ = """ -This module will shortener your link - -──「 **shorten your url** 」── --> `bitly (link)` -Shorten your url with bitly +This module will expand your link +──「 **expand url** 」── +-> `expand (link)` +Reply or parse arg of url to expand """ -@app.on_message(filters.me & filters.command(["bitly"], Command)) -async def bitly(_client, message): - args = message.text.split(None, 1) - shortener = Shortener(tokens=bitly_token, max_cache_size=8192) - if len(args) == 1: - await message.edit("Usage bitly (url)!") - return - if len(args) == 2: - await message.edit("Processing") - urls = [args[1]] - shortlink = shortener.shorten_urls(urls) - await message.edit("Here Your link\n{}".format(shortlink[0]), disable_web_page_preview=True) +@app.on_message(filters.command("expand", Command) & filters.user(AdminSettings)) +async def expand(_client, message): + if message.reply_to_message: + url = message.reply_to_message.text or message.reply_to_message.caption + elif len(message.command) > 1: + url = message.command[1] + else: + url = None + + if url: + expanded = await expand_url(url) + if expanded: + await edrep(message, text=f"Shortened URL: {url}\nExpanded URL: {expanded}", disable_web_page_preview=True) + return + else: + await edrep(message, text="`i Cant expand this url :p`") + await sleep(3) + await message.delete() + else: + await edrep(message, text="Nothing to expand") diff --git a/nana/modules/calculator.py b/nana/modules/calculator.py index cd1549ab..906abc92 100644 --- a/nana/modules/calculator.py +++ b/nana/modules/calculator.py @@ -1,21 +1,12 @@ -import os -import sys -import traceback - from currency_converter import CurrencyConverter from pyrogram import filters -from nana import app, Command, logging +from nana import app, Command, AdminSettings, edrep __MODULE__ = "Calculator" __HELP__ = """ Calculator, converting, math, etc. -──「 **Evaluation** 」── --> `eval (math)` -Example: `eval 1+1` -Math can be used: `+, -, *, /` - ──「 **Money converter** 」── -> `curr (value) (from) (to)` Examlpe: `curr 100 USD IDR` @@ -43,40 +34,10 @@ def convert_c(celsius): return cel -@app.on_message(filters.me & filters.command(["eval"], Command)) -async def evaluation(client, message): - if len(message.text.split()) == 1: - await message.edit("Usage: `eval 1000-7`") - return - q = message.text.split(None, 1)[1] - try: - ev = str(eval(q)) - if ev: - if len(ev) >= 4096: - file = open("nana/cache/output.txt", "w+") - file.write(ev) - file.close() - await client.send_file(message.chat.id, "nana/cache/output.txt", - caption="`Output too large, sending as file`") - os.remove("nana/cache/output.txt") - return - else: - await message.edit("**Query:**\n{}\n\n**Result:**\n`{}`".format(q, ev)) - return - else: - await message.edit("**Query:**\n{}\n\n**Result:**\n`None`".format(q)) - return - except: - exc_type, exc_obj, exc_tb = sys.exc_info() - errors = traceback.format_exception(etype=exc_type, value=exc_obj, tb=exc_tb) - await message.edit("Error: `{}`".format(errors)) - logging.exception("Evaluation error") - - -@app.on_message(filters.me & filters.command(["curr"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("curr", Command)) async def evaluation_curr(_client, message): if len(message.text.split()) <= 3: - await message.edit("Usage: `curr 100 USD IDR`") + await edrep(message, text="Usage: `curr 100 USD IDR`") return value = message.text.split(None, 3)[1] curr1 = message.text.split(None, 3)[2].upper() @@ -84,15 +45,15 @@ async def evaluation_curr(_client, message): try: conv = c.convert(int(value), curr1, curr2) text = "{} {} = {} {}".format(curr1, value, curr2, f'{conv:,.2f}') - await message.edit(text) + await edrep(message, text=text) except ValueError as err: - await message.edit(str(err)) + await edrep(message, text=str(err)) -@app.on_message(filters.me & filters.command(["temp"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("temp", Command)) async def evaluation_temp(_client, message): if len(message.text.split()) <= 2: - await message.edit("Usage: `temp 30 C` or `temp 60 F`") + await edrep(message, text="Usage: `temp 30 C` or `temp 60 F`") return temp1 = message.text.split(None, 2)[1] temp2 = message.text.split(None, 2)[2] @@ -100,12 +61,12 @@ async def evaluation_temp(_client, message): if temp2 == "F": result = convert_c(temp1) text = "`{}°F` = `{}°C`".format(temp1, result) - await message.edit(text) + await edrep(message, text=text) elif temp2 == "C": result = convert_f(temp1) text = "`{}°C` = `{}°F`".format(temp1, result) - await message.edit(text) + await edrep(message, text=text) else: - await message.edit("Unknown type {}".format(temp2)) + await edrep(message, text="Unknown type {}".format(temp2)) except ValueError as err: - await message.edit(str(err)) + await edrep(message, text=str(err)) diff --git a/nana/modules/cat.py b/nana/modules/cat.py new file mode 100644 index 00000000..cd893335 --- /dev/null +++ b/nana/modules/cat.py @@ -0,0 +1,38 @@ +import random +import re + +from pyrogram import filters +from pyrogram.types import InputMediaPhoto, InlineKeyboardMarkup, InlineKeyboardButton + +from nana import setbot, AdminSettings + + +def cat_callback(_, __, query): + if re.match("cat_pic", query.data): + return True + +cat_create = filters.create(cat_callback) + +def speed_convert(size): + """Hi human, you can't read bytes?""" + power = 2 ** 10 + zero = 0 + units = {0: '', 1: 'Kb/s', 2: 'Mb/s', 3: 'Gb/s', 4: 'Tb/s'} + while size > power: + size /= power + zero += 1 + return f"{round(size, 2)} {units[zero]}" + +@setbot.on_callback_query(cat_create) +async def catpic_callback(client, query): + if query.from_user.id in AdminSettings: + image = f"https://d2ph5fj80uercy.cloudfront.net/0{random.randint(1, 6)}/cat{random.randint(0,4999)}.jpg" + buttons = [[InlineKeyboardButton("Source", url="https://thiscatdoesnotexist.com/"), InlineKeyboardButton("Refresh", callback_data='cat_pic')]] + await setbot.edit_inline_media(query.inline_message_id, InputMediaPhoto(media=image, + caption='Hi I like you too >~<'), + reply_markup=InlineKeyboardMarkup(buttons) + ) + else: + await client.answer_callback_query(query.id, + "No, you are not allowed to do this", + show_alert=False) \ No newline at end of file diff --git a/nana/modules/chats.py b/nana/modules/chats.py index d26de49a..4efae5a3 100644 --- a/nana/modules/chats.py +++ b/nana/modules/chats.py @@ -2,7 +2,7 @@ from pyrogram import filters -from nana import app, Command, DB_AVAILABLE +from nana import app, Command, DB_AVAILABLE, AdminSettings, edrep if DB_AVAILABLE: from nana.modules.database.chats_db import update_chat, get_all_chats @@ -34,10 +34,10 @@ async def updatemychats(_client, message): MESSAGE_RECOUNTER += 1 -@app.on_message(filters.me & filters.command(["chatlist"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("chatlist", Command)) async def get_chat(client, message): if not DB_AVAILABLE: - await message.edit("Your database is not avaiable!") + await edrep(message, text="Your database is not avaiable!") return all_chats = get_all_chats() chatfile = 'List of chats that I joined.\n' @@ -53,5 +53,5 @@ async def get_chat(client, message): await client.send_document("self", document="nana/cache/chatlist.txt", caption="Here is the chat list that I joined.") - await message.edit("My chat list exported to my saved messages.") + await edrep(message, text="My chat list exported to my saved messages.") os.remove("nana/cache/chatlist.txt") diff --git a/nana/modules/corona_virus.py b/nana/modules/corona_virus.py index 8ffe2d3c..8f509587 100644 --- a/nana/modules/corona_virus.py +++ b/nana/modules/corona_virus.py @@ -3,7 +3,7 @@ from pyrogram import filters -from nana import Command, app +from nana import Command, app, AdminSettings, edrep from nana.helpers.aiohttp_helper import AioHttp __MODULE__ = "Covid" @@ -16,51 +16,53 @@ """ -@app.on_message(filters.me & filters.command(["covid"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("covid", Command)) async def corona(_client, message): args = message.text.split(None, 1) if len(args) == 1: try: r = await AioHttp().get_json("https://corona.lmao.ninja/v2/all") reply_text = f"""**Global Cases 🦠:** -Cases: `{r['cases']:,}` -Cases Today: `{r['todayCases']:,}` -Deaths: `{r['deaths']:,}` -Deaths Today: `{r['todayDeaths']:,}` -Recovered: `{r['recovered']:,}` -Active: `{r['active']:,}` -Critical: `{r['critical']:,}` -Cases/Mil: `{r['casesPerOneMillion']}` -Deaths/Mil: `{r['deathsPerOneMillion']}`` + - **Cases:** `{r['cases']:,}` + - **Cases Today:** `{r['todayCases']:,}` + - **Deaths:** `{r['deaths']:,}` + - **Deaths Today:** `{r['todayDeaths']:,}` + - **Recovered:** `{r['recovered']:,}` + - **Active:** `{r['active']:,}` + - **Critical:** `{r['critical']:,}` + - **Cases/Mil:** `{r['casesPerOneMillion']}` + - **Deaths/Mil:** `{r['deathsPerOneMillion']}`` """ - await message.edit(f"{reply_text}") + await edrep(message, text=f"{reply_text}") return except Exception as e: - await message.edit("`The corona API could not be reached`") + await edrep(message, text="`The corona API could not be reached`") + print(e) await asyncio.sleep(3) await message.delete() return country = args[1] r = await AioHttp().get_json(f"https://corona.lmao.ninja/v2/countries/{country}") if "cases" not in r: - await message.edit("```The country could not be found!```") + await edrep(message, text="```The country could not be found!```") await asyncio.sleep(3) await message.delete() else: try: reply_text = f"""**Cases for {r['country']} 🦠:** -Cases: `{r['cases']:,}` -Cases Today: `{r['todayCases']:,}` -Deaths: `{r['deaths']:,}` -Deaths Today: `{r['todayDeaths']:,}` -Recovered: `{r['recovered']:,}` -Active: `{r['active']:,}` -Critical: `{r['critical']:,}` -Cases/Mil: `{r['casesPerOneMillion']}` -Deaths/Mil: `{r['deathsPerOneMillion']}` + - **Cases:** `{r['cases']:,}` + - **Cases Today:** `{r['todayCases']:,}` + - **Deaths:** `{r['deaths']:,}` + - **Deaths Today:** `{r['todayDeaths']:,}` + - **Recovered:** `{r['recovered']:,}` + - **Active:** `{r['active']:,}` + - **Critical:** `{r['critical']:,}` + - **Cases/Mil:** `{r['casesPerOneMillion']}` + - **Deaths/Mil:** `{r['deathsPerOneMillion']}` """ - await message.edit(f"{reply_text}") + await edrep(message, text=reply_text) except Exception as e: - await message.edit("`The corona API could not be reached`") + await edrep(message, text="`The corona API could not be reached`") + print(e) await asyncio.sleep(3) await message.delete() diff --git a/nana/modules/database/afk_db.py b/nana/modules/database/afk_db.py index d4c747f2..afa074bd 100644 --- a/nana/modules/database/afk_db.py +++ b/nana/modules/database/afk_db.py @@ -10,11 +10,13 @@ class AFK(BASE): reason = Column(UnicodeText, default=False) def __init__(self, user_id, is_afk, reason): + "initializing db" self.user_id = str(user_id) self.is_afk = is_afk self.reason = reason def __repr__(self): + "afk message for db" return "".format(self.user_id) diff --git a/nana/modules/database/anime_db.py b/nana/modules/database/anime_db.py new file mode 100644 index 00000000..fd55416a --- /dev/null +++ b/nana/modules/database/anime_db.py @@ -0,0 +1,64 @@ +import threading + +from sqlalchemy import Column, UnicodeText, Numeric + +from nana import SESSION, BASE + + +class Favourites(BASE): + __tablename__ = "favourites" + user_id = Column(Numeric, primary_key=True) + data = Column(UnicodeText, primary_key=True) + + def __init__(self, user_id, data): + self.user_id = user_id + self.data = data + + +Favourites.__table__.create(checkfirst=True) +FAV_INSERTION_LOCK = threading.RLock() + + +def check_fav(user_id, data): + try: + return SESSION.query(Favourites).get((int(user_id), str(data))) + finally: + SESSION.close() + + +def get_fav(user_id): + try: + return ( + SESSION.query(Favourites).filter(Favourites.user_id == int(user_id)).all() + ) + finally: + SESSION.close() + + +def add_fav(user_id, data): + with FAV_INSERTION_LOCK: + to_check = check_fav(user_id, data) + if not to_check: + adder = Favourites(int(user_id), str(data)) + SESSION.add(adder) + SESSION.commit() + return True + return False + + +def remove_fav(user_id): + with FAV_INSERTION_LOCK: + to_check = get_fav(user_id) + if not to_check: + return False + rem = SESSION.query(Favourites).filter(Favourites.user_id == user_id) + rem.delete() + SESSION.commit() + return True + + +def fav_count(): + try: + return SESSION.query(Favourites).count() + finally: + SESSION.close() \ No newline at end of file diff --git a/nana/modules/database/chats_db.py b/nana/modules/database/chats_db.py index dabf0865..6fe9ec89 100644 --- a/nana/modules/database/chats_db.py +++ b/nana/modules/database/chats_db.py @@ -10,11 +10,13 @@ class MyChats(BASE): chat_username = Column(UnicodeText) def __init__(self, chat_id, chat_name, chat_username): + "initializing db" self.chat_id = str(chat_id) self.chat_name = chat_name self.chat_username = chat_username def __repr__(self): + "chat message for db" return "".format(self.chat_name, self.chat_id) @@ -25,10 +27,13 @@ def __repr__(self): def update_chat(chat): global MY_ALL_CHATS - if chat.id in list(MY_ALL_CHATS): - if MY_ALL_CHATS.get(chat.id) and MY_ALL_CHATS[chat.id].get('name') == chat.title and MY_ALL_CHATS[chat.id].get( - 'username') == chat.username: - return + if ( + chat.id in list(MY_ALL_CHATS) + and MY_ALL_CHATS.get(chat.id) + and MY_ALL_CHATS[chat.id].get('name') == chat.title + and MY_ALL_CHATS[chat.id].get('username') == chat.username + ): + return chat_db = SESSION.query(MyChats).get(str(chat.id)) if chat_db: SESSION.delete(chat_db) diff --git a/nana/modules/database/cloner_db.py b/nana/modules/database/cloner_db.py index cda819cd..376bd6d3 100644 --- a/nana/modules/database/cloner_db.py +++ b/nana/modules/database/cloner_db.py @@ -11,12 +11,14 @@ class Cloner(BASE): bio = Column(UnicodeText) def __init__(self, user_id, first_name, last_name, bio): + "intialize cloner db" self.user_id = str(user_id) self.first_name = first_name self.last_name = last_name self.bio = bio def __repr__(self): + "clooner message for db" return "".format(self.user_id) diff --git a/nana/modules/database/lang_db.py b/nana/modules/database/lang_db.py new file mode 100644 index 00000000..7e82799f --- /dev/null +++ b/nana/modules/database/lang_db.py @@ -0,0 +1,36 @@ +import threading + +from sqlalchemy import Column, String, UnicodeText + +from nana import BASE, SESSION + + +class Locales(BASE): + __tablename__ = "locales" + chat_id = Column(String(14), primary_key=True) + locale_name = Column(UnicodeText) + + def __init__(self, chat_id, locale_name): + self.chat_id = str(chat_id) # ensure string + self.locale_name = locale_name + + +Locales.__table__.create(checkfirst=True) +LOCALES_INSERTION_LOCK = threading.RLock() + + +def switch_to_locale(chat_id, locale_name): + with LOCALES_INSERTION_LOCK: + prev = SESSION.query(Locales).get((str(chat_id))) + if prev: + SESSION.delete(prev) + switch_locale = Locales(str(chat_id), locale_name) + SESSION.add(switch_locale) + SESSION.commit() + + +def prev_locale(chat_id): + try: + return SESSION.query(Locales).get((str(chat_id))) + finally: + SESSION.close() diff --git a/nana/modules/database/lydia_db.py b/nana/modules/database/lydia_db.py new file mode 100644 index 00000000..bd58931b --- /dev/null +++ b/nana/modules/database/lydia_db.py @@ -0,0 +1,72 @@ +import threading + +from sqlalchemy import Column, String + +from nana import BASE, SESSION + + +class ChatbotChats(BASE): + __tablename__ = "chatbot_chats" + chat_id = Column(String(14), primary_key=True) + ses_id = Column(String(70)) + expires = Column(String(15)) + + def __init__(self, chat_id, ses_id, expires): + """initializing db""" + self.chat_id = chat_id + self.ses_id = ses_id + self.expires = expires + + +ChatbotChats.__table__.create(checkfirst=True) + +INSERTION_LOCK = threading.RLock() + + +def is_chat(chat_id): + try: + chat = SESSION.query(ChatbotChats).get(str(chat_id)) + return bool(chat) + finally: + SESSION.close() + + +def set_ses(chat_id, ses_id, expires): + with INSERTION_LOCK: + autochat = SESSION.query(ChatbotChats).get(str(chat_id)) + if not autochat: + autochat = ChatbotChats(str(chat_id), str(ses_id), str(expires)) + else: + autochat.ses_id = str(ses_id) + autochat.expires = str(expires) + + SESSION.add(autochat) + SESSION.commit() + + +def get_ses(chat_id): + autochat = SESSION.query(ChatbotChats).get(str(chat_id)) + sesh = "" + exp = "" + if autochat: + sesh = str(autochat.ses_id) + exp = str(autochat.expires) + + SESSION.close() + return sesh, exp + + +def rem_chat(chat_id): + with INSERTION_LOCK: + autochat = SESSION.query(ChatbotChats).get(str(chat_id)) + if autochat: + SESSION.delete(autochat) + + SESSION.commit() + + +def get_all_chats(): + try: + return SESSION.query(ChatbotChats.chat_id).all() + finally: + SESSION.close() diff --git a/nana/modules/database/notes_db.py b/nana/modules/database/notes_db.py index dec7609c..9af15d04 100644 --- a/nana/modules/database/notes_db.py +++ b/nana/modules/database/notes_db.py @@ -15,6 +15,7 @@ class SelfNotes(BASE): file = Column(UnicodeText) def __init__(self, user_id, name, value, msgtype, file): + """initializing db""" self.user_id = user_id self.name = name self.value = value @@ -22,6 +23,7 @@ def __init__(self, user_id, name, value, msgtype, file): self.file = file def __repr__(self): + """get db message""" return "" % self.name @@ -69,7 +71,7 @@ def get_selfnote(user_id, note_name): def get_all_selfnotes(user_id): if not SELF_NOTES.get(user_id): SELF_NOTES[user_id] = {} - return [] + return None allnotes = list(SELF_NOTES[user_id]) allnotes.sort() return allnotes @@ -111,7 +113,5 @@ def __load_allnotes(): SELF_NOTES[x.user_id] = {} SELF_NOTES[x.user_id][x.name] = {'value': x.value, 'type': x.msgtype, 'file': x.file} -def count_notes(): - return SESSION.query(SelfNotes).count() __load_allnotes() diff --git a/nana/modules/database/pm_db.py b/nana/modules/database/pm_db.py index c9e5ff5e..f171d0e7 100644 --- a/nana/modules/database/pm_db.py +++ b/nana/modules/database/pm_db.py @@ -13,8 +13,9 @@ class WhitelistUsers(BASE): __tablename__ = "pmapprove" user_id = Column(String(14), primary_key=True) username = Column(String(15)) - + def __init__(self, user_id, username): + """initializing db""" self.user_id = user_id self.username = username @@ -24,6 +25,7 @@ class ReqUsers(BASE): username = Column(String(15)) def __init__(self, user_id, username): + """getting query from db for user and name""" self.user_id = user_id self.username = username diff --git a/nana/modules/devs.py b/nana/modules/devs.py index 4ac519a9..13945f9c 100644 --- a/nana/modules/devs.py +++ b/nana/modules/devs.py @@ -4,14 +4,12 @@ import subprocess import sys import traceback -from platform import python_version +from io import StringIO -import pyrogram as p import requests from pyrogram import filters -from speedtest import Speedtest -from nana import Command, logging, app, DB_AVAILABLE, USERBOT_VERSION, ASSISTANT_VERSION +from nana import Command, app, edrep, AdminSettings from nana.helpers.aiohttp_helper import AioHttp from nana.helpers.deldog import deldog from nana.helpers.parser import mention_markdown @@ -21,15 +19,11 @@ This command means for helping development ──「 **Execution** 」── --> `exec (command)` -Execute a python commands. - -──「 **Evaluation** 」── -> `eval (command)` -Do math evaluation. +Python Shell Execution ──「 **Command shell** 」── --> `cmd (command)` +-> `sh (command)` Execute command shell ──「 **Take log** 」── @@ -40,10 +34,6 @@ -> `dc` Get user specific data center -──「 **Get Repo Nana-Bot** 」── --> `repo` -Get Repo For this userbot - ──「 **Test Your Server Internet Speed** 」── -> `speedtest` Obtain Server internet speed using speedtest @@ -52,14 +42,17 @@ -> `id` Send id of what you replied to +──「 **Self Destruct Reveal** 」── +-> `reveal` or `reveal self` +Reveal Self Destruct photo untouched, 'self' tag will reveal it in Saved Messages """ async def stk(chat, photo): if "http" in photo: r = requests.get(photo, stream=True) - with open("nana/cache/stiker.png", "wb") as stk: - shutil.copyfileobj(r.raw, stk) + with open("nana/cache/stiker.png", "wb") as stikr: + shutil.copyfileobj(r.raw, stikr) await app.send_sticker(chat, "nana/cache/stiker.png") os.remove("nana/cache/stiker.png") else: @@ -74,43 +67,104 @@ async def pic(chat, photo, caption=None): await app.send_photo(chat, photo, caption) -async def aexec(client, message, code): - # Make an async function with the code and `exec` it +async def aexec(code, client, message): exec( - 'async def __ex(client, message): ' + + f'async def __aexec(client, message): ' + ''.join(f'\n {l}' for l in code.split('\n')) ) + return await locals()['__aexec'](client, message) + - # Get `__ex` from local variables, call it and return the result - return await locals()['__ex'](client, message) +@app.on_message(filters.me & filters.command("reveal", Command)) +async def sd_reveal(client, message): + cmd = message.command + self_tag = " ".join(cmd[1:]) + tags = "self" in self_tag + if len(message.text.split()) == 1: + await message.delete() + return + if tags: + await message.delete() + a = 'nana/file.png' + await client.download_media(message.reply_to_message.photo, file_name=a) + await client.send_photo('me', a) + os.remove(a) + else: + await message.delete() + a = 'nana/file.png' + await client.download_media(message.reply_to_message.photo, file_name=a) + await client.send_photo(message.chat.id, a) + os.remove(a) -@app.on_message(filters.me & filters.command(["py"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("eval", Command)) async def executor(client, message): - if len(message.text.split()) == 1: - await message.edit("Usage: `py message.edit('edited!')`") + try: + cmd = message.text.split(" ", maxsplit=1)[1] + except IndexError: + await message.delete() return - args = message.text.split(None, 1) - code = args[1] + reply_to_id = message.message_id + if message.reply_to_message: + reply_to_id = message.reply_to_message.message_id + old_stderr = sys.stderr + old_stdout = sys.stdout + redirected_output = sys.stdout = StringIO() + redirected_error = sys.stderr = StringIO() + stdout, stderr, exc = None, None, None try: - await aexec(client, message, code) - except: - exc_type, exc_obj, exc_tb = sys.exc_info() - errors = traceback.format_exception(etype=exc_type, value=exc_obj, tb=exc_tb) - await message.edit("**Execute**\n`{}`\n\n**Failed:**\n```{}```".format(code, "".join(errors))) - logging.exception("Execution error") + await aexec(cmd, client, message) + except Exception: + exc = traceback.format_exc() + stdout = redirected_output.getvalue() + stderr = redirected_error.getvalue() + sys.stdout = old_stdout + sys.stderr = old_stderr + evaluation = "" + if exc: + evaluation = exc + elif stderr: + evaluation = stderr + elif stdout: + evaluation = stdout + else: + evaluation = "Success" + final_output = f"QUERY:\n{cmd}\n\nOUTPUT:\n{evaluation.strip()}" + if len(final_output) > 4096: + filename = 'output.txt' + with open(filename, "w+", encoding="utf8") as out_file: + out_file.write(str(evaluation.strip())) + await message.reply_document( + document=filename, + caption=cmd, + disable_notification=True, + reply_to_message_id=reply_to_id + ) + os.remove(filename) + await message.delete() + else: + await edrep(message, text=final_output) -@app.on_message(filters.me & filters.command(["ip"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("ip", Command)) async def public_ip(_client, message): - ip = await AioHttp().get_text("https://api.ipify.org") - await message.edit(f'{ip}', parse_mode='html') + j = await AioHttp().get_json("http://ip-api.com/json") + stats = f"**ISP {j['isp']}:**\n" + stats += f"**AS:** `{j['as']}`\n" + stats += f"**IP Address:** `{j['query']}`\n" + stats += f"**Country:** `{j['country']}`\n" + stats += f"**Zip code:** `{j['zip']}`\n" + stats += f"**Lattitude:** `{j['lat']}`\n" + stats += f"**Longitude:** `{j['lon']}`\n" + stats += f"**Time Zone:** `{j['timezone']}`" + await edrep(message, text=stats, parse_mode='markdown') + -@app.on_message(filters.me & filters.command(["sh"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("sh", Command)) async def terminal(client, message): if len(message.text.split()) == 1: - await message.edit("Usage: `sh ping -c 5 google.com`") + await edrep(message, text="Usage: `sh ping -c 5 google.com`") return args = message.text.split(None, 1) teks = args[1] @@ -126,7 +180,8 @@ async def terminal(client, message): stderr=subprocess.PIPE ) except Exception as err: - await message.edit(""" + print(err) + await edrep(message, text=""" **Input:** ```{}``` @@ -149,7 +204,7 @@ async def terminal(client, message): except Exception as err: exc_type, exc_obj, exc_tb = sys.exc_info() errors = traceback.format_exception(etype=exc_type, value=exc_obj, tb=exc_tb) - await message.edit("""**Input:**\n```{}```\n\n**Error:**\n```{}```""".format(teks, "".join(errors))) + await edrep(message, text="""**Input:**\n```{}```\n\n**Error:**\n```{}```""".format(teks, "".join(errors))) return output = process.stdout.read()[:-1].decode("utf-8") if str(output) == "\n": @@ -163,20 +218,20 @@ async def terminal(client, message): caption="`Output file`") os.remove("nana/cache/output.txt") return - await message.edit("""**Input:**\n```{}```\n\n**Output:**\n```{}```""".format(teks, output)) + await edrep(message, text="""**Input:**\n```{}```\n\n**Output:**\n```{}```""".format(teks, output)) else: - await message.edit("**Input: **\n`{}`\n\n**Output: **\n`No Output`".format(teks)) + await edrep(message, text="**Input: **\n`{}`\n\n**Output: **\n`No Output`".format(teks)) -@app.on_message(filters.me & filters.command(["log"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command(["log"], Command)) async def log(_client, message): f = open("nana/logs/error.log", "r") data = await deldog(message, f.read()) - await message.edit("`Your recent logs stored here : `{}".format(data)) + await edrep(message, text=f"`Your recent logs stored here : `{data}", disable_web_page_preview=True) -@app.on_message(filters.me & filters.command(["dc"], Command)) -async def dc_id(_client, message): +@app.on_message(filters.user(AdminSettings) & filters.command("dc", Command)) +async def dc_id_check(_client, message): user = message.from_user if message.reply_to_message: if message.reply_to_message.forward_from: @@ -202,98 +257,82 @@ async def dc_id(_client, message): text = "{}'s assigned datacenter is **DC5**, located in **SIN, Singapore, SG**".format(user) else: text = "{}'s assigned datacenter is **Unknown**".format(user) - await message.edit(text) + await edrep(message, text=text) - -@app.on_message(filters.me & filters.command(["alive"], Command)) -async def alive(_client, message): - try: - me = await app.get_me() - except ConnectionError: - me = None - text = "[Nana-Bot](https://github.com/legenhand/Nana-Bot)** Up and Running:**\n" - if not me: - text += "- Userbot: `Stopped (v{})`\n".format(USERBOT_VERSION) - else: - text += "- Userbot: `Running (v{})`\n".format(USERBOT_VERSION) - text += "- Assistant: `Running (v{})`\n".format(ASSISTANT_VERSION) - text += "- Database: `{}`\n".format(DB_AVAILABLE) - text += "- Python: `{}`\n".format(python_version()) - text += "- Pyrogram: `{}`\n".format(p.__version__) - await message.edit(text, disable_web_page_preview=True) - -@app.on_message(filters.me & filters.command(["id"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("id", Command)) async def get_id(_client, message): file_id = None user_id = None - if message.reply_to_message: rep = message.reply_to_message if rep.audio: - file_id = rep.audio.file_id + file_id = f"**File ID**: `{rep.audio.file_id}`\n" + file_id += f"**File Ref**: `{rep.audio.file_ref}`\n" + file_id += "**File Type**: `audio`\n" elif rep.document: - file_id = rep.document.file_id + file_id = f"**File ID**: `{rep.document.file_id}`\n" + file_id += f"**File Ref**: `{rep.document.file_ref}`\n" + file_id += f"**File Type**: `{rep.document.mime_type}`\n" elif rep.photo: - file_id = rep.photo.file_id + file_id = f"**File ID**: `{rep.photo.file_id}`\n" + file_id += f"**File Ref**: `{rep.photo.file_ref}`\n" + file_id += "**File Type**: `photo`" elif rep.sticker: - file_id = rep.sticker.file_id + file_id = f"**Sicker ID**: `{rep.sticker.file_id}`\n" + if rep.sticker.set_name and rep.sticker.emoji: + file_id += f"**Sticker Set**: `{rep.sticker.set_name}`\n" + file_id += f"**Sticker Emoji**: `{rep.sticker.emoji}`\n" + if rep.sticker.is_animated: + file_id += f"**Animated Sticker**: `{rep.sticker.is_animated}`\n" + else: + file_id += "**Animated Sticker**: `False`\n" + else: + file_id += "**Sticker Set**: __None__\n" + file_id += "**Sticker Emoji**: __None__" elif rep.video: - file_id = rep.video.file_id + file_id = f"**File ID**: `{rep.video.file_id}`\n" + file_id += f"**File Ref**: `{rep.video.file_ref}`\n" + file_id += "**File Type**: `video`" elif rep.animation: - file_id = rep.animation.file_id + file_id = f"**File ID**: `{rep.animation.file_id}`\n" + file_id += f"**File Ref**: `{rep.animation.file_ref}`\n" + file_id += "**File Type**: `GIF`" elif rep.voice: - file_id = rep.voice.file_id + file_id = f"**File ID**: `{rep.voice.file_id}`\n" + file_id += f"**File Ref**: `{rep.voice.file_ref}`\n" + file_id += "**File Type**: `Voice Note`" elif rep.video_note: - file_id = rep.video_note.file_id - elif rep.contact: - file_id = rep.contact.file_id + file_id = f"**File ID**: `{rep.animation.file_id}`\n" + file_id += f"**File Ref**: `{rep.animation.file_ref}`\n" + file_id += "**File Type**: `Video Note`" elif rep.location: - file_id = rep.location.file_id + file_id = "**Location**:\n" + file_id += f"**longitude**: `{rep.location.longitude}`\n" + file_id += f"**latitude**: `{rep.location.latitude}`" elif rep.venue: - file_id = rep.venue.file_id + file_id = "**Location**:\n" + file_id += f"**longitude**: `{rep.venue.location.longitude}`\n" + file_id += f"**latitude**: `{rep.venue.location.latitude}`\n\n" + file_id += "**Address**:\n" + file_id += f"**title**: `{rep.venue.title}`\n" + file_id += f"**detailed**: `{rep.venue.address}`\n\n" elif rep.from_user: user_id = rep.from_user.id - if user_id: - await message.edit(user_id) + if rep.forward_from: + user_detail = f"**Forwarded User ID**: `{message.reply_to_message.forward_from.id}`\n" + else: + user_detail = f"**User ID**: `{message.reply_to_message.from_user.id}`\n" + user_detail += f"**Message ID**: `{message.reply_to_message.message_id}`" + await edrep(message, text=user_detail) elif file_id: - await message.edit(file_id) + if rep.forward_from: + user_detail = f"**Forwarded User ID**: `{message.reply_to_message.forward_from.id}`\n" + else: + user_detail = f"**User ID**: `{message.reply_to_message.from_user.id}`\n" + user_detail += f"**Message ID**: `{message.reply_to_message.message_id}`\n\n" + user_detail += file_id + await edrep(message, text=user_detail) else: - await message.edit("This chat's ID:\n`{}`".format(message.chat.id)) - - -@app.on_message(filters.me & filters.command(["speedtest"], Command)) -async def speedtest(_client, message): - await message.edit("`Running speed test . . .`") - test = Speedtest() - test.get_best_server() - test.download() - test.upload() - test.results.share() - result = test.results.dict() - await message.edit("`" - "Started at " - f"{result['timestamp']} \n\n" - "Download " - f"{speed_convert(result['download'])} \n" - "Upload " - f"{speed_convert(result['upload'])} \n" - "Ping " - f"{result['ping']} \n" - "ISP " - f"{result['client']['isp']}" - "`") - - -def speed_convert(size): - """ - Hi human, you can't read bytes? - """ - power = 2 ** 10 - zero = 0 - units = {0: '', 1: 'Kb/s', 2: 'Mb/s', 3: 'Gb/s', 4: 'Tb/s'} - while size > power: - size /= power - zero += 1 - return f"{round(size, 2)} {units[zero]}" + await edrep(message, text=f"**Chat ID**: `{message.chat.id}`") diff --git a/nana/modules/dictionary.py b/nana/modules/dictionary.py index 8b23d15c..c16d9bfd 100644 --- a/nana/modules/dictionary.py +++ b/nana/modules/dictionary.py @@ -2,19 +2,19 @@ from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep from nana.helpers.aiohttp_helper import AioHttp __HELP__ = """ ──「 **Dictionary** 」── --> `dic` or `dictionary` +-> `dic` Search dictionary for given words """ __MODULE__ = "Dictionary" -@app.on_message(filters.me & filters.command(["dic", "dictionary"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("dic", Command)) async def dictionary(_client, message): cmd = message.command input_ = "" @@ -23,7 +23,7 @@ async def dictionary(_client, message): elif message.reply_to_message and len(cmd) == 1: input_ = message.reply_to_message.text elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`Can't pass to the void.`") + await edrep(message, text="`Can't pass to the void.`") await asyncio.sleep(2) await message.delete() return @@ -90,7 +90,8 @@ def out_print(word1): return out if not input_: - await message.edit("`Plz enter word to search‼️`") + await edrep(message, text="`query not found`") + return else: word = input_ r_dec = await AioHttp().get_json(f"https://api.dictionaryapi.dev/api/v1/entries/en/{word}") @@ -101,6 +102,6 @@ def out_print(word1): v_word = r_dec['word'] last_output = out_print(r_dec) if last_output: - await message.edit("`Search reasult for `" + f" {v_word}\n\n" + last_output) + await edrep(message, text="`Search reasult for `" + f" {v_word}\n\n" + last_output) else: - await message.edit('`No result found from the database.`') \ No newline at end of file + await edrep(message, text='`No result found from the database.`') \ No newline at end of file diff --git a/nana/modules/downloads.py b/nana/modules/downloads.py index ab33c5f2..ee10e34b 100644 --- a/nana/modules/downloads.py +++ b/nana/modules/downloads.py @@ -13,7 +13,7 @@ from pyDownload import Downloader from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep __MODULE__ = "Downloads" __HELP__ = """ @@ -47,13 +47,10 @@ """ -@app.on_message(filters.me & filters.command(["ls"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("ls", Command)) async def ls(_client, message): args = message.text.split(None, 1) - if len(args) == 2: - basepath = "nana/{}".format(args[1]) - else: - basepath = "nana/" + basepath = "nana/{}".format(args[1]) if len(args) == 2 else "nana/" directory = "" listfile = "" for entry in os.listdir(basepath): @@ -62,14 +59,14 @@ async def ls(_client, message): for entry in os.listdir(basepath): if os.path.isfile(os.path.join(basepath, entry)): listfile += "\n{}".format(entry) - await message.edit("**List directory :**`{}`\n**List file :**`{}`".format(directory, listfile)) + await edrep(message, text="**List directory :**`{}`\n**List file :**`{}`".format(directory, listfile)) -@app.on_message(filters.me & filters.command(["upload"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("upload", Command)) async def upload_file(client, message): args = message.text.split(None, 1) if len(args) == 1: - await message.edit("usage : upload (path)") + await edrep(message, text="usage : upload (path)") return path = "nana/{}".format(args[1]) try: @@ -78,9 +75,9 @@ async def upload_file(client, message): except Exception as e: logging.error("Exception occured", exc_info=True) logging.error(e) - await message.edit("`File not found!`") + await edrep(message, text="`File not found!`") return - await message.edit("`Success!`") + await edrep(message, text="`Success!`") await asyncio.sleep(5) await client.delete_messages(message.chat.id, message.message_id) @@ -138,10 +135,10 @@ async def download_url(url, file_name): return downlaoded -@app.on_message(filters.me & filters.command(["dl"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("dl", Command)) async def download_from_url(_client, message): if len(message.text.split()) == 1: - await message.edit("Usage: `dl `") + await edrep(message, text="Usage: `dl `") return if len(message.text.split()) == 2: url = message.text.split(None, 1)[1] @@ -150,44 +147,44 @@ async def download_from_url(_client, message): url = message.text.split(None, 2)[1] file_name = message.text.split(None, 2)[2] else: - await message.edit("Invaild args given!") + await edrep(message, text="Invaild args given!") return try: os.listdir("nana/downloads/") except FileNotFoundError: - await message.edit("Invalid download path in config!") + await edrep(message, text="Invalid download path in config!") return - await message.edit("Downloading...") + await edrep(message, text="Downloading...") download = await download_url(url, file_name) - await message.edit(download) + await edrep(message, text=download) -@app.on_message(filters.me & filters.command(["download"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("download", Command)) async def dssownload_from_telegram(client, message): if message.reply_to_message: await download_file_from_tg(client, message) else: - await message.edit("Reply document to download it") + await edrep(message, text="Reply document to download it") -@app.on_message(filters.me & filters.command(["direct"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("direct", Command)) async def direct_link_generator(_client, message): args = message.text.split(None, 1) - await message.edit("`Processing...`") + await edrep(message, text="`Processing...`") if len(args) == 1: - await message.edit("Write any args here!") + await edrep(message, text="Write any args here!") return downloadurl = args[1] reply = '' links = re.findall(r'\bhttps?://.*\.\S+', downloadurl) if not links: reply = "`No links found!`" - await message.edit(reply) + await edrep(message, text=reply) for link in links: if 'drive.google.com' in link: reply += gdrive(link) elif 'zippyshare.com' in link: - reply += zippy_share(link) + reply += 'Zippy Share disabled of security reasons' elif 'yadi.sk' in link: reply += yandex_disk(link) elif 'mediafire.com' in link: @@ -203,11 +200,11 @@ async def direct_link_generator(_client, message): else: reply += re.findall(r"\bhttps?://(.*?[^/]+)", link)[0] + 'is not supported' - await message.edit(reply) + await edrep(message, text=reply) def gdrive(url: str) -> str: - """ GDrive direct links generator """ + """GDrive direct links generator""" drive = 'https://drive.google.com' try: link = re.findall(r'\bhttps?://drive\.google\.com\S+', url)[0] @@ -249,38 +246,8 @@ def gdrive(url: str) -> str: return reply -def zippy_share(url: str) -> str: - """ ZippyShare direct links generator - Based on https://github.com/LameLemon/ziggy""" - reply = '' - dl_url = '' - try: - link = re.findall(r'\bhttps?://.*zippyshare\.com\S+', url)[0] - except IndexError: - reply = "`No ZippyShare links found`\n" - return reply - session = requests.Session() - base_url = re.search('http.+.com', link).group() - response = session.get(link) - page_soup = BeautifulSoup(response.content, "lxml") - scripts = page_soup.find_all("script", {"type": "text/javascript"}) - for script in scripts: - if "getElementById('dlbutton')" in script.text: - url_raw = re.search(r'= (?P\".+\" \+ (?P\(.+\)) .+);', - script.text).group('url') - mathh = re.search(r'= (?P\".+\" \+ (?P\(.+\)) .+);', - script.text).group('math') - dl_url = url_raw.replace(mathh, '"' + str(eval(mathh)) + '"') - break - dl_url = base_url + eval(dl_url) - name = urllib.parse.unquote(dl_url.split('/')[-1]) - reply += f'[{name}]({dl_url})\n' - return reply - - def yandex_disk(url: str) -> str: - """ Yandex.Disk direct links generator - Based on https://github.com/wldhx/yadisk-direct""" + """Yandex.Disk direct links generator""" reply = '' try: link = re.findall(r'\bhttps?://.*yadi\.sk\S+', url)[0] @@ -299,7 +266,7 @@ def yandex_disk(url: str) -> str: def mediafire(url: str) -> str: - """ MediaFire direct links generator """ + """MediaFire direct links generator""" try: link = re.findall(r'\bhttps?://.*mediafire\.com\S+', url)[0] except IndexError: @@ -316,7 +283,7 @@ def mediafire(url: str) -> str: def sourceforge(url: str) -> str: - """ SourceForge direct links generator """ + """SourceForge direct links generator""" try: link = re.findall(r'\bhttps?://.*sourceforge\.net\S+', url)[0] except IndexError: @@ -337,7 +304,7 @@ def sourceforge(url: str) -> str: def osdn(url: str) -> str: - """ OSDN direct links generator """ + """OSDN direct links generator""" osdn_link = 'https://osdn.net' try: link = re.findall(r'\bhttps?://.*osdn\.net\S+', url)[0] @@ -359,7 +326,7 @@ def osdn(url: str) -> str: def github(url: str) -> str: - """ GitHub direct links generator """ + """GitHub direct links generator""" try: link = re.findall(r'\bhttps?://.*github\.com.*releases\S+', url)[0] except IndexError: @@ -378,7 +345,7 @@ def github(url: str) -> str: def androidfilehost(url: str) -> str: - """ AFH direct links generator """ + """AFH direct links generator""" try: link = re.findall(r'\bhttps?://.*androidfilehost.*fid.*\S+', url)[0] except IndexError: @@ -429,9 +396,7 @@ def androidfilehost(url: str) -> str: def useragent(): - """ - useragent random setter - """ + """useragent random setter""" useragents = BeautifulSoup( requests.get( 'https://developers.whatismybrowser.com/' @@ -459,7 +424,7 @@ async def progressdl(current, total, event, start, type_of_ps, file_name=None): "{0} of {1}\nETA: {2}".format( humanbytes(current), humanbytes(total), - time_formatter(estimated_total_time) + await time_formatter(estimated_total_time) ) if file_name: await event.edit("{}\nFile Name: `{}`\n{}".format( @@ -469,8 +434,7 @@ async def progressdl(current, total, event, start, type_of_ps, file_name=None): def humanbytes(size): - """Input size in bytes, - outputs in a human readable format""" + """Input size in bytes""" # https://stackoverflow.com/a/49361727/4723940 if not size: return "" @@ -484,9 +448,8 @@ def humanbytes(size): return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B" -def time_formatter(milliseconds: int) -> str: - """Inputs time in milliseconds, to get beautified time, - as string""" +async def time_formatter(milliseconds: int) -> str: + """Inputs time in milliseconds""" seconds, milliseconds = divmod(int(milliseconds), 1000) minutes, seconds = divmod(seconds, 60) hours, minutes = divmod(minutes, 60) @@ -516,7 +479,7 @@ async def download_reply_nocall(client, message): nama = "{}".format(message.reply_to_message.audio.file_name) await client.download_media(message.reply_to_message.audio, file_name="nana/downloads/" + nama) elif message.reply_to_message.voice: - nama = "audio_{}.ogg".format(message.reply_to_message.voice) + nama = "audio_{}.ogg".format(message.reply_to_message.voice.date) await client.download_media(message.reply_to_message.voice, file_name="nana/downloads/" + nama) elif message.reply_to_message.document: nama = "{}".format(message.reply_to_message.document.file_name) @@ -527,7 +490,6 @@ async def download_reply_nocall(client, message): async def download_file_from_tg(client, message): - await message.edit("__Downloading...__") start = int(time.time()) c_time = time.time() name = await name_file(client, message) @@ -560,12 +522,12 @@ async def download_file_from_tg(client, message): progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) else: - await message.edit("Unknown file!") + await edrep(message, text="Unknown file!") return end = int(time.time()) times = await time_parser(start, end) text = f"**⬇ Downloaded!**\n🗂 File name: `{name}`\n🏷 Saved to: `nana/downloads/`\n⏲ Downloaded in: {times}" - await message.edit(text) + await edrep(message, text=text) async def name_file(_client, message): @@ -588,5 +550,5 @@ async def name_file(_client, message): elif message.reply_to_message.document: return "{}".format(message.reply_to_message.document.file_name) else: - await message.edit("Unknown file!") + await edrep(message, text="Unknown file!") return diff --git a/nana/modules/github.py b/nana/modules/github.py index b946a128..3136c1b7 100644 --- a/nana/modules/github.py +++ b/nana/modules/github.py @@ -1,30 +1,40 @@ +import asyncio +import os +from asyncio import sleep +from glob import iglob +from random import randint + +import aiofiles import aiohttp from pyrogram import filters +from reportlab.graphics import renderPM +from svglib.svglib import svg2rlg -from nana import app, Command +from nana import app, Command, AdminSettings, edrep +from nana.helpers.PyroHelpers import ReplyCheck +from nana.helpers.aiohttp_helper import AioHttp __MODULE__ = "Github" __HELP__ = """ This module can help you find information about a github user! -──「 **Github Acc Info** 」── +──「 **Github User Info** 」── -> `git (username)` Finding information about a github user. """ -@app.on_message(filters.me & filters.command(["git"], Command)) -async def github(_client, message): +@app.on_message(filters.user(AdminSettings) & filters.command("git", Command)) +async def github(client, message): if len(message.text.split()) == 1: - await message.edit("Usage: `git (username)`") + await edrep(message, text="Usage: `git (username)`") return username = message.text.split(None, 1)[1] URL = f"https://api.github.com/users/{username}" async with aiohttp.ClientSession() as session: async with session.get(URL) as request: if request.status == 404: - return await message.edit("`" + username + - " not found`") + return await edrep(message, text="`" + username + " not found`") result = await request.json() @@ -35,23 +45,33 @@ async def github(_client, message): created_at = result.get("created_at", "Not Found") REPLY = ( - f"**GitHub Info for `{username}**`" - f"\n**Username:** `{name}`\n**Bio:** `{bio}`\n**URL:** {url}" + f"**GitHub Info for {name}**" + f"\n**Username:** `{username}`\n**Bio:** `{bio}`\n**Profile Link:** [Link]({url})" f"\n**Company:** `{company}`\n**Created at:** `{created_at}`" + f"\n**Repository:** [Link](https://github.com/{username}?tab=repositories)" ) + url = f"https://ghchart.rshah.org/{username}" + file_name = f"{randint(1, 999)}{username}" + resp = await AioHttp.get_raw(url) + f = await aiofiles.open(f"{file_name}.svg", mode='wb') + await f.write(resp) + await f.close() - if not result.get("repos_url", None): - return await message.edit(REPLY) - async with session.get(result.get("repos_url", None)) as request: - result = request.json - if request.status == 404: - return await message.edit(REPLY) - - result = await request.json() - - REPLY += "\n**Repos:**\n" - - for nr in range(len(result)): - REPLY += f"[{result[nr].get('name', None)}]({result[nr].get('html_url', None)})\n" - - await message.edit(REPLY) \ No newline at end of file + try: + drawing = svg2rlg(f"{file_name}.svg") + renderPM.drawToFile(drawing, f"{file_name}.png") + except UnboundLocalError: + await edrep(message, text="Username does not exist!") + await sleep(2) + await message.delete() + return + await asyncio.gather( + client.send_photo( + chat_id=message.chat.id, + photo=f"{file_name}.png", + caption=REPLY, + reply_to_message_id=ReplyCheck(message) + ) + ) + for file in iglob(f"{file_name}.*"): + os.remove(file) \ No newline at end of file diff --git a/nana/modules/googledrive.py b/nana/modules/googledrive.py index a9264cde..93ed1082 100644 --- a/nana/modules/googledrive.py +++ b/nana/modules/googledrive.py @@ -7,12 +7,12 @@ from pydrive.drive import GoogleDrive from pyrogram import filters -from nana import app, setbot, Command, gauth, gdrive_credentials, HEROKU_API +from nana import app, setbot, Command, gauth, gdrive_credentials, HEROKU_API, AdminSettings, edrep from nana.helpers.parser import cleanhtml from nana.modules.downloads import download_url from .downloads import progressdl -__MODULE__ = "Google Drive" +__MODULE__ = "GDrive" __HELP__ = """ Google Drive stuff, for login just type /gdrive in Assistant bot @@ -62,34 +62,32 @@ async def get_driveid(driveid): async def get_driveinfo(driveid): getdrivename = BeautifulSoup( requests.get('https://drive.google.com/file/d/{}/view'.format(driveid), allow_redirects=False).content) - filename = cleanhtml(str(getdrivename.find('title'))).split(" - ")[0] - return filename + return cleanhtml(str(getdrivename.find('title'))).split(" - ")[0] -@app.on_message(filters.me & filters.command(["credentials"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("credentials", Command)) async def credentials(_client, message): args = message.text.split(None, 1) if len(args) == 1: - await message.edit("Write any args here!") + await edrep(message, text="Write any args here!") return if len(args) == 2: file = open("client_secrets.json", "w") file.write(args[1]) file.close() - await message.edit("credentials success saved on client_secrets") + await edrep(message, text="credentials success saved on client_secrets") return -@app.on_message(filters.me & filters.command(["gdrive"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("gdrive", Command)) async def gdrive_stuff(client, message): gauth.LoadCredentialsFile("nana/session/drive") if gauth.credentials is None: - if HEROKU_API: - if gdrive_credentials: - file = open("client_secrets.json", "w") - file.write(gdrive_credentials) - file.close() - await message.edit( + if HEROKU_API and gdrive_credentials: + file = open("client_secrets.json", "w") + file.write(gdrive_credentials) + file.close() + await edrep(message, text= "You are not logged in to your google drive account!\nYour assistant bot may help you to login google " "drive, check your assistant bot for more information!") gdriveclient = os.path.isfile("client_secrets.json") @@ -107,7 +105,8 @@ async def gdrive_stuff(client, message): else: try: gauth.GetAuthUrl() - except: + except Exception as e: + print(e) await setbot.send_message(message.from_user.id, "Wrong Credentials! Check var ENV gdrive_credentials on heroku or do " ".credentials (your credentials) for change your Credentials") @@ -130,94 +129,109 @@ async def gdrive_stuff(client, message): drive_dir = await get_drivedir(drive) if len(message.text.split()) == 3 and message.text.split()[1] == "download": - await message.edit("Downloading...") + await edrep(message, text="Downloading...") driveid = await get_driveid(message.text.split()[2]) if not driveid: - await message.edit( + await edrep(message, text= "Invaild URL!\nIf you think this is bug, please go to your Assistant bot and type `/reportbug`") return filename = await get_driveinfo(driveid) if not filename: - await message.edit( + await edrep(message, text= "Invaild URL!\nIf you think this is bug, please go to your Assistant bot and type `/reportbug`") return - await message.edit("Downloading for `{}`\nPlease wait...".format(filename.replace(' ', '_'))) + await edrep(message, text="Downloading for `{}`\nPlease wait...".format(filename.replace(' ', '_'))) download = drive.CreateFile({'id': driveid}) download.GetContentFile(filename) try: os.rename(filename, "nana/downloads/" + filename.replace(' ', '_')) except FileExistsError: os.rename(filename, "nana/downloads/" + filename.replace(' ', '_') + ".2") - await message.edit("Downloaded!\nFile saved to `{}`".format("nana/downloads/" + filename.replace(' ', '_'))) + await edrep(message, text="Downloaded!\nFile saved to `{}`".format("nana/downloads/" + filename.replace(' ', '_'))) elif len(message.text.split()) == 3 and message.text.split()[1] == "upload": filerealname = message.text.split()[2].split(None, 1)[0] filename = "nana/downloads/{}".format(filerealname.replace(' ', '_')) checkfile = os.path.isfile(filename) if not checkfile: - await message.edit("File `{}` was not found!".format(filerealname)) + await edrep(message, text="File `{}` was not found!".format(filerealname)) return - await message.edit("Uploading `{}`...".format(filerealname)) + await edrep(message, text="Uploading `{}`...".format(filerealname)) upload = drive.CreateFile({"parents": [{"kind": "drive#fileLink", "id": drive_dir}], 'title': filerealname}) upload.SetContentFile(filename) upload.Upload() upload.InsertPermission({'type': 'anyone', 'value': 'anyone', 'role': 'reader'}) - await message.edit( + await edrep(message, text= "Uploaded!\nDownload link: [{}]({})\nDirect download link: [{}]({})".format(filerealname, upload[ 'alternateLink'], filerealname, upload['downloadUrl'])) elif len(message.text.split()) == 3 and message.text.split()[1] == "mirror": - message.edit("Mirroring...") + await edrep(message, text="Mirroring...") driveid = await get_driveid(message.text.split()[2]) if not driveid: - await message.edit( - "Invaild URL!\nIf you think this is bug, please go to your Assistant bot and type `/reportbug`") + await edrep(message, text="Invaild URL!\nIf you think this is bug, please go to your Assistant bot and type `/reportbug`") return filename = await get_driveinfo(driveid) if not filename: - await message.edit( - "Invaild URL!\nIf you think this is bug, please go to your Assistant bot and type `/reportbug`") + await edrep(message, text="Invaild URL!\nIf you think this is bug, please go to your Assistant bot and type `/reportbug`") return mirror = drive.auth.service.files().copy(fileId=driveid, body={"parents": [{"kind": "drive#fileLink", "id": drive_dir}], 'title': filename}).execute() new_permission = {'type': 'anyone', 'value': 'anyone', 'role': 'reader'} drive.auth.service.permissions().insert(fileId=mirror['id'], body=new_permission).execute() - await message.edit( - "Done!\nDownload link: [{}]({})\nDirect download link: [{}]({})".format(filename, mirror['alternateLink'], + await edrep(message, text="Done!\nDownload link: [{}]({})\nDirect download link: [{}]({})".format(filename, mirror['alternateLink'], filename, mirror['downloadUrl'])) elif len(message.text.split()) == 2 and message.text.split()[1] == "tgmirror": if message.reply_to_message: - await message.edit("__Downloading...__") + await edrep(message, text="__Downloading...__") c_time = time.time() if message.reply_to_message.photo: - nama = "photo_{}.png".format(message.reply_to_message.photo.date) + if not message.reply_to_message.caption: + nama = f"photo_{message.reply_to_message.photo.date}.png" + else: + nama = f'{message.reply_to_message.caption}.png'.replace(' ', '_') await client.download_media(message.reply_to_message.photo, file_name="nana/downloads/" + nama, progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) elif message.reply_to_message.animation: - nama = "giphy_{}-{}.gif".format(message.reply_to_message.animation.date, - message.reply_to_message.animation.file_size) + if not message.reply_to_message.caption: + nama = "giphy_{}-{}.gif".format(message.reply_to_message.animation.date, + message.reply_to_message.animation.file_size) + else: + nama = f'{message.reply_to_message.caption}.gif'.replace(' ', '_') await client.download_media(message.reply_to_message.animation, file_name="nana/downloads/" + nama, progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) elif message.reply_to_message.video: - nama = "video_{}-{}.mp4".format(message.reply_to_message.video.date, - message.reply_to_message.video.file_size) + if not message.reply_to_message.caption: + nama = "video_{}-{}.mp4".format(message.reply_to_message.video.date, + message.reply_to_message.video.file_size) + else: + nama = f'{message.reply_to_message.caption}.mp4'.replace(' ', '_').replace('.mkv', '') await client.download_media(message.reply_to_message.video, file_name="nana/downloads/" + nama, progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) elif message.reply_to_message.sticker: - nama = "sticker_{}_{}.webp".format(message.reply_to_message.sticker.date, - message.reply_to_message.sticker.set_name) + if not message.reply_to_message.caption: + nama = "sticker_{}_{}.webp".format(message.reply_to_message.sticker.date, + message.reply_to_message.sticker.set_name) + else: + nama = f'{message.reply_to_message.caption}.webp'.replace(' ', '_') await client.download_media(message.reply_to_message.sticker, file_name="nana/downloads/" + nama, progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) elif message.reply_to_message.audio: - nama = "audio_{}.mp3".format(message.reply_to_message.audio.date) + if not message.reply_to_message.caption: + nama = "audio_{}.mp3".format(message.reply_to_message.audio.date) + else: + nama = f'{message.reply_to_message.caption}.mp3'.replace(' ', '_') await client.download_media(message.reply_to_message.audio, file_name="nana/downloads/" + nama, progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) elif message.reply_to_message.voice: - nama = "audio_{}.ogg".format(message.reply_to_message.voice.date) + if not message.reply_to_message.caption: + nama = "audio_{}.ogg".format(message.reply_to_message.voice.date) + else: + nama = f'{message.reply_to_message.caption}.ogg'.replace(' ', '_') await client.download_media(message.reply_to_message.voice, file_name="nana/downloads/" + nama, progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) @@ -227,36 +241,36 @@ async def gdrive_stuff(client, message): progress=lambda d, t: asyncio.get_event_loop().create_task( progressdl(d, t, message, c_time, "Downloading..."))) else: - await message.edit("Unknown file!") + await edrep(message, text="Unknown file!") return upload = drive.CreateFile({"parents": [{"kind": "drive#fileLink", "id": drive_dir}], 'title': nama}) upload.SetContentFile("nana/downloads/" + nama) upload.Upload() upload.InsertPermission({'type': 'anyone', 'value': 'anyone', 'role': 'reader'}) - await message.edit( + await edrep(message, text= "Done!\nDownload link: [{}]({})\nDirect download link: [{}]({})".format(nama, upload['alternateLink'], nama, upload['downloadUrl'])) os.remove("nana/downloads/" + nama) else: - await message.edit("Reply document to mirror it to gdrive") + await edrep(message, text="Reply document to mirror it to gdrive") elif len(message.text.split()) == 3 and message.text.split()[1] == "urlmirror": - await message.edit("Downloading...") + await edrep(message, text="Downloading...") URL = message.text.split()[2] nama = URL.split("/")[-1] time_dl = await download_url(URL, nama) if "Downloaded" not in time_dl: - await message.edit("Failed to download file, invaild url!") + await edrep(message, text="Failed to download file, invaild url!") return - await message.edit(f"Downloaded with {time_dl}.\nNow uploading...") + await edrep(message, text=f"Downloaded with {time_dl}.\nNow uploading...") upload = drive.CreateFile({"parents": [{"kind": "drive#fileLink", "id": drive_dir}], 'title': nama}) upload.SetContentFile("nana/downloads/" + nama) upload.Upload() upload.InsertPermission({'type': 'anyone', 'value': 'anyone', 'role': 'reader'}) - await message.edit( + await edrep(message, text= "Done!\nDownload link: [{}]({})\nDirect download link: [{}]({})".format(nama, upload['alternateLink'], nama, upload['downloadUrl'])) os.remove("nana/downloads/" + nama) else: - await message.edit( + await edrep(message, text= "Usage:\n-> `gdrive download `\n-> `gdrive upload `\n-> `gdrive mirror `\n\nFor " "more information about this, go to your assistant.") diff --git a/nana/modules/info.py b/nana/modules/info.py new file mode 100644 index 00000000..15fa7662 --- /dev/null +++ b/nana/modules/info.py @@ -0,0 +1,119 @@ +from datetime import datetime +from time import sleep + +import spamwatch +from pyrogram import filters +from pyrogram.errors import PeerIdInvalid +from pyrogram.raw import functions +from pyrogram.types import User + +from nana import app, Command, sw_api, AdminSettings, edrep + +__MODULE__ = "Whois" +__HELP__ = """ +──「 **Whois** 」── +-> `info` `@username` or `user_id` +-> `info` "reply to a text" +To find information about a person. + +""" + + + + +def LastOnline(user: User): + if user.is_bot: + return "" + elif user.status == 'recently': + return "Recently" + elif user.status == 'within_week': + return "Within the last week" + elif user.status == 'within_month': + return "Within the last month" + elif user.status == 'long_time_ago': + return "A long time ago :(" + elif user.status == 'online': + return "Currently Online" + elif user.status == 'offline': + return datetime.fromtimestamp(user.status.date).strftime("%a, %d %b %Y, %H:%M:%S") + + +async def GetCommon(client, get_user): + common = await client.send( + functions.messages.GetCommonChats( + user_id=await client.resolve_peer(get_user), + max_id=0, + limit=0)) + return common + + +def ProfilePicUpdate(user_pic): + return datetime.fromtimestamp(user_pic[0].date).strftime("%d.%m.%Y, %H:%M:%S") + + +@app.on_message(filters.user(AdminSettings) & filters.command("info", Command)) +async def whois(client, message): + cmd = message.command + if not message.reply_to_message and len(cmd) == 1: + get_user = message.from_user.id + elif len(cmd) == 1: + if message.reply_to_message.forward_from: + get_user = message.reply_to_message.forward_from.id + else: + get_user = message.reply_to_message.from_user.id + elif len(cmd) > 1: + get_user = cmd[1] + try: + get_user = int(cmd[1]) + except ValueError: + pass + try: + user = await client.get_users(get_user) + except PeerIdInvalid: + await edrep(message, text="I don't know that User.") + sleep(2) + await message.delete() + return + desc = await client.get_chat(get_user) + desc = desc.description + common = await GetCommon(client, user.id) + + if user: + if sw_api: + sw = spamwatch.Client(sw_api) + status = sw.get_ban(user.id) + if status == False: + await edrep(message, text=f""" +**About [{user.first_name} {user.last_name if user.last_name else ''}](tg://user?id={user.id})**: + - **UserID**: `{user.id}` + - **Username**: {'@'+user.username if user.username else ''} + - **Last Online**: `{LastOnline(user)}` + - **Common Groups**: `{len(common.chats)}` + - **Contact**: `{user.is_contact}` +**SpamWatch Banned** : `False` + """, + disable_web_page_preview=True) + else: + await edrep(message, text=f""" +**About [{user.first_name} {user.last_name if user.last_name else ''}](tg://user?id={user.id})**: + - **UserID**: `{user.id}` + - **Username**: {'@'+user.username if user.username else ''} + - **Last Online**: `{LastOnline(user)}` + - **Common Groups**: `{len(common.chats)}` + - **Contact**: `{user.is_contact}` +**SpamWatch Banned** : `True` + • **Reason**: `{status.reason}` + • **Message**: `{status.message}` + """, + disable_web_page_preview=True) + return + else: + await edrep(message, text=f""" +**About [{user.first_name} {user.last_name if user.last_name else ''}](tg://user?id={user.id})**: + - **UserID**: `{user.id}` + - **Username**: {'@'+user.username if user.username else ''} + - **Last Online**: `{LastOnline(user)}` + - **Common Groups**: `{len(common.chats)}` + - **Contact**: `{user.is_contact}` + """, + disable_web_page_preview=True) \ No newline at end of file diff --git a/nana/modules/lastfm.py b/nana/modules/lastfm.py index 1fc8a6bc..3db77403 100644 --- a/nana/modules/lastfm.py +++ b/nana/modules/lastfm.py @@ -1,7 +1,7 @@ from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings from nana.helpers.PyroHelpers import ReplyCheck __HELP__ = """ @@ -15,7 +15,7 @@ __MODULE__ = "Last.FM" -@app.on_message(filters.me & filters.command(["lastfm", "lf"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command(["lastfm", "lf"], Command)) async def lastfm(client, message): x = await client.get_inline_bot_results("lastfmrobot", "") await message.delete() diff --git a/nana/modules/lookup.py b/nana/modules/lookup.py new file mode 100644 index 00000000..e33441a5 --- /dev/null +++ b/nana/modules/lookup.py @@ -0,0 +1,67 @@ +from asyncio import sleep +from datetime import datetime + +from pyrogram import filters +from pyrogram.errors import PeerIdInvalid + +from nana import app, Command, AdminSettings, edrep +from nana.helpers.aiohttp_helper import AioHttp + + +@app.on_message(filters.user(AdminSettings) & filters.command("lookup", Command)) +async def lookup(client, message): + cmd = message.command + if not message.reply_to_message and len(cmd) == 1: + get_user = message.from_user.id + elif len(cmd) == 1: + if message.reply_to_message.forward_from: + get_user = message.reply_to_message.forward_from.id + else: + get_user = message.reply_to_message.from_user.id + elif len(cmd) > 1: + get_user = cmd[1] + try: + get_user = int(cmd[1]) + except ValueError: + pass + try: + user = await client.get_chat(get_user) + except PeerIdInvalid: + await edrep(message, text="I don't know that User.") + sleep(2) + await message.delete() + return + url = f'https://api.intellivoid.net/spamprotection/v1/lookup?query={user.id}' + a = await AioHttp().get_json(url) + response = a['success'] + if response == True: + date = a["results"]["last_updated"] + stats = f'**◢ Intellivoid• SpamProtection Info**:\n' + stats += f' - **Updated on**: `{datetime.fromtimestamp(date).strftime("%Y-%m-%d %I:%M:%S %p")}`\n' + stats += f' - **Chat Info**: [Link](t.me/SpamProtectionBot/?start=00_{user.id})\n' + + if a["results"]["attributes"]["is_potential_spammer"] == True: + stats += f' - **User**: `USERxSPAM`\n' + elif a["results"]["attributes"]["is_operator"] == True: + stats += f' - **User**: `USERxOPERATOR`\n' + elif a["results"]["attributes"]["is_agent"] == True: + stats += f' - **User**: `USERxAGENT`\n' + elif a["results"]["attributes"]["is_whitelisted"] == True: + stats += f' - **User**: `USERxWHITELISTED`\n' + + stats += f' - **Type**: `{a["results"]["entity_type"]}`\n' + stats += f' - **Language**: `{a["results"]["language_prediction"]["language"]}`\n' + stats += f' - **Language Probability**: `{a["results"]["language_prediction"]["probability"]}`\n' + stats += f'**Spam Prediction**:\n' + stats += f' - **Ham Prediction**: `{a["results"]["spam_prediction"]["ham_prediction"]}`\n' + stats += f' - **Spam Prediction**: `{a["results"]["spam_prediction"]["spam_prediction"]}`\n' + stats += f'**Blacklisted**: `{a["results"]["attributes"]["is_blacklisted"]}`\n' + if a["results"]["attributes"]["is_blacklisted"] == True: + stats += f' - **Reason**: `{a["results"]["attributes"]["blacklist_reason"]}`\n' + stats += f' - **Flag**: `{a["results"]["attributes"]["blacklist_flag"]}`\n' + stats += f'**TELEGRAM HASH**:\n`{a["results"]["private_telegram_id"]}`\n' + await edrep(message, text=stats, disable_web_page_preview=True) + else: + await edrep(message, text='`cannot reach SpamProtection API`') + await sleep(3) + await message.delete() \ No newline at end of file diff --git a/nana/modules/lydia.py b/nana/modules/lydia.py index 4f54beb1..81e56bb1 100644 --- a/nana/modules/lydia.py +++ b/nana/modules/lydia.py @@ -1,59 +1,103 @@ import asyncio +from time import time from coffeehouse.api import API +from coffeehouse.exception import CoffeeHouseError as CFError from coffeehouse.lydia import LydiaAI from pyrogram import filters -from nana import lydia_api, app, Command -from nana.helpers.PyroHelpers import ReplyCheck - -lydia_status = False -coffeehouse_api = None -lydia = None -session = None +import nana.modules.database.lydia_db as sql +from nana import lydia_api, app, Command, setbot, Owner, OwnerUsername, AdminSettings, edrep __MODULE__ = "Chatbot" __HELP__ = """ An AI Powered Chat Bot Module ──「 **Chatbot** 」── --> `lydia` -Enables AI on replied user & Desables +-> `addchat` +Enables AI on chat + +-> `rmchat` +Removes AI on chat + Powered by CoffeeHouse API created by @Intellivoid. """ -@app.on_message(filters.me & filters.command(["lydia"], Command)) -async def lydia_private(_client, message): - global lydia_status, coffeehouse_api, lydia, session - if lydia_api == "": - await message.edit("`lydia API key is not set!\nSet your lydia API key by adding Config Vars in heroku with " - "name lydia_api with value your lydia key API`") - return - if lydia_status: - await message.edit("Turning off lydia...") - asyncio.sleep(0.5) - lydia_status = False - await message.edit("Lydia will not reply your message") +CoffeeHouseAPI = API(lydia_api) +api_client = LydiaAI(CoffeeHouseAPI) + + +@app.on_message(filters.user(AdminSettings) & filters.command("addchat", Command)) +async def add_chat(_client, message): + global api_client + chat_id = message.chat.id + is_chat = sql.is_chat(chat_id) + if not is_chat: + ses = api_client.create_session() + ses_id = str(ses.id) + expires = str(ses.expires) + sql.set_ses(chat_id, ses_id, expires) + await edrep(message, text="`AI successfully enabled for this chat!`") else: - await message.edit("Turning on lydia...") - try: - coffeehouse_api = API(lydia_api) - # Create Lydia instance - lydia = LydiaAI(coffeehouse_api) - # Create a new chat session (Like a conversation) - session = lydia.create_session() - except: - await message.edit("Wrong lydia API key!") - return - lydia_status = True - await message.edit("now Lydia will reply your message!") + await edrep(message, text="`AI is already enabled for this chat!`") + + await asyncio.sleep(5) + await message.delete() -@app.on_message(~filters.me & ~filters.edited & (filters.mentioned | filters.private), group=6) -async def lydia_reply(_client, message): - global lydia_status, session - if lydia_status: - output = session.think_thought(message.text) - await message.reply_text(f"`{output}`", quote=True, reply_to_message_id=ReplyCheck(message)) +@app.on_message(filters.user(AdminSettings) & filters.command("rmchat", Command)) +async def remove_chat(_client, message): + chat_id = message.chat.id + is_chat = sql.is_chat(chat_id) + if not is_chat: + await edrep(message, text="`AI isn't enabled here in the first place!`") else: + sql.rem_chat(chat_id) + await edrep(message, text="`AI disabled successfully!`") + + await asyncio.sleep(5) + await message.delete() + + +@app.on_message(~filters.user(AdminSettings) & ~filters.edited & (filters.group | filters.private), group=6) +async def chat_bot(client, message): + global api_client + chat_id = message.chat.id + is_chat = sql.is_chat(chat_id) + if not is_chat: return + if message.text and not message.document: + if not await check_message(client, message): + return + sesh, exp = sql.get_ses(chat_id) + query = message.text + try: + if int(exp) < time(): + ses = api_client.create_session() + ses_id = str(ses.id) + expires = str(ses.expires) + sql.set_ses(chat_id, ses_id, expires) + sesh, exp = sql.get_ses(chat_id) + except ValueError: + pass + try: + await client.send_chat_action(chat_id, action='typing') + rep = api_client.think_thought(sesh, query) + await asyncio.sleep(0.3) + await message.reply_text(rep) + except CFError as e: + await setbot.send_message( + Owner, f"Chatbot error: {e} occurred in {chat_id}!") + + +async def check_message(_client, message): + if message.chat.type == 'private': + return True + else: + if message.text.lower() == f"@{OwnerUsername}": + return True + if message.reply_to_message: + if message.reply_to_message.from_user.id == Owner: + return True + else: + return False diff --git a/nana/modules/mega.py b/nana/modules/mega.py index 4a32ae35..3d2bb4e1 100644 --- a/nana/modules/mega.py +++ b/nana/modules/mega.py @@ -3,9 +3,9 @@ from mega import Mega from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep -__MODULE__ = "Mega Downloader" +__MODULE__ = "Mega" __HELP__ = """ Download any file from URL or from telegram @@ -20,29 +20,29 @@ """ -@app.on_message(filters.me & filters.command(["mega"], Command)) -async def mega_download(_client, msg): - args = msg.text.split(None, 1) +@app.on_message(filters.user(AdminSettings) & filters.command("mega", Command)) +async def mega_download(_client, message): + args = message.text.split(None, 1) if len(args) == 1: - await msg.edit("usage: mega (url)") + await edrep(message, text="usage: mega (url)") return - await msg.edit("Processing...") + await edrep(message, text="Processing...") if not os.path.exists('nana/downloads/mega'): os.makedirs('nana/downloads/mega') m = Mega() - await m.download_url(message=msg, url=args[1], dest_path="nana/downloads/mega") - await msg.edit("Success! file was downloaded at nana/downloads") + await m.download_url(message=message, url=args[1], dest_path="nana/downloads/mega") + await edrep(message, text="Success! file was downloaded at nana/downloads") -@app.on_message(filters.me & filters.command(["megafile"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("megafile", Command)) async def mega_downloaded_file(_client, message): filelist = os.listdir("nana/downloads/mega") print(len(filelist)) if len(filelist) == 0: - await message.edit("You haven't download any files with mega! try to download something") + await edrep(message, text="You haven't download any files with mega! try to download something") return listoffile = "List of file you downloaded with mega: \n`" - for i in range(len(filelist)): - listoffile += filelist[i] + "\n" + for item in filelist: + listoffile += item + "\n" listoffile += "`" - await message.edit(listoffile) + await edrep(message, text=listoffile) diff --git a/nana/modules/mega_download.py b/nana/modules/mega_download.py index e06c17bd..a88f5e4a 100644 --- a/nana/modules/mega_download.py +++ b/nana/modules/mega_download.py @@ -13,18 +13,18 @@ from pySmartDL import SmartDL from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep from .downloads import humanbytes -async def subprocess_run(cmd, megadl): +async def subprocess_run(cmd, message): subproc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True, universal_newlines=True, executable="bash") talk = subproc.communicate() exit_code = subproc.returncode if exit_code != 0: - await megadl.edit( + await edrep(message, text= '```An error was detected while running the subprocess:\n' f'exit code: {exit_code}\n' f'stdout: {talk[0]}\n' @@ -33,30 +33,30 @@ async def subprocess_run(cmd, megadl): return talk -@app.on_message(filters.me & filters.command(["megadownload"], Command)) -async def mega_downloader(_client, megadl): - args = megadl.text.split(None, 1) - await megadl.edit("`Processing...`") - msg_link = await megadl.reply_to_message.text +@app.on_message(filters.user(AdminSettings) & filters.command("megadownload", Command)) +async def mega_downloader(_client, message): + args = message.text.split(None, 1) + await edrep(message, text="`Processing...`") + msg_link = await message.reply_to_message.text link = args[1] if link: pass elif msg_link: link = msg_link.text else: - await megadl.edit("Usage: `.mega `") + await edrep(message, text="Usage: `mega `") return try: link = re.findall(r'\bhttps?://.*mega.*\.nz\S+', link)[0] except IndexError: - await megadl.edit("`No MEGA.nz link found`\n") + await edrep(message, text="`No MEGA.nz link found`\n") return cmd = f'bin/megadown -q -m {link}' - result = await subprocess_run(cmd, megadl) + result = await subprocess_run(cmd, message) try: data = json.loads(result[0]) except json.JSONDecodeError: - await megadl.edit("`Error: Can't extract the link`\n") + await edrep(message, text="`Error: Can't extract the link`\n") return except TypeError: return @@ -74,7 +74,7 @@ async def mega_downloader(_client, megadl): try: downloader.start(blocking=False) except HTTPError as e: - await megadl.edit("`" + str(e) + "`") + await edrep(message, text="`" + str(e) + "`") return while not downloader.isFinished(): status = downloader.get_status().capitalize() @@ -94,34 +94,35 @@ async def mega_downloader(_client, megadl): f"\nETA: {estimated_total_time}" ) if status == "Downloading": - await megadl.edit(current_message) + await edrep(message, text=current_message) time.sleep(0.2) elif status == "Combining": if display_message != current_message: - await megadl.edit(current_message) + await edrep(message, text=current_message) display_message = current_message - except Exception: + except Exception as e: + print(e) pass if downloader.isSuccessful(): download_time = downloader.get_dl_time(human=True) if exists(temp_file_name): await decrypt_file( - file_name, temp_file_name, hex_key, hex_raw_key, megadl) - await megadl.edit(f"`{file_name}`\n\n" + file_name, temp_file_name, hex_key, hex_raw_key, message) + await edrep(message, text=f"`{file_name}`\n\n" "Successfully downloaded\n" f"Download took: {download_time}") else: - await megadl.edit("Failed to download, check heroku Log for details") + await edrep(message, text="Failed to download, check heroku Log for details") for e in downloader.get_errors(): - megadl.edit(str(e)) + await edrep(message, text=str(e)) return async def decrypt_file(file_name, temp_file_name, - hex_key, hex_raw_key, megadl): - await megadl.edit("Decrypting file...") + hex_key, hex_raw_key, message): + await edrep(message, text="Decrypting file...") cmd = ("cat '{}' | openssl enc -d -aes-128-ctr -K {} -iv {} > '{}'" .format(temp_file_name, hex_key, hex_raw_key, file_name)) - await subprocess_run(cmd, megadl) + await subprocess_run(cmd, message) os.remove(temp_file_name) return diff --git a/nana/modules/meme.py b/nana/modules/meme.py index 87a0c1f4..70c12ed1 100644 --- a/nana/modules/meme.py +++ b/nana/modules/meme.py @@ -2,15 +2,14 @@ import os import random import re -import shutil -from difflib import get_close_matches +import subprocess import aiohttp -import requests from pyrogram import filters +from pyrogram.raw import functions import nana.modules.meme_strings as meme_strings -from nana import app, Command +from nana import app, Command, AdminSettings, edrep from nana.helpers.PyroHelpers import ReplyCheck __MODULE__ = "Memes" @@ -19,68 +18,68 @@ ──「 **Stretch Text** 」── -> `str` -stretch text +__stretch text__ ──「 **Copy Pasta** 」── -> `cp` -add randoms emoji to his/her text. +__add randoms emoji to text.__ ──「 **Scam** 」── -> `scam ` -User decides time/action, bot decides the other. +__chat input action.__ -scame types: `'typing','upload_photo', 'record_video', 'upload_video', 'record_audio', 'upload_audio', 'upload_document', 'find_location','record_video_note', 'upload_video_note', 'choose_contact', 'playing'` +**scame types**: '`typing`', '`upload_photo`', '`record_video`', '`upload_video`', '`record_audio`', '`upload_audio`', '`upload_document`', '`find_location`', '`record_video_note`', '`upload_video_note`', '`playing`' ──「 **Mock text** 」── -> `mocktxt` -Mock someone with text. - -──「 **Meme generator** 」── --> `meme` -For get avaiable type, just send `meme`, just send `meme (type)`. -To leave it blank, set text to _ -Usage: -```meme (up text) -(down text)``` +__Mock someone with text.__ ──「 **Vaporwave/Aestethic** 」── -> `aes` -Convert your text to Vaporwave. +__Convert your text to Vaporwave.__ + +──「 **SPAM** 」── +-> `spam` (value) (word) +__spams a word with value given__ + +-> `spamstk` (value) +__Reply to a sticker to spam the sticker__ ──「 **Shrugs** 」── -> `shg` -Free Shrugs? Anyone?... +__Free Shrugs?..__ ──「 **Pat** 」── -> `pat` -pat gifs +__pat gifs__ + +——「 **the F sign** 」── +-> `f` +__press **f** to show some respect!__ -──「 **TypeWriter** 」── --> `type` -typing message +──「 **Fake Screenshot** 」── +-> `fakess` +__fake screenshot notification toasts__ """ async def mocking_text(text): teks = list(text) for i, ele in enumerate(teks): - if i % 2 != 0: - teks[i] = ele.upper() - else: - teks[i] = ele.lower() + teks[i] = ele.upper() if i % 2 != 0 else ele.lower() pesan = "" - for x in range(len(teks)): - pesan += teks[x] + for tek in teks: + pesan += tek return pesan -@app.on_message(filters.me & filters.command(["pat"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("pat", Command)) async def pat(client, message): - URL = "https://some-random-api.ml/animu/pat" async with aiohttp.ClientSession() as session: + URL = "https://some-random-api.ml/animu/pat" async with session.get(URL) as request: if request.status == 404: - return await message.edit("`no Pats for u :c") + return await edrep(message, text="**no Pats for u :c**") result = await request.json() url = result.get("link", None) await message.delete() @@ -89,7 +88,7 @@ async def pat(client, message): ) -@app.on_message(filters.me & filters.command(["scam"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("scam", Command)) async def scam(client, message): input_str = message.command if len(input_str) == 1: # Let bot decide action and time @@ -106,7 +105,7 @@ async def scam(client, message): scam_action = str(input_str[1]).lower() scam_time = int(input_str[2]) else: - await message.edit("`Invalid Syntax !!`") + await edrep(message, text="**Invalid Syntax!**") return try: if scam_time > 0: @@ -121,12 +120,12 @@ async def scam(client, message): return -@app.on_message(filters.me & filters.command(["shg"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("shg", Command)) async def shg(_client, message): - await message.edit(random.choice(meme_strings.shgs)) + await edrep(message, text=random.choice(meme_strings.shgs)) -@app.on_message(filters.me & filters.command(["spam"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("spam", Command)) async def spam(client, message): await message.delete() times = message.command[1] @@ -142,7 +141,32 @@ async def spam(client, message): await asyncio.sleep(0.20) -@app.on_message(filters.me & filters.command(["owo"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("spamstk", Command)) +async def spam_stick(client, message): + if not message.reply_to_message: + await edrep(message, text="**reply to a sticker with amount you want to spam**") + return + if not message.reply_to_message.sticker: + await edrep(message, text="**reply to a sticker with amount you want to spam**") + return + else: + times = message.command[1] + if message.chat.type in ['supergroup', 'group']: + for _ in range(int(times)): + await client.send_sticker(message.chat.id, + sticker=message.reply_to_message.sticker.file_id, + reply_to_message_id=ReplyCheck(message) + ) + await asyncio.sleep(0.20) + + if message.chat.type == "private": + for _ in range(int(times)): + await client.send_message(message.chat.id, + sticker=message.reply_to_message.sticker.file_id) + await asyncio.sleep(0.20) + + +@app.on_message(filters.user(AdminSettings) & filters.command("owo", Command)) async def owo(_client, message): cmd = message.command text = "" @@ -150,8 +174,8 @@ async def owo(_client, message): text = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: text = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`cant uwu the void.`") + elif len(cmd) == 1: + await edrep(message, text="**cant uwu the void.**") await asyncio.sleep(2) await message.delete() return @@ -169,10 +193,10 @@ async def owo(_client, message): reply_text = reply_text.replace("ove", "uv") reply_text = reply_text.replace("ove", "uv") reply_text += ' ' + random.choice(meme_strings.faces) - await message.edit(reply_text) + await edrep(message, text=reply_text) -@app.on_message(filters.me & filters.command(["f"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("f", Command)) async def pay_respecc(_client, message): cmd = message.command paytext = "" @@ -180,8 +204,8 @@ async def pay_respecc(_client, message): paytext = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: paytext = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`Press F to Pay Respecc`") + elif len(cmd) == 1: + await edrep(message, text="**Press F to Pay Respecc!**") await asyncio.sleep(2) await message.delete() return @@ -190,10 +214,10 @@ async def pay_respecc(_client, message): paytext * 6, paytext * 6, paytext * 2, paytext * 2, paytext * 2, paytext * 2, paytext * 2 ) - await message.edit(pay) + await edrep(message, text=pay) -@app.on_message(filters.me & filters.command(["str"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("str", Command)) async def stretch(_client, message): cmd = message.command stretch_text = "" @@ -201,98 +225,93 @@ async def stretch(_client, message): stretch_text = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: stretch_text = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`Giiiiiiiv sooooooomeeeeeee teeeeeeext!`") + elif len(cmd) == 1: + await edrep(message, text="`Giiiiiiiv sooooooomeeeeeee teeeeeeext!`") await asyncio.sleep(2) await message.delete() return count = random.randint(3, 10) reply_text = re.sub(r"([aeiouAEIOUaeiouAEIOUаеиоуюяыэё])", (r"\1" * count), stretch_text) - await message.edit(reply_text) + await edrep(message, text=reply_text) -@app.on_message(filters.me & filters.command(["cp"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("cp", Command)) async def haha_emojis(_client, message): - if message.reply_to_message.message_id: - teks = message.reply_to_message.text - reply_text = random.choice(meme_strings.emojis) - b_char = random.choice(teks).lower() - for c in teks: - if c == " ": - reply_text += random.choice(meme_strings.emojis) - elif c in meme_strings.emojis: - reply_text += c - reply_text += random.choice(meme_strings.emojis) - elif c.lower() == b_char: - reply_text += "🅱️" - else: - if bool(random.getrandbits(1)): - reply_text += c.upper() - else: - reply_text += c.lower() - reply_text += random.choice(meme_strings.emojis) - await message.edit(reply_text) - - -@app.on_message(filters.me & filters.command(["mocktxt"], Command)) + if not message.reply_to_message.message_id: + return + + teks = message.reply_to_message.text + reply_text = random.choice(meme_strings.emojis) + b_char = random.choice(teks).lower() + for c in teks: + if c == " ": + reply_text += random.choice(meme_strings.emojis) + elif c in meme_strings.emojis: + reply_text += c + reply_text += random.choice(meme_strings.emojis) + elif c.lower() == b_char: + reply_text += "🅱️" + else: + reply_text += c.upper() if bool(random.getrandbits(1)) else c.lower() + reply_text += random.choice(meme_strings.emojis) + await edrep(message, text=reply_text) + + +@app.on_message(filters.user(AdminSettings) & filters.command("mocktxt", Command)) async def mock_text(client, message): if message.reply_to_message: teks = message.reply_to_message.text if teks is None: teks = message.reply_to_message.caption - if teks is None: - return + if teks is None: + return pesan = await mocking_text(teks) await client.edit_message_text(message.chat.id, message.message_id, pesan) -@app.on_message(filters.me & filters.command(["type"], Command)) -async def typingmeme(_client, message): - teks = message.text[3:] - total = len(teks) - for loop in range(total): - try: - await message.edit(teks[:loop + 1]) - except: - pass - - -@app.on_message(filters.me & filters.command(["meme"], Command)) -async def meme_gen(client, message): - meme_types = requests.get( - "https://raw.githubusercontent.com/legenhand/Nana-Bot/master/nana/helpers/memes.json").json() - if len(message.text.split()) <= 2: - if len(message.text.split()) == 2: - closematch = get_close_matches(message.text.split(None, 1)[1], list(meme_types)) - text = "Search result:\n" - for x in closematch: - text += "\n`{}`\n-> **{}**\n-> [Example]({})\n".format(x, meme_types[x]['title'], - meme_types[x]['example']) - await message.edit(text) - else: - await message.edit("Avaiable type: `{}`".format("`, `".join(list(meme_types)))) - return - memetype = message.text.split(None, 2)[1] - if memetype not in list(meme_types): - await message.edit("Unknown type!") +@app.on_message(filters.user(AdminSettings) & filters.command("fakess", Command)) +async def fake_ss(client, message): + await asyncio.gather( + message.delete(), + client.send( + functions.messages.SendScreenshotNotification( + peer=await client.resolve_peer(message.chat.id), + reply_to_msg_id=0, + random_id=client.rnd_id(), + ) + ) + ) + + +@app.on_message(filters.user(AdminSettings) & filters.command("g", Command)) +async def glitch(client, message): + cmd = message.command + amount = "" + if len(cmd) > 1: + amount = " ".join(cmd[1:]) + elif len(cmd) == 1: + amount = '2' + profile_photo = "nana/downloads/pfp.jpg" + glitched_gif = "nana/downloads/glitched_pfp.gif" + replied = message.reply_to_message + if not replied: + await message.delete() return + user = await client.get_users(replied.from_user.id) + await client.download_media(user.photo.big_file_id, file_name=profile_photo) + subprocess.run( + ["glitch_this", + profile_photo, + f"{amount}", + "--gif"], + capture_output=True, + text=True + ) + await client.send_animation(message.chat.id, + glitched_gif, + reply_to_message_id=ReplyCheck(message) + ) await message.delete() - sptext = message.text.split(None, 2)[2].split("\n") - if len(sptext) == 1: - text1 = "_" - text2 = sptext[0] - else: - text1 = sptext[0] - text2 = sptext[1] - getimg = requests.get("https://memegen.link/{}/{}/{}.jpg?font=impact".format(memetype, text1, text2), stream=True) - if getimg.status_code == 200: - with open("nana/cache/meme.png", 'wb') as f: - getimg.raw.decode_content = True - shutil.copyfileobj(getimg.raw, f) - if message.reply_to_message: - await client.send_sticker(message.chat.id, "nana/cache/meme.png", - reply_to_message_id=message.reply_to_message.message_id) - else: - await client.send_sticker(message.chat.id, "nana/cache/meme.png", reply_to_message_id=message.message_id) - os.remove("nana/cache/meme.png") + os.remove(profile_photo) + os.remove(glitched_gif) \ No newline at end of file diff --git a/nana/modules/meme_strings.py b/nana/modules/meme_strings.py index fb4b4a49..be68dbe6 100644 --- a/nana/modules/meme_strings.py +++ b/nana/modules/meme_strings.py @@ -68,25 +68,24 @@ faces = [ '(・`ω´・)', - ';;w;;', + ';w;', 'owo', 'UwU', - '>w<', - '^w^', - r'\(^o\) (/o^)/', + '>w<', + '^w^', '( ^ _ ^)∠☆', '(ô_ô)', - '~:o', + '~:o', ';_;', - '(*^*)', - '(>_', - '*(^O^)*', + '(*^*)', + '*(>_<)*', + '*(^O^)*', '((+_+))' ] emojis = [ - "😂", - "😂", + "😂", + "😂", "👌", "✌️", "💞", @@ -100,9 +99,9 @@ "👏", "👐", "🍕", - "💥", + "💥", "🍴", - "💦", + "💦", "💦", "🍑", "🍆", diff --git a/nana/modules/mention.py b/nana/modules/mention.py index e7ad3b4e..662a94c1 100644 --- a/nana/modules/mention.py +++ b/nana/modules/mention.py @@ -3,7 +3,7 @@ from pyrogram import filters -from nana import Command, app +from nana import Command, app, AdminSettings, edrep __MODULE__ = "Mention" __HELP__ = """ @@ -25,39 +25,39 @@ ) -@app.on_message(filters.me & filters.command(["mention"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("mention", Command)) async def mention_user(client, message): if len(message.command) < 3: - await message.edit("Incorrect format\nExample: mention @pokurt CTO") + await edrep(message, text="Incorrect format\nExample: mention @pokurt CTO") await sleep(3) await message.delete() return try: user = await client.get_users(message.command[1]) except Exception: - await message.edit("User not found") + await edrep(message, text="User not found") await sleep(3) await message.delete() return _mention = mention(user.id, ' '.join(message.command[2:])) - await message.edit(_mention) + await edrep(message, text=_mention) -@app.on_message(filters.me & filters.command(["hmention"], Command)) +@app.on_message(filters.me & filters.command("hmention", Command)) async def hidden_mention(client, message): if len(message.command) < 3: - await message.edit("Incorrect format\nExample: hmention @pokurt") + await edrep(message, text="Incorrect format\nExample: hmention @pokurt") await sleep(3) await message.delete() return try: user = await client.get_users(message.command[1]) except Exception: - await message.edit("User not found") + await edrep(message, text="User not found") await sleep(3) await message.delete() return _hmention = hmention(user.id, ' '.join(message.command[2:])) - await message.edit(_hmention) \ No newline at end of file + await edrep(message, text=_hmention) \ No newline at end of file diff --git a/nana/modules/metrics.py b/nana/modules/metrics.py index 1f73c053..1c724c9c 100644 --- a/nana/modules/metrics.py +++ b/nana/modules/metrics.py @@ -2,46 +2,87 @@ # Go and Do a star on his repo: https://github.com/athphane/userbot import time +import timeago from pyrogram import filters +from pyrogram.utils import get_channel_id -from nana import Command, app +from nana import Command, app, AdminSettings, edrep __MODULE__ = "Metrics" __HELP__ = """ This module can help you do the wordcount in the last 1000 messages in a groupchat or private chat. ──「 **Word Count** 」── --> `wordcount` +-> `wordcount` or `wc` Finds the 25 most used words in the last 1000 messages in a chat. +──「 **Inactive message count** 」── +-> `msg` or `msg ` +Finds the inactive users with last message in a chat. + """ class Custom(dict): def __missing__(self, key): + """define missing value""" return 0 -@app.on_message(filters.me & filters.command(["wordcount"], Command)) +async def get_inactive(client, message): + cmd = message.command + start = time.time() + limit = int(" ".join(cmd[1:])) if len(cmd) > 1 else 0 + messages = [ + m + async for member in client.iter_chat_members( + message.chat.id, limit=limit, filter="recent" + ) + if not member.user.is_deleted + async for m in client.search_messages( + message.chat.id, limit=1, from_user=member.user.id + ) + ] + + delta = time.time() - start + messages.sort(key=lambda k: k["date"]) + + return "\n".join( + [ + "[{}](tg://user?id={}) last [message](https://t.me/c/{}/{}) was {}".format( + m.from_user.first_name, + m.from_user.id, + get_channel_id(m.chat.id), + m.message_id, + timeago.format(m.date), + ) + for m in messages + ] + + [f"`{int(delta * 1000)}ms`"] + ) + + +@app.on_message(filters.user(AdminSettings) & filters.command(["wordcount", "wc"], Command)) async def word_count(client, message): await message.delete() words = Custom() - progress = await client.send_message(message.chat.id, "`Processed 0 messages...`") - total = 0 - async for msg in client.iter_history(message.chat.id, 1000): - total += 1 - if total % 100 == 0: - await progress.edit_text(f"`Processed {total} messages...`") - time.sleep(0.5) - if msg.text: - for word in msg.text.split(): + progress = await client.send_message(message.chat.id, "`Processing 1000 messages...`") + async for ms_g in client.iter_history(message.chat.id, 1000): + if ms_g.text: + for word in ms_g.text.split(): words[word.lower()] += 1 - if msg.caption: - for word in msg.caption.split(): + if ms_g.caption: + for word in ms_g.caption.split(): words[word.lower()] += 1 freq = sorted(words, key=words.get, reverse=True) out = "Word Counter\n" for i in range(25): out += f"{i + 1}. **{words[freq[i]]}**: {freq[i]}\n" - await progress.edit_text(out) \ No newline at end of file + await progress.edit_text(out) + + +@app.on_message(filters.me & filters.command("msg", Command)) +async def inactive_msg(client, message): + text = await get_inactive(client, message) + await edrep(message, text=text) diff --git a/nana/modules/mkvn.py b/nana/modules/mkvn.py index 71653645..ae6800ff 100644 --- a/nana/modules/mkvn.py +++ b/nana/modules/mkvn.py @@ -7,7 +7,7 @@ from pyrogram import filters -from nana import setbot, app, Command, Owner +from nana import setbot, app, Command, Owner, AdminSettings, edrep from nana.helpers.PyroHelpers import ReplyCheck from nana.modules.downloads import download_reply_nocall @@ -19,23 +19,41 @@ Reply a video to make it as video note """ +error_message = ''' +Hello 🙂 +You need to install ffmpeg to make audio works better, here is guide how to install it: +**If you're using linux**, go to your terminal, type: +`sudo apt install ffmpeg` +**If you're using Windows**, download ffmpeg here: +`https://ffmpeg.zeranoe.com/builds/` +And then extract (if was archive), and place ffmpeg.exe to workdir (in current dir) +**If you're using heroku**, type this in your workdir: +`heroku buildpacks:add https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git` +Or if you not using heroku term, follow this guide: +1. Go to heroku.com +2. Go to your app in heroku +3. Change tabs/click Settings, then search for Buildpacks text +4. Click button Add build pack, then type `https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest` +5. Click Save changes, and you need to rebuild your heroku app to take changes! +''' -@app.on_message(filters.user("self") & filters.command(["mkvn"], Command)) + +@app.on_message(filters.user(AdminSettings) & filters.command("mkvn", Command)) async def vn_maker(client, message): if message.reply_to_message and message.reply_to_message.video: dlvid = await download_reply_nocall(client, message) if dlvid: - await message.edit("__Converting...__") + await edrep(message, text="__Converting...__") try: subprocess.Popen("ffmpeg", stdout=subprocess.PIPE, stderr=subprocess.PIPE) except Exception as err: if "The system cannot find the file specified" in str(err) or "No such file or directory" in str(err): - await message.edit("an error occured! check assistant for more details") + await edrep(message, text="an error occured! check assistant for more details") await sleep(5) await message.delete() await setbot.send_message( Owner, - "Hello 🙂\nYou need to install ffmpeg to make audio works better, here is guide how to install it:\n\n**If you're using linux**, go to your terminal, type:\n`sudo apt install ffmpeg`\n\n**If you're using Windows**, download ffmpeg here:\n`https://ffmpeg.zeranoe.com/builds/`\nAnd then extract (if was archive), and place ffmpeg.exe to workdir (in current dir)\n\n**If you're using heroku**, type this in your workdir:\n`heroku buildpacks:add https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git`\nOr if you not using heroku term, follow this guide:\n1. Go to heroku.com\n2. Go to your app in heroku\n3. Change tabs/click Settings, then search for Buildpacks text\n4. Click button Add build pack, then type `https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest`\n5. Click Save changes, and you need to rebuild your heroku app to take changes!" + error_message ) return os.system( diff --git a/nana/modules/music.py b/nana/modules/music.py index 5d9c8659..43238750 100644 --- a/nana/modules/music.py +++ b/nana/modules/music.py @@ -2,7 +2,7 @@ from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep __MODULE__ = "Deezer" __HELP__ = """ @@ -14,7 +14,7 @@ """ -@app.on_message(filters.me & filters.command(["music"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("music", Command)) async def send_music(client, message): try: cmd = message.command @@ -23,8 +23,8 @@ async def send_music(client, message): song_name = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: song_name = message.reply_to_message.text or message.reply_to_message.caption - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("Give a song name") + elif len(cmd) == 1: + await edrep(message, text="Give a song name") await asyncio.sleep(2) await message.delete() return @@ -52,12 +52,12 @@ async def send_music(client, message): # delete the message from Saved Messages await client.delete_messages("me", saved.message_id) except TimeoutError: - await message.edit("That didn't work out") + await edrep(message, text="That didn't work out") await asyncio.sleep(2) await message.delete() except Exception as e: print(e) - await message.edit("`Failed to find song`") + await edrep(message, text="`Failed to find song`") await asyncio.sleep(2) await message.delete() \ No newline at end of file diff --git a/nana/modules/nekobin.py b/nana/modules/nekobin.py index 24ffbf99..4cb0cd13 100644 --- a/nana/modules/nekobin.py +++ b/nana/modules/nekobin.py @@ -4,7 +4,7 @@ import aiohttp from pyrogram import filters -from nana import Command, app +from nana import Command, app, AdminSettings, edrep from nana.helpers.aiohttp_helper import AioHttp __MODULE__ = "Nekobin" @@ -16,12 +16,13 @@ """ -@app.on_message(filters.me & filters.command(["neko"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("neko", Command)) async def paste(client, message): if message.reply_to_message: text = message.reply_to_message.text if message.reply_to_message.document and message.reply_to_message.document.file_size < 2 ** 20 * 10: var = os.path.splitext(message.reply_to_message.document.file_name)[1] + print(var) path = await message.reply_to_message.download("nana/") with open(path, 'r') as doc: text = doc.read() @@ -41,13 +42,19 @@ async def paste(client, message): return else: url = f'https://nekobin.com/{key}' - reply_text = f'Nekofied to [Nekobin]({url})' + raw_url = f'https://nekobin.com/raw/{key}' + reply_text = '**Nekofied:**\n' + reply_text += f' - **Link**: {url}\n' + reply_text += f' - **Raw**: {raw_url}' delete = True if len(message.command) > 1 and \ message.command[1] in ['d', 'del'] and \ message.reply_to_message.from_user.is_self else False if delete: await asyncio.gather( - client.send_message(message.chat.id, reply_text, disable_web_page_preview=True), + client.send_message(message.chat.id, + reply_text, + disable_web_page_preview=True + ), message.reply_to_message.delete(), message.delete() ) @@ -58,14 +65,14 @@ async def paste(client, message): ) -@app.on_message(filters.me & filters.command(["gpaste"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command(["gpaste"], Command)) async def get_paste_(_client, message): - """ fetches the content of a dogbin or nekobin URL """ + """fetches the content of a dogbin or nekobin URL.""" link = message.reply_to_message.text if not link: - await message.edit("input not found!") + await edrep(message, text="input not found!") return - await message.edit("`Getting paste content...`") + await edrep(message, text="`Getting paste content...`") format_view = 'https://del.dog/v/' if link.startswith(format_view): link = link[len(format_view):] @@ -83,8 +90,7 @@ async def get_paste_(_client, message): link = link[len("nekobin.com/"):] raw_link = f'https://nekobin.com/raw/{link}' else: - await message.edit("Is that even a paste url?") + await edrep(message, text="Is that even a paste url?") return resp = await AioHttp().get_text(raw_link) - await message.edit( - f"**URL content** :\n`{resp}`") \ No newline at end of file + await edrep(message, text=f"**URL content** :\n`{resp}`") \ No newline at end of file diff --git a/nana/modules/notes.py b/nana/modules/notes.py index 992a6ba3..63d9319a 100644 --- a/nana/modules/notes.py +++ b/nana/modules/notes.py @@ -1,7 +1,7 @@ from pyrogram import filters, errors from pyrogram.types import InlineKeyboardMarkup -from nana import app, setbot, Command, Owner, BotUsername, DB_AVAILABLE +from nana import app, setbot, Command, Owner, BotUsername, DB_AVAILABLE, edrep from nana.helpers.PyroHelpers import ReplyCheck from nana.helpers.msg_types import Types, get_note_type from nana.helpers.string import parse_button, build_keyboard @@ -62,7 +62,7 @@ } -@app.on_message(filters.user(Owner) & filters.command(["save"], Command)) +@app.on_message(filters.user(Owner) & filters.command("save", Command)) async def save_note(_client, message): if not DB_AVAILABLE: await message.edit("Your database is not avaiable!") @@ -83,7 +83,7 @@ async def save_note(_client, message): await message.edit(f'Saved note `{note_name}`!') -@app.on_message(filters.user(Owner) & filters.command(["get"], Command)) +@app.on_message(filters.user(Owner) & filters.command("get", Command)) async def get_note(client, message): if not DB_AVAILABLE: await message.edit("Your database is not avaiable!") @@ -101,10 +101,7 @@ async def get_note(client, message): if getnotes['type'] == Types.TEXT: teks, button = parse_button(getnotes.get('value')) button = build_keyboard(button) - if button: - button = InlineKeyboardMarkup(button) - else: - button = None + button = InlineKeyboardMarkup(button) if button else None if button: try: inlineresult = await app.get_inline_bot_results(f"@{BotUsername}", f"note {note}") @@ -137,10 +134,7 @@ async def get_note(client, message): if getnotes.get('value'): teks, button = parse_button(getnotes.get('value')) button = build_keyboard(button) - if button: - button = InlineKeyboardMarkup(button) - else: - button = None + button = InlineKeyboardMarkup(button) if button else None else: teks = None button = None @@ -185,14 +179,14 @@ async def local_notes(_client, message): rply = "**Local notes:**\n" for x in getnotes: if len(rply) >= 1800: - await message.reply(rply) + await edrep(message, text=rply) rply = "**Local notes:**\n" rply += f"- `{x}`\n" await message.edit(rply) -@app.on_message(filters.user(Owner) & filters.command(["clear"], Command)) +@app.on_message(filters.user(Owner) & filters.command("clear", Command)) async def clear_note(_client, message): if not DB_AVAILABLE: await message.edit("Your database is not avaiable!") diff --git a/nana/modules/ocr.py b/nana/modules/ocr.py new file mode 100644 index 00000000..14fa0e54 --- /dev/null +++ b/nana/modules/ocr.py @@ -0,0 +1,75 @@ +import os + +import requests +from pyrogram import filters + +from nana import app, Command, AdminSettings, edrep + +__MODULE__ = "OCR" +__HELP__ = """ +Read Texts from photos and Stickers + +──「 **OCR** 」── +-> `ocr (lang)` +Read texts from an image or photo. + +""" + + +OCR_SPACE_API_KEY = '30dd97e2b588957' +async def ocr_space_file(filename,overlay=False,api_key=OCR_SPACE_API_KEY,language='eng'): + payload = { + 'isOverlayRequired': overlay, + 'apikey': api_key, + 'language': language, + } + with open(filename, 'rb') as f: + r = requests.post( + 'https://api.ocr.space/parse/image', + files={filename: f}, + data=payload, + ) + return r.json() + + +@app.on_message(filters.user(AdminSettings) & filters.command("ocr", Command)) +async def ocr(client, message): + cmd = message.command + lang_code = '' + if len(cmd) > 1: + lang_code = " ".join(cmd[1:]) + elif len(cmd) == 1: + lang_code = 'eng' + replied = message.reply_to_message + if not replied: + await message.delete() + return + if replied.video: + await message.delete() + return + if replied.document: + await message.delete() + return + if replied.voice: + await message.delete() + return + if replied.audio: + await message.delete() + return + if replied.photo: + reply_p = replied.photo + elif replied.sticker: + reply_p = replied.sticker + downloaded_file_name = await client.download_media(reply_p, 'nana/cache/file.png') + test_file = await ocr_space_file(filename=downloaded_file_name,language=lang_code) + try: + ParsedText = test_file["ParsedResults"][0]["ParsedText"] + except BaseException as e: + await edrep(message, text=e) + else: + if ParsedText == 'ParsedResults': + await message.delete() + return + else: + await edrep(message, text=f"`{ParsedText}`") + os.remove(downloaded_file_name) \ No newline at end of file diff --git a/nana/modules/pm.py b/nana/modules/pm.py index 8bc33cc9..b4639499 100644 --- a/nana/modules/pm.py +++ b/nana/modules/pm.py @@ -9,49 +9,50 @@ if DB_AVAILABLE: from nana.modules.database.pm_db import set_whitelist, get_whitelist, set_req, get_req, del_whitelist -welc_txt = f"""Hello, I'm {OwnerName}'s Userbot. -Try contacting me by pressing buttons down bellow""" +welc_txt = f""" +Hello, I'm {OwnerName}'s Userbot. +Try contacting me by pressing buttons down below +""" + NOTIFY_ID = Owner BLACKLIST = ["hack", "fuck", "bitch", "pubg", "sex"] -USER_IN_RESTRICT = [] - @app.on_message(~filters.me & filters.private & ~filters.bot) async def pm_block(client, message): - if PM_PERMIT: - if not get_whitelist(message.chat.id): - await client.read_history(message.chat.id) - if message.text: - for x in message.text.lower().split(): - if x in BLACKLIST: - await message.reply( - "Naah im blocking you and reporting you to TAbuse,\nwith that being said fuck you OwO") - await client.block_user(message.chat.id) - return - if not get_req(message.chat.id): - x = await client.get_inline_bot_results(BotUsername, "engine_pm") - await client.send_inline_bot_result(message.chat.id, query_id=x.query_id, - result_id=x.results[0].id, hide_via=True) - else: - x = await client.get_inline_bot_results(BotUsername, "engine_pm") - await client.send_inline_bot_result(message.chat.id, query_id=x.query_id, - result_id=x.results[0].id, hide_via=True) - else: + if not PM_PERMIT: return + if not get_whitelist(message.chat.id): + await client.read_history(message.chat.id) + if message.text: + for x in message.text.lower().split(): + if x in BLACKLIST: + await client.send_sticker(message.chat.id, + sticker='CAADAgAD1QQAAp7kTAry1JrL3zVXSxYE' + ) + await message.reply("Naah im blocking you and reporting you to SpamWatch,\nwith that being said fuck you too OwO") + await client.block_user(message.chat.id) + return + if not get_req(message.chat.id): + x = await client.get_inline_bot_results(BotUsername, "engine_pm") + else: + x = await client.get_inline_bot_results(BotUsername, "engine_pm") + await client.send_inline_bot_result(message.chat.id, query_id=x.query_id, + result_id=x.results[0].id, hide_via=True + ) -@app.on_message(filters.me & filters.command(["approve"], Command) & filters.private) +@app.on_message(filters.me & filters.command("approve", Command) & filters.private) async def approve_pm(_client, message): set_whitelist(message.chat.id, True) - await message.edit("`PM permission was approved!`") + await message.edit("**PM permission was approved!**") @app.on_message(filters.me & filters.command(["revoke", "disapprove"], Command) & filters.private) async def revoke_pm_block(_client, message): del_whitelist(message.chat.id) - await message.edit("`PM permission was revoked!`") + await message.edit("**PM permission was revoked!**") def pm_button_callback(_, __, query): @@ -59,57 +60,47 @@ def pm_button_callback(_, __, query): return True -pm_button_create = filters.create(pm_button_callback) +pm_filter = filters.create(pm_button_callback) -@setbot.on_callback_query(pm_button_create) +@setbot.on_callback_query(pm_filter) async def pm_button(client, query): - if PM_PERMIT: - if query.from_user.id in AdminSettings and not re.match(r"engine_pm_apr", query.data) and not re.match( - r"engine_pm_blk", query.data): - await client.answer_callback_query(query.id, "No, you can't click by yourself", show_alert=False) - return - if re.match(r"engine_pm_block", query.data): - await setbot.edit_inline_text(query.inline_message_id, "💩") - await app.send_message(query.from_user.id, "Opps, no nudes for you") - await app.block_user(query.from_user.id) - elif re.match(r"engine_pm_nope", query.data): - await setbot.edit_inline_text(query.inline_message_id, "👍") - await app.send_message(query.from_user.id, - "Hello, please wait for a reply from my master, thank you") - buttons = InlineKeyboardMarkup([[InlineKeyboardButton("Approve", - callback_data=f"engine_pm_apr-{query.from_user.id}"), - InlineKeyboardButton("Block", - callback_data=f"engine_pm_blk-{query.from_user.id}")]]) - pm_bot_mention = mention_markdown(query.from_user.id, query.from_user.first_name) - pm_bot_message = f"[{OwnerName}](tg://user?id={Owner}), {pm_bot_mention} want to contact you~" - await setbot.send_message(NOTIFY_ID, - pm_bot_message, - reply_markup=buttons) - set_req(query.from_user.id, True) - from nana.modules.lydia import lydia_status - if lydia_status: - await app.send_message(query.from_user.id, - "During the wait for permission from my master, why do not we have a little chat?") - elif re.match("engine_pm_report", query.data): - await setbot.edit_inline_text(query.inline_message_id, "👍") - await app.send_message(query.from_user.id, - "Hello, if you want to report any bugs, please vist in @NanaBotSupport") - elif re.match("engine_pm_none", query.data): - await setbot.edit_inline_text(query.inline_message_id, "👍") - await app.send_message(query.from_user.id, - "Alright then,\nIf you want anything from me, please contact my again. Thank you") - elif re.match("engine_pm_apr", query.data): - target = query.data.split("-")[1] - await query.message.edit_text(f"[Approved for PM]({target})") - await app.send_message(target, "Hello, this is Nana, my master approved you to PM.") - set_whitelist(int(target), True) - elif re.match(r"engine_pm_blk", query.data): - target = query.data.split("-")[1] - await query.message.edit_text("That user was blocked~") - await app.send_message(target, "Hello, this is Nana, my master has decide to block you.\nSorry for this!") - await app.block_user(target) - else: - await setbot.edit_inline_text(query.inline_message_id, "🙆‍") + print(query) + if not PM_PERMIT: + return + if query.from_user.id in AdminSettings and not re.match("engine_pm_apr", query.data) and not re.match("engine_pm_blk", query.data): + await client.answer_callback_query(query.id, "No, you can't click by yourself", show_alert=False) + return + if re.match("engine_pm_block", query.data): + await app.send_sticker(query.from_user.id, sticker='CAADAgAD1QQAAp7kTAry1JrL3zVXSxYE') + await setbot.edit_inline_text(query.from_user.id, "Sorry, No cash.\nAlso you are getting reported to **SpamWatch**, OwO") + await app.block_user(query.from_user.id) + elif re.match("engine_pm_nope", query.data): + await setbot.edit_inline_text(query.inline_message_id, "👍") + await app.send_message(query.from_user.id, "Hello, please wait for a reply from my master, thank you") + buttons = InlineKeyboardMarkup([[InlineKeyboardButton("Approve", + callback_data=f"engine_pm_apr-{query.from_user.id}"), + InlineKeyboardButton("Block", + callback_data=f"engine_pm_blk-{query.from_user.id}")]]) + pm_bot_mention = mention_markdown(query.from_user.id, query.from_user.first_name) + pm_bot_message = f"[{OwnerName}](tg://user?id={Owner}), {pm_bot_mention} want to contact you~" + await setbot.send_message(NOTIFY_ID, pm_bot_message,reply_markup=buttons) + set_req(query.from_user.id, True) + elif re.match("engine_pm_report", query.data): + await setbot.edit_inline_text(query.inline_message_id, "👍") + await app.send_message(query.from_user.id, "Hello, if you want to report any bugs, please vist in @NanaBotSupport") + elif re.match("engine_pm_none", query.data): + await setbot.edit_inline_text(query.inline_message_id, "👍") + await app.send_message(query.from_user.id, "Alright then,\nIf you want anything from me, please contact my again. Thank you") + elif re.match("engine_pm_apr", query.data): + target = query.data.split("-")[1] + await query.message.edit_text(f"[Approved for PM]({target})") + await app.send_message(target, "Hello, this is **Nana**, my master approved you to PM.") + set_whitelist(int(target), True) + elif re.match(r"engine_pm_blk", query.data): + target = query.data.split("-")[1] + await query.message.edit_text("That user was blocked ~") + await app.send_message(target, "Hello, this is **Nana**, my master has decide to block you.\nSorry for this!") + await app.block_user(target) else: - return \ No newline at end of file + await setbot.edit_inline_text(query.inline_message_id, "🙆‍") diff --git a/nana/modules/purge.py b/nana/modules/purge.py index 4b279a6a..9eb58d9e 100644 --- a/nana/modules/purge.py +++ b/nana/modules/purge.py @@ -4,7 +4,7 @@ from pyrogram import filters -from nana import Owner, app, Command +from nana import Owner, app, Command, AdminSettings, edrep from nana.helpers.admincheck import admin_check __MODULE__ = "Purges" @@ -34,7 +34,7 @@ """ -@app.on_message(filters.me & filters.command(["purge"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("purge", Command)) async def purge_message(client, message): if message.chat.type in (("supergroup", "channel")): is_admin = await admin_check(message) @@ -58,7 +58,7 @@ async def purge_message(client, message): ) count_del_etion_s += len(message_ids) message_ids = [] - if len(message_ids) > 0: + if message_ids: await client.delete_messages( chat_id=message.chat.id, message_ids=message_ids, @@ -67,20 +67,20 @@ async def purge_message(client, message): count_del_etion_s += len(message_ids) end_t = datetime.now() time_taken_ms = (end_t - start_t).seconds - msg = await client.send_message( + ms_g = await client.send_message( message.chat.id, f"Purged {count_del_etion_s} messages in {time_taken_ms} seconds" ) await asyncio.sleep(5) - await msg.delete() + await ms_g.delete() -@app.on_message(filters.me & filters.command(["purgeme"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("purgeme", Command)) async def purge_myself(client, message): if len(message.text.split()) >= 2 and message.text.split()[1].isdigit(): target = int(message.text.split()[1]) else: - await message.edit("Give me a number for a range!") + await edrep(message, text="Give me a number for a range!") get_msg = await client.get_history(message.chat.id) listall = [] counter = 0 @@ -95,7 +95,7 @@ async def purge_myself(client, message): semua = listall jarak = 0 jarak2 = 0 - for x in range(math.ceil(len(listall) / 100)): + for x in range(math.ceil(len(semua) / 100)): if total >= 101: jarak2 += 100 await client.delete_messages(message.chat.id, message_ids=semua[jarak:jarak2]) @@ -110,7 +110,7 @@ async def purge_myself(client, message): await client.delete_messages(message.chat.id, message_ids=listall) -@app.on_message(filters.me & filters.command(["del"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("del", Command)) async def delete_replied(client, message): msg_ids = [message.message_id] if message.reply_to_message: diff --git a/nana/modules/quotly.py b/nana/modules/quotly.py index 7684c889..a08bef85 100644 --- a/nana/modules/quotly.py +++ b/nana/modules/quotly.py @@ -1,9 +1,8 @@ -import random from asyncio import sleep from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep __MODULE__ = "Quotly" __HELP__ = """ @@ -11,33 +10,31 @@ ──「 **Make Quote From Message** 」── -> `q` -Reply To Message Text To Create Quote Sticker +__Reply To Message Text To Create Quote Sticker.__ """ -@app.on_message(filters.me & filters.command(["q"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("q", Command)) async def q_maker(_client, message): if not message.reply_to_message: - await message.edit("Reply to any users text message") + await edrep(message, text="**Reply to any users text message**") return - await message.edit("```Making a Quote```") await message.reply_to_message.forward("@QuotLyBot") is_sticker = False - progress = 0 while not is_sticker: try: - msg = await app.get_history("@QuotLyBot", 1) - check = msg[0]["sticker"]["file_id"] + ms_g = await app.get_history("@QuotLyBot", 1) + check = ms_g[0]["sticker"]["file_id"] + print(check) is_sticker = True - except: + except Exception as e: + print(e) await sleep(0.5) - progress += random.randint(0, 10) try: - await message.edit("```Making a Quote```\nProcessing {}%".format(progress)) - except: - await message.edit("ERROR") - await message.edit("```Complete !```") - msg_id = msg[0]["message_id"] + print('Making a Quote') + except Exception as e: + print(e) + msg_id = ms_g[0]["message_id"] await message.delete() - await app.forward_messages(message.chat.id, "@QuotLyBot", msg_id) \ No newline at end of file + await app.forward_messages(message.chat.id, "@QuotLyBot", msg_id, as_copy=True) diff --git a/nana/modules/reverse.py b/nana/modules/reverse.py index 0de3d85f..c75e37a4 100644 --- a/nana/modules/reverse.py +++ b/nana/modules/reverse.py @@ -4,17 +4,17 @@ import shlex from datetime import datetime from os.path import basename +from typing import Tuple, Optional import requests import tracemoepy from bs4 import BeautifulSoup from pyrogram import filters -from typing import Tuple, Optional -from nana import app, Command, logging +from nana import app, Command, logging, AdminSettings, edrep from nana.helpers.PyroHelpers import ReplyCheck -__MODULE__ = "Reverse Search" +__MODULE__ = "Reverse" __HELP__ = """ This module will help you Reverse Search Media @@ -34,7 +34,7 @@ async def run_cmd(cmd: str) -> Tuple[str, str, int, int]: - """run command in terminal""" + """run command in terminal.""" args = shlex.split(cmd) process = await asyncio.create_subprocess_exec(*args, stdout=asyncio.subprocess.PIPE, @@ -47,7 +47,7 @@ async def run_cmd(cmd: str) -> Tuple[str, str, int, int]: async def take_screen_shot(video_file: str, duration: int, path: str = '') -> Optional[str]: - """take a screenshot""" + """take a screenshot.""" ttl = duration // 2 thumb_image_path = path or os.path.join(screen_shot, f"{basename(video_file)}.jpg") command = f"ffmpeg -ss {ttl} -i '{video_file}' -vframes 1 '{thumb_image_path}'" @@ -57,11 +57,10 @@ async def take_screen_shot(video_file: str, duration: int, path: str = '') -> Op return thumb_image_path if os.path.exists(thumb_image_path) else None -@app.on_message(filters.me & filters.command(["reverse"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("reverse", Command)) async def google_rs(client, message): start = datetime.now() dis_loc = '' - base_url = "http://www.google.com" out_str = "`Reply to an image`" if message.reply_to_message: message_ = message.reply_to_message @@ -75,15 +74,16 @@ async def google_rs(client, message): ) dis_loc = os.path.join(screen_shot, os.path.basename(dis)) if message_.animation or message_.video: - await message.edit("`Converting this Gif`") + await edrep(message, text="`Converting this Gif`") img_file = os.path.join(screen_shot, "grs.jpg") await take_screen_shot(dis_loc, 0, img_file) if not os.path.lexists(img_file): - await message.edit("`Something went wrong in Conversion`") + await edrep(message, text="`Something went wrong in Conversion`") await asyncio.sleep(5) await message.delete() return dis_loc = img_file + base_url = "http://www.google.com" if dis_loc: search_url = "{}/searchbyimage/upload".format(base_url) multipart = { @@ -96,7 +96,6 @@ async def google_rs(client, message): else: await message.delete() return - await message.edit("`Found Google Result.`") headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0" } @@ -112,10 +111,10 @@ async def google_rs(client, message): Possible Related Search: {prs_text} More Info: Open this Link """ - await message.edit(out_str, parse_mode="HTML", disable_web_page_preview=True) + await edrep(message, text=out_str, parse_mode="HTML", disable_web_page_preview=True) -@app.on_message(filters.me & filters.command(["areverse"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("areverse", Command)) async def tracemoe_rs(client, message): dis_loc = '' if message.reply_to_message: @@ -130,11 +129,11 @@ async def tracemoe_rs(client, message): ) dis_loc = os.path.join(screen_shot, os.path.basename(dis)) if message_.animation: - await message.edit("`Converting this Gif`") + await edrep(message, text="`Converting this Gif`") img_file = os.path.join(screen_shot, "grs.jpg") await take_screen_shot(dis_loc, 0, img_file) if not os.path.lexists(img_file): - await message.edit("`Something went wrong in Conversion`") + await edrep(message, text="`Something went wrong in Conversion`") await asyncio.sleep(5) await message.delete() return @@ -146,7 +145,7 @@ async def tracemoe_rs(client, message): img_file = os.path.join(screen_shot, "grs.jpg") await take_screen_shot(dis_loc, 0, img_file) if not os.path.lexists(img_file): - await message.edit("`Something went wrong in Conversion`") + await edrep(message, text="`Something went wrong in Conversion`") await asyncio.sleep(5) await message.delete() return @@ -155,13 +154,12 @@ async def tracemoe_rs(client, message): if message_.video: search = await tracemoe.search(img_file, encode=True) os.remove(img_file) - os.remove(dis_loc) else: search = await tracemoe.search(dis_loc, encode=True) - os.remove(dis_loc) + os.remove(dis_loc) result = search['docs'][0] - msg = f"**Title**: {result['title_english']}" \ - f"\n**Similarity**: {str(result['similarity'])[1:2]}" \ + ms_g = f"**Title**: {result['title_english']}" \ + f"\n**Similarity**: {result['similarity']*100}"\ f"\n**Episode**: {result['episode']}" preview = await tracemoe.video_preview(search) with open('preview.mp4', 'wb') as f: @@ -169,7 +167,7 @@ async def tracemoe_rs(client, message): await message.delete() await client.send_video(message.chat.id, 'preview.mp4', - caption=msg, + caption=ms_g, reply_to_message_id=ReplyCheck(message) ) await asyncio.sleep(5) @@ -179,7 +177,7 @@ async def tracemoe_rs(client, message): await message.delete() return else: - await message.edit("`Reply to a message to proceed`") + await edrep(message, text="`Reply to a message to proceed`") await asyncio.sleep(5) await message.delete() return diff --git a/nana/modules/rmbg.py b/nana/modules/rmbg.py index 1d46834f..c050e0ad 100644 --- a/nana/modules/rmbg.py +++ b/nana/modules/rmbg.py @@ -8,11 +8,12 @@ # Ported to Nana by @pokurt import os +from asyncio import sleep from pyrogram import filters from removebg import RemoveBg -from nana import app, Command, remove_bg_api +from nana import app, Command, remove_bg_api, AdminSettings, edrep from nana.helpers.PyroHelpers import ReplyCheck DOWN_PATH = 'nana/' @@ -20,12 +21,11 @@ IMG_PATH = DOWN_PATH + "image.jpg" -@app.on_message(filters.me & filters.command(["rmbg"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("rmbg", Command)) async def remove_bg(client, message): if not remove_bg_api: - await message.edit("Get the API from [Remove.bg](https://www.remove.bg/b/background-removal-api)", + await edrep(message, text="Get the API from [Remove.bg](https://www.remove.bg/b/background-removal-api)", disable_web_page_preview=True, parse_mode="html") - await message.edit("Analysing...") replied = message.reply_to_message if (replied and replied.media and (replied.photo @@ -33,7 +33,6 @@ async def remove_bg(client, message): if os.path.exists(IMG_PATH): os.remove(IMG_PATH) await client.download_media(message=replied, file_name=IMG_PATH) - await message.edit("Removing Background...") try: rmbg = RemoveBg(remove_bg_api, "rm_bg_error.log") rmbg.remove_background_from_img_file(IMG_PATH) @@ -44,8 +43,12 @@ async def remove_bg(client, message): reply_to_message_id=ReplyCheck(message), disable_notification=True) await message.delete() + os.remove(remove_img) + os.remove(IMG_PATH) except Exception as e: print(e) - await message.edit("Something went wrong!\nCheck your usage.") + await edrep(message, text="`Something went wrong!`") + await sleep(3) + await message.delete() else: - await message.edit("Usage: reply to a photo to remove background!") + await edrep(message, text="Usage: reply to a photo to remove background!") diff --git a/nana/modules/sed.py b/nana/modules/sed.py index c7c1c60c..d724e929 100644 --- a/nana/modules/sed.py +++ b/nana/modules/sed.py @@ -1,112 +1,112 @@ -import re -import sre_constants - -from pyrogram import filters - -from nana import app - -__MODULE__ = "Sed" -__HELP__ = """ -Need help? -Learn regex here: regexone.com - -──「 **Regex** 」── --> `s/(regex)` -Yes, just reply a msg and do `s/test/text`. - -Example: "This is test" -Reply: s/test/text -Result: "This is text" - -Flags: i (ignore), g (global) -Flag text: `test things test` -Flag ex: s/test/text/g -Flag result: `text things text` -""" - -DELIMITERS = ("/", ":", "|", "_") - - -async def separate_sed(sed_string): - if ( - len(sed_string) >= 3 - and sed_string[3] in DELIMITERS - and sed_string.count(sed_string[3]) >= 2 - ): - delim = sed_string[3] - start = counter = 4 - while counter < len(sed_string): - if sed_string[counter] == "\\": - counter += 1 - - elif sed_string[counter] == delim: - replace = sed_string[start:counter] - counter += 1 - start = counter - break - - counter += 1 - - else: - return None - - while counter < len(sed_string): - if ( - sed_string[counter] == "\\" - and counter + 1 < len(sed_string) - and sed_string[counter + 1] == delim - ): - sed_string = sed_string[:counter] + sed_string[counter + 1:] - - elif sed_string[counter] == delim: - replace_with = sed_string[start:counter] - counter += 1 - break - - counter += 1 - else: - return replace, sed_string[start:], "" - - flags = "" - if counter < len(sed_string): - flags = sed_string[counter:] - return replace, replace_with, flags.lower() - - -@app.on_message(filters.me & filters.regex("^s/(.*?)")) -async def sed_msg(client, message): - sed_result = await separate_sed("s/" + message.text) - if sed_result: - if message.reply_to_message: - to_fix = message.reply_to_message.text - if to_fix is None: - to_fix = message.reply_to_message.caption - if to_fix is None: - return - else: - return - repl, repl_with, flags = sed_result - if not repl: - return - - try: - check = re.match(repl, to_fix, flags=re.IGNORECASE) - if check and check.group(0).lower() == to_fix.lower(): - return - - if "i" in flags and "g" in flags: - text = re.sub(repl, repl_with, to_fix, flags=re.I).strip() - elif "i" in flags: - text = re.sub(repl, repl_with, to_fix, count=1, flags=re.I).strip() - elif "g" in flags: - text = re.sub(repl, repl_with, to_fix).strip() - else: - text = re.sub(repl, repl_with, to_fix, count=1).strip() - except sre_constants.error: - print("SRE constant error") - await message.edit("SRE constant error. You can learn regex in [here](https://regexone.com)", - disable_web_page_preview=True) - return - if text: - await client.edit_message_text(message.chat.id, message_id=message.message_id, - text="Did you you mean:\n```{}```".format(text)) +import re +import sre_constants + +from pyrogram import filters + +from nana import app, edrep, AdminSettings + +__MODULE__ = "Sed" +__HELP__ = """ +Need help? +Learn regex here: regexone.com + +──「 **Regex** 」── +-> `s/(regex)` +Yes, just reply a msg and do `s/test/text`. + +Example: "This is test" +Reply: s/test/text +Result: "This is text" + +Flags: i (ignore), g (global) +Flag text: `test things test` +Flag ex: s/test/text/g +Flag result: `text things text` +""" + +DELIMITERS = ("/", ":", "|", "_") + + +async def separate_sed(sed_string): + if ( + len(sed_string) < 3 + or sed_string[3] not in DELIMITERS + or sed_string.count(sed_string[3]) < 2 + ): + return + + delim = sed_string[3] + start = counter = 4 + while counter < len(sed_string): + if sed_string[counter] == "\\": + counter += 1 + + elif sed_string[counter] == delim: + replace = sed_string[start:counter] + counter += 1 + start = counter + break + + counter += 1 + + else: + return None + + while counter < len(sed_string): + if ( + sed_string[counter] == "\\" + and counter + 1 < len(sed_string) + and sed_string[counter + 1] == delim + ): + sed_string = sed_string[:counter] + sed_string[counter + 1:] + + elif sed_string[counter] == delim: + replace_with = sed_string[start:counter] + counter += 1 + break + + counter += 1 + else: + return replace, sed_string[start:], "" + + flags = "" + if counter < len(sed_string): + flags = sed_string[counter:] + return replace, replace_with, flags.lower() + + +@app.on_message(filters.user(AdminSettings) & filters.regex("^s/(.*?)")) +async def sed_msg(client, message): + sed_result = await separate_sed("s/" + message.text) + if sed_result: + if message.reply_to_message: + to_fix = message.reply_to_message.text + if to_fix is None: + to_fix = message.reply_to_message.caption + if to_fix is None: + return + else: + return + repl, repl_with, flags = sed_result + if not repl: + return + + try: + check = re.match(repl, to_fix, flags=re.IGNORECASE) + if check and check.group(0).lower() == to_fix.lower(): + return + + if "i" in flags and "g" in flags: + text = re.sub(repl, repl_with, to_fix, flags=re.I).strip() + elif "i" in flags: + text = re.sub(repl, repl_with, to_fix, count=1, flags=re.I).strip() + elif "g" in flags: + text = re.sub(repl, repl_with, to_fix).strip() + else: + text = re.sub(repl, repl_with, to_fix, count=1).strip() + except sre_constants.error: + print("SRE constant error") + await edrep(message, text="SRE constant error. You can learn regex in [here](https://regexone.com)", disable_web_page_preview=True) + return + if text: + await edrep(message, text="```{}```".format(text)) diff --git a/nana/modules/speedtest.py b/nana/modules/speedtest.py new file mode 100644 index 00000000..37b75a24 --- /dev/null +++ b/nana/modules/speedtest.py @@ -0,0 +1,59 @@ +import re + +import speedtest +from pyrogram import filters + +from nana import setbot, AdminSettings, BotUsername, app, Command +from nana.helpers.PyroHelpers import ReplyCheck + + +def speedtest_callback(_, __, query): + if re.match("speedtest", query.data): + return True + +speedtest_create = filters.create(speedtest_callback) + +def speed_convert(size): + """Hi human, you can't read bytes?""" + power = 2 ** 10 + zero = 0 + units = {0: '', 1: 'Kb/s', 2: 'Mb/s', 3: 'Gb/s', 4: 'Tb/s'} + while size > power: + size /= power + zero += 1 + return f"{round(size, 2)} {units[zero]}" + +@setbot.on_callback_query(speedtest_create) +async def speedtestxyz_callback(client, query): + if query.from_user.id in AdminSettings: + await setbot.edit_inline_text(query.inline_message_id,'Runing a speedtest....') + speed = speedtest.Speedtest() + speed.get_best_server() + speed.download() + speed.upload() + replymsg = '**SpeedTest Results:**' + if query.data == 'speedtest_image': + speedtest_image = speed.results.share() + replym = f"**[SpeedTest Results:]({speedtest_image})**" + await setbot.edit_inline_text(query.inline_message_id, replym, parse_mode="markdown") + + elif query.data == 'speedtest_text': + result = speed.results.dict() + replymsg += f"\n - **ISP:** `{result['client']['isp']}`" + replymsg += f"\n - **Download:** `{speed_convert(result['download'])}`" + replymsg += f"\n - **Upload:** `{speed_convert(result['upload'])}`" + replymsg += f"\n - **Ping:** `{result['ping']}`" + await setbot.edit_inline_text(query.inline_message_id, replymsg, parse_mode="markdown") + else: + await client.answer_callback_query(query.id, "No, you are not allowed to do this", show_alert=False) + + +@app.on_message(filters.user(AdminSettings) & filters.command("speedtest", Command)) +async def google_search(client, message): + x = await client.get_inline_bot_results(f"{BotUsername}", f"speedtest") + await message.delete() + await client.send_inline_bot_result(chat_id=message.chat.id, + query_id=x.query_id, + result_id=x.results[0].id, + reply_to_message_id=ReplyCheck(message), + hide_via=True) \ No newline at end of file diff --git a/nana/modules/stickerizer.py b/nana/modules/stickerizer.py index 2b1a3709..4c8a4b73 100644 --- a/nana/modules/stickerizer.py +++ b/nana/modules/stickerizer.py @@ -3,7 +3,7 @@ from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep from nana.helpers.PyroHelpers import ReplyCheck __MODULE__ = "Stickerizer" @@ -32,9 +32,19 @@ senpais = [37, 38, 48, 55] -@app.on_message(filters.me & filters.command(["ggl"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("ggl", Command)) async def google_search(client, message): - googles = message.reply_to_message.text + cmd = message.command + googles = "" + if len(cmd) > 1: + googles = " ".join(cmd[1:]) + elif message.reply_to_message and len(cmd) == 1: + googles = message.reply_to_message.text + elif len(cmd) == 1: + await edrep(message, text="`No text Given hence can not google the void.`") + await asyncio.sleep(2) + await message.delete() + return x = await client.get_inline_bot_results("Stickerizerbot", f"#12{googles}") await message.delete() await client.send_inline_bot_result(chat_id=message.chat.id, @@ -44,7 +54,7 @@ async def google_search(client, message): hide_via=True) -@app.on_message(filters.me & filters.command(["mock"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("mock", Command)) async def mock_spongebob(client, message): cmd = message.command mock = "" @@ -52,8 +62,8 @@ async def mock_spongebob(client, message): mock = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: mock = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`Can't mock the void.`") + elif len(cmd) == 1: + await edrep(message, text="`Can't mock the void.`") await asyncio.sleep(2) await message.delete() return @@ -66,7 +76,7 @@ async def mock_spongebob(client, message): hide_via=True) -@app.on_message(filters.me & filters.command(["senpai"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("senpai", Command)) async def senpai_sticker(client, message): cmd = message.command senpai = "" @@ -74,8 +84,8 @@ async def senpai_sticker(client, message): senpai = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: senpai = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`No text Given hence the senpai Ran Away.`") + elif len(cmd) == 1: + await edrep(message, text="`No text Given hence the senpai Ran Away.`") await asyncio.sleep(2) await message.delete() return @@ -88,7 +98,7 @@ async def senpai_sticker(client, message): hide_via=True) -@app.on_message(filters.me & filters.command(["waifu"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("waifu", Command)) async def waifu_sticker(client, message): cmd = message.command waifu = "" @@ -96,8 +106,8 @@ async def waifu_sticker(client, message): waifu = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: waifu = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("`No text Given hence the waifu Ran Away.`") + elif len(cmd) == 1: + await edrep(message, text="`No text Given hence the waifu Ran Away.`") await asyncio.sleep(2) await message.delete() return diff --git a/nana/modules/stickers.py b/nana/modules/stickers.py index 8e562a13..81bc3fb5 100644 --- a/nana/modules/stickers.py +++ b/nana/modules/stickers.py @@ -4,7 +4,7 @@ from PIL import Image -from nana import app, setbot, Command, DB_AVAILABLE +from nana import app, setbot, Command, DB_AVAILABLE, AdminSettings, edrep if DB_AVAILABLE: from nana.assistant.database.stickers_db import get_sticker_set, get_stanim_set @@ -28,15 +28,15 @@ """ -@app.on_message(filters.me & filters.command(["kang"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("kang", Command)) async def kang_stickers(client, message): if not DB_AVAILABLE: - await message.edit("Your database is not avaiable!") + await edrep(message, text="Your database is not avaiable!") return sticker_pack = get_sticker_set(message.from_user.id) animation_pack = get_stanim_set(message.from_user.id) if not sticker_pack: - await message.edit("You're not setup sticker pack!\nCheck your assistant for more information!") + await edrep(message, text="You're not setup sticker pack!\nCheck your assistant for more information!") await setbot.send_message(message.from_user.id, "Hello 🙂\nYou're look like want to steal a sticker, but sticker pack was not set. " "To set a sticker pack, type /setsticker and follow setup.") @@ -45,7 +45,7 @@ async def kang_stickers(client, message): if message.reply_to_message and message.reply_to_message.sticker: if message.reply_to_message.sticker.mime_type == "application/x-tgsticker": if not animation_pack: - await message.edit( + await edrep(message, text= "You're not setup animation sticker pack!\nCheck your assistant for more information!") await setbot.send_message(message.from_user.id, "Hello 🙂\nYou're look like want to steal a animation sticker, but sticker " @@ -57,22 +57,28 @@ async def kang_stickers(client, message): await client.download_media(message.reply_to_message.sticker, file_name="nana/cache/sticker.png") elif message.reply_to_message and message.reply_to_message.photo: await client.download_media(message.reply_to_message.photo, file_name="nana/cache/sticker.png") - elif message.reply_to_message and message.reply_to_message.document and message.reply_to_message.document.mime_type == "image/png": + elif ( + message.reply_to_message + and message.reply_to_message.document + and message.reply_to_message.document.mime_type + in ["image/png", "image/jpeg"] + ): await client.download_media(message.reply_to_message.document, file_name="nana/cache/sticker.png") else: - await message.edit( - "Reply a sticker or photo to kang it!\nCurrent sticker pack is: {}\nCurrent animation pack is: {}".format( + await edrep(message, text="Reply a sticker or photo to kang it!\nCurrent sticker pack is: {}\nCurrent animation pack is: {}".format( sticker_pack, animation_pack.sticker)) return - if not ( - message.reply_to_message.sticker and message.reply_to_message.sticker.mime_type) == "application/x" \ - "-tgsticker": + if ( + ( + message.reply_to_message.sticker + and message.reply_to_message.sticker.mime_type + ) + ) != "application/x" "-tgsticker": im = Image.open("nana/cache/sticker.png") - maxsize = (512, 512) if (im.width and im.height) < 512: size1 = im.width size2 = im.height - if im.width > im.height: + if size1 > size2: scale = 512 / size1 size1new = 512 size2new = size2 * scale @@ -85,23 +91,22 @@ async def kang_stickers(client, message): sizenew = (size1new, size2new) im = im.resize(sizenew) else: + maxsize = (512, 512) im.thumbnail(maxsize) im.save("nana/cache/sticker.png", 'PNG') await client.send_message("@Stickers", "/addsticker") - await client.read_history("@Stickers") time.sleep(0.2) if message.reply_to_message.sticker and message.reply_to_message.sticker.mime_type == "application/x-tgsticker": await client.send_message("@Stickers", animation_pack.sticker) else: await client.send_message("@Stickers", sticker_pack) - await client.read_history("@Stickers") time.sleep(0.2) checkfull = await app.get_history("@Stickers", limit=1) if checkfull[ 0].text == "Whoa! That's probably enough stickers for one pack, give it a break. A pack can't have more than " \ "120 stickers at the moment.": - await message.edit("Your sticker pack was full!\nPlease change one from your Assistant") + await edrep(message, text="Your sticker pack was full!\nPlease change one from your Assistant") os.remove('nana/cache/sticker.png') return if message.reply_to_message.sticker and message.reply_to_message.sticker.mime_type == "application/x-tgsticker": @@ -110,26 +115,19 @@ async def kang_stickers(client, message): else: await client.send_document("@Stickers", 'nana/cache/sticker.png') os.remove('nana/cache/sticker.png') - try: + if len(message.text.split(None,1)) > 1: ic = message.text.split(None, 1)[1] - except: - try: - ic = message.reply_to_message.sticker.emoji - except: - ic = "🤔" - if ic is None: + elif message.reply_to_message.sticker: + ic = message.reply_to_message.sticker.emoji + else: ic = "🤔" await client.send_message("@Stickers", ic) - await client.read_history("@Stickers") time.sleep(1) await client.send_message("@Stickers", "/done") if message.reply_to_message.sticker and message.reply_to_message.sticker.mime_type == "application/x-tgsticker": - await message.edit( - "**Animation Sticker added!**\nYour animated sticker has been saved on [This sticker animated pack](" + await edrep(message, text="**Animation Sticker added!**\nYour animated sticker has been saved on [This sticker animated pack](" "https://t.me/addstickers/{})".format( animation_pack.sticker)) else: - await message.edit( - "**Sticker added!**\nYour sticker has been saved on [This sticker pack](https://t.me/addstickers/{})".format( + await edrep(message, text="**Sticker added!**\nYour sticker has been saved on [This sticker pack](https://t.me/addstickers/{})".format( sticker_pack)) - await client.read_history("@Stickers") diff --git a/nana/modules/stylish.py b/nana/modules/stylish.py index 10a60318..3e55a2e9 100644 --- a/nana/modules/stylish.py +++ b/nana/modules/stylish.py @@ -3,29 +3,13 @@ from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep __MODULE__ = "Stylish Text" __HELP__ = """ Convert your text to stylish text! -Use this custom format: --> `Upside-down text` = `ʇxəʇ uʍop-əpısp∩` --> `Overline text` = `̅o̅v̅e̅r̅l̅i̅n̅e̅ ̅t̅e̅x̅t̅` --> `Strike text` = `̶s̶t̶r̶i̶k̶e̶ ̶t̶e̶x̶t̶` --> `Underline text` = `̲u̲n̲d̲e̲r̲l̲i̲n̲e̲ ̲t̲e̲x̲t̲` --> `Point text` = `p̤o̤i̤n̤t̤ ̤t̤e̤x̤t̤` --> `Smallcaps text` = `sᴍᴀʟʟᴄᴀᴘs ᴛᴇxᴛ` --> `Superscript text` = `ˢᵘᵖᵉʳˢᶜʳᶦᵖᵗ ᵗᵉˣᵗ` --> `Subscript text` = `ₛᵤᵦₛ𝒸ᵣᵢₚₜ ₜₑₓₜ` --> `Wide text` = `wide text` --> `Bubbles text` = `ⒷⓊⒷⒷⓁⒺⓈ ⓉⒺⓍⓉ` --> `Bubbles black text` = `🅑🅤🅑🅑🅛🅔🅢 🅑🅛🅐🅒🅚 🅣🅔🅧🅣` --> `Smoth text` = `ᔑᗰᝪᎢᕼ Ꭲᗴ᙭Ꭲ` --> `Graffiti text` = `𝔊𝔯𝔞𝔣𝔣𝔦𝔱𝔦 𝔱𝔢𝔵𝔱` --> `Graffiti Bold text` = `𝕲𝖗𝖆𝖋𝖋𝖎𝖙𝖎 𝕭𝖔𝖑𝖉 𝖙𝖊𝖝𝖙` --> `Handwaritng text` = `𝐻𝒶𝓃𝒹𝓌𝓇𝒾𝓉𝒾𝓃𝑔 𝓉𝑒𝓍𝓉` --> `Handwriting Bold text` = `𝓗𝓪𝓷𝓭𝔀𝓻𝓲𝓽𝓲𝓷𝓰 𝓑𝓸𝓵𝓭 𝓽𝓮𝔁𝓽` +Use this custom format: [Click here to Read](https://telegra.ph/Nana-Remix-Stylish-Text-Helper-07-17) ──「 **Stylish Generator** 」── -> `stylish Your text here with formatted style` @@ -78,8 +62,8 @@ def text_style_generator(text, text_type): for i, _ in enumerate(teks): teks[i] = text_type + teks[i] pesan = "" - for x in range(len(teks)): - pesan += teks[x] + for tek in teks: + pesan += tek return pesan + text_type @@ -124,7 +108,7 @@ def stylish_formatting(text): smallcaps_compile = re.compile(r'(.*?)') src_code = smallcaps_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, smallcaps)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, smallcaps)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) @@ -132,7 +116,7 @@ def stylish_formatting(text): superscript_compile = re.compile(r'(.*?)') src_code = superscript_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, superscript)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, superscript)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) @@ -140,7 +124,7 @@ def stylish_formatting(text): subscript_compile = re.compile(r'(.*?)') src_code = subscript_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, subscript)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, subscript)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) @@ -148,7 +132,7 @@ def stylish_formatting(text): wide_compile = re.compile(r'(.*?)') src_code = wide_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, wide)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, wide)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) @@ -156,7 +140,7 @@ def stylish_formatting(text): bubble_compile = re.compile(r'(.*?)') src_code = bubble_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, bubbles)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, bubbles)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) @@ -164,7 +148,7 @@ def stylish_formatting(text): bubble2_compile = re.compile(r'(.*?)') src_code = bubble2_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, bubblesblack)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, bubblesblack)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) @@ -172,35 +156,35 @@ def stylish_formatting(text): smoth_compile = re.compile(r'(.*?)') src_code = smoth_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, smothtext)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, smothtext)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) graffiti_compile = re.compile(r'(.*?)') src_code = graffiti_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, graffiti)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, graffiti)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) handwriting_compile = re.compile(r'(.*?)') src_code = handwriting_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, handwriting)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, handwriting)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) handwritingb_compile = re.compile(r'(.*?)') src_code = handwritingb_compile.findall(text) for x in src_code: - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, handwritingb)) + unic = {ord(x[0]): x[1] for x in zip(normaltext, handwritingb)} convtext = x.translate(unic) text = re.sub(r'(.*?)', convtext, text, 1) return text -@app.on_message(filters.me & filters.command(["stylish"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("stylish", Command)) async def stylish_generator(_client, message): if message.text and len(message.text.split()) == 1 or message.caption and len(message.caption.split()) == 1: - await message.edit("Usage: `stylish your text goes here`") + await edrep(message, text="Usage: `stylish your text goes here`") return if message.caption: @@ -213,14 +197,13 @@ async def stylish_generator(_client, message): if message.caption: await message.edit_caption(text) else: - await message.edit(text) + await edrep(message, text=text) # For inline stuff def formatting_text_inline(text, text_style): - unic = dict((ord(x[0]), x[1]) for x in zip(normaltext, text_style)) - conv = text.translate(unic) - return conv + unic = {ord(x[0]): x[1] for x in zip(normaltext, text_style)} + return text.translate(unic) def upsidedown_text_inline(text): diff --git a/nana/modules/telegraph.py b/nana/modules/telegraph.py index f62cabeb..cbf769f2 100644 --- a/nana/modules/telegraph.py +++ b/nana/modules/telegraph.py @@ -3,7 +3,7 @@ from pyrogram import filters from telegraph import upload_file -from nana import Command, app +from nana import Command, app, AdminSettings, edrep __MODULE__ = "Telegra.ph" __HELP__ = """ @@ -17,11 +17,11 @@ """ -@app.on_message(filters.me & filters.command(["telegraph"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("telegraph", Command)) async def telegraph(client, message): replied = message.reply_to_message if not replied: - await message.edit("reply to a supported media file") + await edrep(message, text="reply to a supported media file") return if not ((replied.photo and replied.photo.file_size <= 5242880) or (replied.animation and replied.animation.file_size <= 5242880) @@ -31,15 +31,14 @@ async def telegraph(client, message): and replied.document.file_name.endswith( ('.jpg', '.jpeg', '.png', '.gif', '.mp4')) and replied.document.file_size <= 5242880)): - await message.edit("not supported!") + await edrep(message, text="not supported!") return download_location = await client.download_media(message=message.reply_to_message,file_name='root/nana/') - await message.edit("`passing to telegraph...`") try: response = upload_file(download_location) except Exception as document: - await message.edit(document) + await edrep(message, text=document) else: - await message.edit(f"**Document passed to: [Telegra.ph](https://telegra.ph{response[0]})**") + await edrep(message, text=f"**Document passed to: [Telegra.ph](https://telegra.ph{response[0]})**") finally: os.remove(download_location) \ No newline at end of file diff --git a/nana/modules/termux.py b/nana/modules/termux.py index be8c18fd..0de19e52 100644 --- a/nana/modules/termux.py +++ b/nana/modules/termux.py @@ -5,7 +5,7 @@ from pyrogram import filters -from nana import Command, app, TERMUX_USER +from nana import Command, app, TERMUX_USER, AdminSettings, edrep __MODULE__ = "Termux" __HELP__ = """ @@ -23,40 +23,39 @@ """ torch = False -@app.on_message(filters.me & filters.command(["bstats"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("bstats", Command)) async def bstat(_client, message): if TERMUX_USER: termux_command = subprocess.Popen("termux-battery-status", shell=True, stdout=subprocess.PIPE) my_bytes_value = termux_command.stdout.read() my_json = my_bytes_value.decode('utf8').replace("'", '').replace('"', '').replace("{", '').replace("}", '').replace(",", '').replace(" ", '').replace(":", ': ') - await message.edit(f"Battery Status:{my_json}") + await edrep(message, text=f"Battery Status:{my_json}") else: - await message.edit("This command is only for Termux users!") + await edrep(message, text="This command is only for Termux users!") await sleep(2.0) await message.delete() -@app.on_message(filters.me & filters.command(["torch"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("torch", Command)) async def termux_torch(_client, message): global torch if torch: - await message.edit("Turning off torch...") + await edrep(message, text="Turning off torch...") await sleep(0.5) subprocess.Popen("termux-torch off", shell=True, stdout=subprocess.PIPE) torch = False - await message.edit("Torch turned off") - await sleep(2.0) - await message.delete() + await edrep(message, text="Torch turned off") else: - await message.edit("Turning on torch...") + await edrep(message, text="Turning on torch...") try: subprocess.Popen("termux-torch on", shell=True, stdout=subprocess.PIPE) - except: - await message.edit("Couldn't turn off torch!") + except Exception as e: + print(e) + await edrep(message, text="Couldn't turn off torch!") await sleep(2.0) await message.delete() return torch = True - await message.edit("Torch turned on!") - await sleep(2.0) - await message.delete() \ No newline at end of file + await edrep(message, text="Torch turned on!") + await sleep(2.0) + await message.delete() \ No newline at end of file diff --git a/nana/modules/timezone.py b/nana/modules/timezone.py new file mode 100644 index 00000000..93b811a1 --- /dev/null +++ b/nana/modules/timezone.py @@ -0,0 +1,31 @@ +from datetime import datetime + +from pyrogram import filters +from pytz import timezone + +from nana import app, Command, time_country, AdminSettings, edrep + +__MODULE__ = "Time" +__HELP__ = """ +Modules that helps a user to get date and time +here are the timezone list: [link](https://telegra.ph/Time-Zone-list-for-Nana-Remix-07-21) + +──「 **Time and Date** 」── +-> `time` +Returns the Date and Time for a selected country + +""" + + +@app.on_message(filters.user(AdminSettings) & filters.command("time", Command)) +async def grabTime(client, message): + if not time_country: + await message.delete() + return + tz = time_country.replace('_', ' ') + tzDateTime = datetime.now(timezone(tz)) + date = tzDateTime.strftime(r'%d-%m-%Y') + militaryTime = tzDateTime.strftime('%H:%M') + time = datetime.strptime(militaryTime, "%H:%M").strftime("%I:%M %p") + time_string = '__Currently it is__' +f' **{time}** '+'__on__'+f' **{date}** '+'__in__ '+f'**{tz}**' + await edrep(message, text=time_string) \ No newline at end of file diff --git a/nana/modules/transfersh.py b/nana/modules/transfersh.py index fbe4ba9c..b88e12f7 100644 --- a/nana/modules/transfersh.py +++ b/nana/modules/transfersh.py @@ -7,7 +7,7 @@ import pycurl from pyrogram import filters -from nana import app, Command, log +from nana import app, Command, log, AdminSettings, edrep from .downloads import download_file_from_tg, name_file, humanbytes __MODULE__ = "transfer sh" @@ -21,39 +21,31 @@ """ -@app.on_message(filters.me & filters.command(["tfsh"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("tfsh", Command)) async def tfsh(client, message): if not message.reply_to_message: - await message.edit("`Reply to any file telegram message!`") + await edrep(message, text="`Reply to any file telegram message!`") return - await message.edit("`Processing...`") + await edrep(message, text="`Processing...`") name = await name_file(client, message) await download_file_from_tg(client, message) - if len(name) > 10: - name_file_upload = name[-10:] - else: - name_file_upload = name + name_file_upload = name[-10:] if len(name) > 10 else name name_file_upload.encode('ascii', 'ignore') os.rename(r'nana/downloads/{}'.format(name), r'nana/downloads/{}'.format(name_file_upload)) print(name_file_upload) - await message.edit( + await edrep(message, text= await send_to_transfersh("nana/downloads/{}".format(name_file_upload), message, name_file_upload)) os.remove("nana/downloads/{}".format(name_file_upload)) return async def send_to_transfersh(file, message, name): - """ - send file to transfersh, retrieve download link, and copy it to clipboard - :param file: absolute path to file - :param message: a message atribute - :return: download_link - """ + """send file to transfersh, retrieve download link""" size_of_file = get_size(file) final_date = get_date_in_two_weeks() file_name = os.path.basename(file) - await message.edit("\nSending file: {} (size of the file: {})".format(file_name, size_of_file)) + await edrep(message, text="\nSending file: {} (size of the file: {})".format(file_name, size_of_file)) url = 'https://transfer.sh/{}'.format(name) c = pycurl.Curl() c.setopt(c.URL, url) diff --git a/nana/modules/translate.py b/nana/modules/translate.py index bbbeaadb..18a62d14 100644 --- a/nana/modules/translate.py +++ b/nana/modules/translate.py @@ -1,7 +1,7 @@ from googletrans import Translator from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep trl = Translator() @@ -18,14 +18,11 @@ * = Not used when reply a message! """ - -# TODO: Setlang for translation - -@app.on_message(filters.me & filters.command(["tr"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("tr", Command)) async def translate(_client, message): if message.reply_to_message and (message.reply_to_message.text or message.reply_to_message.caption): if len(message.text.split()) == 1: - await message.edit("Usage: Reply to a message, then `tr `") + await edrep(message, text="Usage: Reply to a message, then `tr `") return target = message.text.split()[1] if message.reply_to_message.text: @@ -36,12 +33,11 @@ async def translate(_client, message): try: tekstr = trl.translate(text, dest=target) except ValueError as err: - await message.edit("Error: `{}`".format(str(err))) + await edrep(message, text=f"Error: `{str(err)}`") return - await message.edit("Translated from `{}` to `{}`:\n```{}```".format(detectlang.lang, target, tekstr.text)) else: if len(message.text.split()) <= 2: - await message.edit("Usage: `tr `") + await edrep(message, text="Usage: `tr `") return target = message.text.split(None, 2)[1] text = message.text.split(None, 2)[2] @@ -49,6 +45,7 @@ async def translate(_client, message): try: tekstr = trl.translate(text, dest=target) except ValueError as err: - await message.edit("Error: `{}`".format(str(err))) + await edrep(message, text="Error: `{}`".format(str(err))) return - await message.edit("Translated from `{}` to `{}`:\n```{}```".format(detectlang.lang, target, tekstr.text)) + + await edrep(message, text=f"Translated from `{detectlang.lang}` to `{target}`:\n```{tekstr.text}```") diff --git a/nana/modules/updater.py b/nana/modules/updater.py index a1cdf04f..d2b3621e 100644 --- a/nana/modules/updater.py +++ b/nana/modules/updater.py @@ -6,7 +6,7 @@ from git.exc import InvalidGitRepositoryError, GitCommandError, NoSuchPathError from pyrogram import filters -from nana import app, Command, OFFICIAL_BRANCH, REPOSITORY, HEROKU_API +from nana import app, Command, OFFICIAL_BRANCH, REPOSITORY, HEROKU_API, edrep from nana.__main__ import restart_all, except_hook from nana.assistant.updater import update_changelog @@ -52,26 +52,25 @@ async def initial_git(repo): os.rename('nana-old/nana/session/', 'nana/session/') -@app.on_message(filters.me & filters.command(["update"], Command)) +@app.on_message(filters.me & filters.command("update", Command)) async def updater(client, message): - await message.edit("__Checking update...__") + await edrep(message, text="__Checking update...__") initial = False try: repo = Repo() except NoSuchPathError as error: - await message.edit(f"**Update failed!**\n\nError:\n`directory {error} is not found`") + await edrep(message, text=f"**Update failed!**\n\nError:\n`directory {error} is not found`") return except InvalidGitRepositoryError: repo = Repo.init() initial = True except GitCommandError as error: - await message.edit(f'**Update failed!**\n\nError:\n`{error}`') + await edrep(message, text=f'**Update failed!**\n\nError:\n`{error}`') return if initial: if len(message.text.split()) != 2: - await message.edit( - 'Your git workdir is missing!\nBut i can repair and take new latest update for you.\nJust do `update ' + await edrep(message, text='Your git workdir is missing!\nBut i can repair and take new latest update for you.\nJust do `update ' 'now` to repair and take update!') return elif len(message.text.split()) == 2 and message.text.split()[1] == "now": @@ -79,19 +78,18 @@ async def updater(client, message): await initial_git(repo) except Exception as err: exc_type, exc_obj, exc_tb = sys.exc_info() - await message.edit(f'**Error:**\n{err}') + await edrep(message, text=f'**Error:**\n{err}') await except_hook(exc_type, exc_obj, exc_tb) return - await message.edit('Successfully Updated!\nBot is restarting...') + await edrep(message, text='Successfully Updated!\nBot is restarting...') await update_changelog( - "-> **WARNING**: Bot has been created a new git and sync to latest version, your old files is in " - "nana-old") + "-> **WARNING**: Bot has been created a new git and sync to latest version, your old files is in nana-old") await restart_all() return brname = repo.active_branch.name if brname not in OFFICIAL_BRANCH: - await message.edit(f'**[UPDATER]:** Looks like you are using your own custom branch ({brname}). in that case, Updater is unable to identify which branch is to be merged. please checkout to any official branch') + await edrep(message, text=f'**[UPDATER]:** Looks like you are using your own custom branch ({brname}). in that case, Updater is unable to identify which branch is to be merged. please checkout to any official branch') return try: repo.create_remote('upstream', REPOSITORY) @@ -108,40 +106,38 @@ async def updater(client, message): await initial_git(repo) except Exception as err: exc_type, exc_obj, exc_tb = sys.exc_info() - await message.edit(f'**Error:**\n{err}') + await edrep(message, text=f'**Error:**\n{err}') await except_hook(exc_type, exc_obj, exc_tb) return - await message.edit('Successfully Updated!\nBot is restarting...') - await update_changelog( - "-> **WARNING**: Bot has been created a new git and sync to latest version, your old files is in " - "nana-old") + await edrep(message, text='Successfully Updated!\nBot is restarting...') + await update_changelog("-> **WARNING**: Bot has been created a new git and sync to latest version, your old files is in nana-old") await restart_all() return exc_type, exc_obj, exc_tb = sys.exc_info() - await message.edit('An error has accured!\nPlease see your Assistant for more information!') + await edrep(message, text='An error has accured!\nPlease see your Assistant for more information!') await except_hook(exc_type, exc_obj, exc_tb) return if not changelog: - await message.edit(f'Nana is up-to-date with branch **{brname}**\n') + await edrep(message, text=f'Nana is up-to-date with branch **{brname}**\n') return if len(message.text.split()) != 2: changelog_str = f'To update latest changelog, do\n-> `update now`\n\n**New UPDATE available for [{brname}]:\n' \ f'\nCHANGELOG:**\n`{changelog}` ' if len(changelog_str) > 4096: - await message.edit("`Changelog is too big, view the file to see it.`") + await edrep(message, text="`Changelog is too big, view the file to see it.`") file = open("nana/cache/output.txt", "w+") file.write(changelog_str) file.close() await client.send_document(message.chat.id, "nana/cache/output.txt", reply_to_message_id=message.message_id, - caption="`Changelog file`") + caption="`Changelog file`") os.remove("nana/cache/output.txt") else: - await message.edit(changelog_str) + await edrep(message, text=changelog_str) return elif len(message.text.split()) == 2 and message.text.split()[1] == "now": - await message.edit('`New update found, updating...`') + await edrep(message, text='`New update found, updating...`') if HEROKU_API is not None: import heroku3 heroku = heroku3.from_key(HEROKU_API) @@ -160,20 +156,18 @@ async def updater(client, message): remote.push(refspec="HEAD:refs/heads/master") else: await message.reply("no heroku application found, but a key given? 😕 ") - await message.edit("Build Unsuccess, Check heroku build log for more detail") + await edrep(message, text="Build Unsuccess, Check heroku build log for more detail") return try: upstream.pull(brname) - await message.edit('Successfully Updated!\nBot is restarting...') + await edrep(message, text='Successfully Updated!\nBot is restarting...') except GitCommandError: repo.git.reset('--hard') repo.git.clean('-fd', 'nana/modules/') repo.git.clean('-fd', 'nana/assistant/') repo.git.clean('-fd', 'nana/helpers/') - await message.edit('Successfully Updated!\nBot is restarting...') + await edrep(message, text='Successfully Updated!\nBot is restarting...') await update_changelog(changelog) await restart_all() else: - await message.edit( - "Usage:\n-> `update` to check update\n-> `update now` to update latest commits\nFor more information " - "check at your Assistant") + await edrep(message, text="Usage:\n-> `update` to check update\n-> `update now` to update latest commits\nFor more information ") diff --git a/nana/modules/uploader.py b/nana/modules/uploader.py index 4498fdcc..e47bafee 100644 --- a/nana/modules/uploader.py +++ b/nana/modules/uploader.py @@ -4,9 +4,9 @@ import requests from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep -__MODULE__ = "Uploader image" +__MODULE__ = "Uploader" __HELP__ = """ Reupload URL image to telegram without save it first. @@ -20,10 +20,10 @@ """ -@app.on_message(filters.me & filters.command(["pic"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("pic", Command)) async def PictureUploader(client, message): if len(message.text.split()) == 1: - await message.edit("Usage: `.pic `") + await edrep(message, text="Usage: `.pic `") return photo = message.text.split(None, 1)[1] await message.delete() @@ -45,10 +45,10 @@ async def PictureUploader(client, message): await client.send_photo(message.chat.id, photo, "") -@app.on_message(filters.me & filters.command(["stk"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("stk", Command)) async def StickerUploader(client, message): if len(message.text.split()) == 1: - await message.edit("Usage: `.stk `") + await edrep(message, text="Usage: `.stk `") return photo = message.text.split(None, 1)[1] await message.delete() diff --git a/nana/modules/urbandict.py b/nana/modules/urbandict.py index 84961813..9a9e7ce7 100644 --- a/nana/modules/urbandict.py +++ b/nana/modules/urbandict.py @@ -2,11 +2,11 @@ from pyrogram import filters -from nana import app, Command +from nana import app, Command, AdminSettings, edrep from nana.helpers.aiohttp_helper import AioHttp from nana.helpers.string import replace_text -__MODULE__ = "Urban Dictionary" +__MODULE__ = "Urban" __HELP__ = """ Search for urban dictionary @@ -16,10 +16,10 @@ """ -@app.on_message(filters.me & filters.command(["ud"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("ud", Command)) async def urban_dictionary(_client, message): if len(message.text.split()) == 1: - await message.edit("Usage: `ud example`") + await edrep(message, text="Usage: `ud example`") return try: text = message.text.split(None, 1)[1] @@ -28,10 +28,10 @@ async def urban_dictionary(_client, message): definition = response['list'][0]['definition'] example = response['list'][0]['example'] teks = f"**Text: {replace_text(word)}**\n**Meaning:**\n`{replace_text(definition)}`\n\n**Example:**\n`{replace_text(example)}`" - await message.edit(teks) + await edrep(message, text=teks) return except Exception as e: - await message.edit("`The Unban Dictionary API could not be reached`") + await edrep(message, text="`The Unban Dictionary API could not be reached`") print(e) await sleep(3) await message.delete() diff --git a/nana/modules/usage.py b/nana/modules/usage.py index 23da5614..1c3acdfe 100644 --- a/nana/modules/usage.py +++ b/nana/modules/usage.py @@ -5,7 +5,7 @@ import requests from pyrogram import filters -from nana import app, Command, HEROKU_API +from nana import app, Command, HEROKU_API, AdminSettings, edrep # ================= CONSTANT ================= Heroku = heroku3.from_key(HEROKU_API) @@ -13,7 +13,7 @@ # ================= CONSTANT ================= -@app.on_message(filters.me & filters.command(["usage"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("usage", Command)) async def usage(client, message): useragent = ('Mozilla/5.0 (Linux; Android 10; SM-G975F) ' 'AppleWebKit/537.36 (KHTML, like Gecko) ' @@ -27,20 +27,18 @@ async def usage(client, message): path = "/accounts/" + u_id + "/actions/get-quota" r = requests.get(heroku_api + path, headers=headers) if r.status_code != 200: - return await message.edit("`Error: something bad happened`\n\n" + return await edrep(message, text="`Error: something bad happened`\n\n" f">.`{r.reason}`\n") result = r.json() quota = result['account_quota'] quota_used = result['quota_used'] - """ - Used - """ remaining_quota = quota - quota_used percentage = math.floor(remaining_quota / quota * 100) minutes_remaining = remaining_quota / 60 hours = math.floor(minutes_remaining / 60) minutes = math.floor(minutes_remaining % 60) - """ - Current - """ App = result['apps'] try: App[0]['quota_used'] @@ -56,4 +54,4 @@ async def usage(client, message): message_usage += f"**Available in month**: `{hours}`**h** `{minutes}`**m** | `{percentage}`**%**" await asyncio.sleep(1.5) - await message.edit(message_usage) \ No newline at end of file + await edrep(message, text=message_usage) \ No newline at end of file diff --git a/nana/modules/user.py b/nana/modules/user.py index d3fcef13..fc1f5b0d 100644 --- a/nana/modules/user.py +++ b/nana/modules/user.py @@ -1,10 +1,11 @@ import os -from asyncio import sleep +from asyncio import sleep, gather from pyrogram import filters +from pyrogram import utils from pyrogram.raw import functions -from nana import app, Command, DB_AVAILABLE +from nana import app, Command, DB_AVAILABLE, AdminSettings, edrep if DB_AVAILABLE: from nana.modules.database.cloner_db import backup_indentity, restore_identity @@ -20,20 +21,76 @@ -> `vpfp` View current pfp of user --> `clone` -clone user identity without original backup +──「 **Cloner** 」── +-> `clone` or `revert` +clone user identity or revert to original identity -> `clone origin` clone user identity with original backup --> `revert` -revert to original identity +──「 **Group** 」── +-> `join ` +joins a public groupchat + +-> `leave` +Leave chat + +──「 **Tag All** 」── +-> `tagall` +tags most recent 100 members in a group + +──「 **Unread** 」── +-> `un` or `unread` +Set chat status to unread + +──「 **Save Message** 」── +-> `s` or `save` +Forward a message into Saved Messages + +──「 **Link Message** 」── +-> `link` +Creates message link to a message """ profile_photo = "nana/downloads/pfp.jpg" -@app.on_message(filters.me & filters.command(["setpfp"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("link", Command)) +async def link_message(client, message): + if message.chat.type == "private" and message.chat.type == "bot": + await message.delete() + return + else: + if message.reply_to_message: + b = message.reply_to_message.message_id + else: + b = message.message_id + a = utils.get_channel_id(message.chat.id) + await edrep(message, text=f'https://t.me/c/{a}/{b}') + + +@app.on_message(filters.user(AdminSettings) & filters.command(["e", "edit"], Command)) +async def edit_text(client, message): + cmd = message.command + teks = "" + if len(cmd) > 1: + teks = " ".join(cmd[1:]) + rep = message.reply_to_message + if rep.text: + await message.delete() + await client.edit_message_text(message.chat.id, message.reply_to_message.message_id, teks) + return + elif rep.photo or rep.video or rep.audio or rep.voice or rep.sticker or rep.animation: + await message.delete() + await client.edit_message_caption(message.chat.id, message.reply_to_message.message_id, teks) + else: + await edrep(message, text='`reply to a message to edit caption`') + await sleep(3) + await message.delete() + + + +@app.on_message(filters.user(AdminSettings) & filters.command("setpfp", Command)) async def set_pfp(client, message): replied = message.reply_to_message if (replied and replied.media and ( @@ -49,17 +106,16 @@ async def set_pfp(client, message): await client.set_profile_photo(profile_photo) if os.path.exists(profile_photo): os.remove(profile_photo) - await message.edit( - "Profile picture changed.", + await edrep(message, text="Profile picture changed.", parse_mode='html' ) else: - await message.edit("```Reply to any photo to set as pfp```") + await edrep(message, text="```Reply to any photo to set as pfp```") await sleep(3) await message.delete() -@app.on_message(filters.me & filters.command(["vpfp"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("vpfp", Command)) async def view_pfp(client, message): replied = message.reply_to_message if replied: @@ -67,7 +123,7 @@ async def view_pfp(client, message): else: user = await client.get_me() if not user.photo: - await message.edit("profile photo not found!") + await edrep(message, text="profile photo not found!") return await client.download_media( user.photo.big_file_id, @@ -79,14 +135,14 @@ async def view_pfp(client, message): os.remove(profile_photo) -@app.on_message(filters.me & filters.command(["clone"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("clone", Command)) async def clone(client, message): if message.reply_to_message: target = message.reply_to_message.from_user.id elif len(message.text.split()) >= 2 and message.text.split()[1].isdigit(): - await message.edit("Select target user to clone their identity!") + await edrep(message, text="Select target user to clone their identity!") else: - await message.edit("Select target user to clone their identity!") + await edrep(message, text="Select target user to clone their identity!") if "origin" in message.text: my_self = await app.get_me() my_self = await client.send(functions.users.GetFullUser(id=await client.resolve_peer(my_self['id']))) @@ -103,12 +159,12 @@ async def clone(client, message): p_file.UpdateProfile(first_name=t['user']['first_name'] if t['user']['first_name'] is not None else "", last_name=t['user']['last_name'] if t['user']['last_name'] is not None else "", about=t['about'] if t['about'] is not None else "")) - await message.edit("`New identity has changed!`") + await edrep(message, text="`New identity has changed!`") await sleep(5) await message.delete() -@app.on_message(filters.me & filters.command(["revert"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("revert", Command)) async def revert(client, message): first_name, last_name, bio = restore_identity() @@ -120,6 +176,49 @@ async def revert(client, message): await app.delete_profile_photos(photos[0].file_id) - await message.edit("`Identity Reverted`") + await edrep(message, text="`Identity Reverted`") await sleep(5) await message.delete() + + +@app.on_message(filters.user(AdminSettings) & filters.command("join", Command)) +async def join_chat(client, message): + cmd = message.command + text = "" + if len(cmd) > 1: + text = " ".join(cmd[1:]) + elif message.reply_to_message and len(cmd) == 1: + text = message.reply_to_message.text + elif len(cmd) == 1: + await edrep(message, text="`cant join the void.`") + await sleep(2) + await message.delete() + return + await client.join_chat(text.replace('@', '')) + await edrep(message, text=f'joined {text} successfully!') + await sleep(2) + await message.delete() + + +@app.on_message(filters.user(AdminSettings) & filters.command("leave", Command)) +async def leave_chat(client, message): + await edrep(message, text='__adios__') + await client.leave_chat(message.chat.id) + + +@app.on_message(filters.command('unread', Command) & filters.user(AdminSettings)) +async def mark_chat_unread(client, message): + await gather( + message.delete(), + client.send( + functions.messages.MarkDialogUnread( + peer=await client.resolve_peer(message.chat.id), unread=True + ) + ) + ) + + +@app.on_message(filters.command('s', Command) & filters.user(AdminSettings)) +async def to_saved(_client, message): + await message.delete() + await message.reply_to_message.forward('self') \ No newline at end of file diff --git a/nana/modules/voice.py b/nana/modules/voice.py index 564a3dda..71edb360 100644 --- a/nana/modules/voice.py +++ b/nana/modules/voice.py @@ -1,17 +1,20 @@ import asyncio import os +from datetime import datetime +import requests from gtts import gTTS from pyrogram import filters -from nana import app, Command +from nana import app, Command, IBM_WATSON_CRED_URL, IBM_WATSON_CRED_PASSWORD, AdminSettings, edrep +from nana.modules.downloads import download_reply_nocall -__MODULE__ = "Voice" +__MODULE__ = "TTS / STT" __HELP__ = """ Convert text to voice chat. -──「 **Voice** 」── --> `voice (text)` +──「 **Text-To-Speech** 」── +-> `tts (text)` Convert text to voice by google ──「 **Voice Language** 」── @@ -34,11 +37,15 @@ vi: Vietname | zh-cn: Chinese (Mandarin/China) zh-tw: Chinese (Mandarin/Taiwan)` + +──「 **Speech-To-Text** 」── +-> `stt` +Reply to a voice message to output trascript """ lang = "en" # Default Language for voice -@app.on_message(filters.me & filters.command(["voice"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("tts", Command)) async def voice(client, message): global lang cmd = message.command @@ -46,26 +53,30 @@ async def voice(client, message): v_text = " ".join(cmd[1:]) elif message.reply_to_message and len(cmd) == 1: v_text = message.reply_to_message.text - elif not message.reply_to_message and len(cmd) == 1: - await message.edit("Usage: `reply to a message or send text arg to convert to voice`") + elif len(cmd) == 1: + await edrep(message, text="Usage: `reply to a message or send text arg to convert to voice`" + ) await asyncio.sleep(2) await message.delete() return await client.send_chat_action(message.chat.id, "record_audio") # noinspection PyUnboundLocalVariable tts = gTTS(v_text, lang=lang) - tts.save('nana/cache/voice.mp3') + tts.save("nana/cache/voice.mp3") await message.delete() if message.reply_to_message: - await client.send_voice(message.chat.id, voice="nana/cache/voice.mp3", - reply_to_message_id=message.reply_to_message.message_id) + await client.send_voice( + message.chat.id, + voice="nana/cache/voice.mp3", + reply_to_message_id=message.reply_to_message.message_id, + ) else: await client.send_voice(message.chat.id, voice="nana/cache/voice.mp3") await client.send_chat_action(message.chat.id, action="cancel") os.remove("nana/cache/voice.mp3") -@app.on_message(filters.me & filters.command(["voicelang"], Command)) +@app.on_message(filters.user(AdminSettings) & filters.command("voicelang", Command)) async def voicelang(_client, message): global lang temp = lang @@ -73,7 +84,64 @@ async def voicelang(_client, message): try: gTTS("tes", lang=lang) except Exception as e: - await message.edit("Wrong Language id !") + print(e) + await edrep(message, text="Wrong Language id !") lang = temp return - await message.edit("Language Set to {}".format(lang)) + await edrep(message, text="Language Set to {}".format(lang)) + + +@app.on_message(filters.user(AdminSettings) & filters.command("stt", Command)) +async def speach_to_text(client, message): + start = datetime.now() + input_str = message.reply_to_message.voice + if input_str: + required_file_name = await download_reply_nocall(client, message) + if IBM_WATSON_CRED_URL is None or IBM_WATSON_CRED_PASSWORD is None: + await edrep(message, text="`no ibm watson key provided, aborting...`") + await asyncio.sleep(3) + await message.delete() + else: + headers = { + "Content-Type": message.reply_to_message.voice.mime_type, + } + data = open(required_file_name, "rb").read() + response = requests.post( + IBM_WATSON_CRED_URL + "/v1/recognize", + headers=headers, + data=data, + auth=("apikey", IBM_WATSON_CRED_PASSWORD), + ) + r = response.json() + if "results" in r: + # process the json to appropriate string format + results = r["results"] + transcript_response = "" + transcript_confidence = "" + for alternative in results: + alternatives = alternative["alternatives"][0] + transcript_response += " " + str(alternatives["transcript"]) + transcript_confidence += ( + " " + str(alternatives["confidence"]) + ) + end = datetime.now() + ms = (end - start).seconds + if transcript_response != "": + string_to_show = f""" +TRANSCRIPT: +
{transcript_response}
+
+Time Taken: 
{ms} seconds
+Confidence: 
{transcript_confidence}
+                                    """
+                else:
+                    string_to_show = f"
Time Taken
: {ms} seconds\n
No Results Found
"
+                await edrep(message, text=string_to_show, parse_mode='html')
+            else:
+                await edrep(message, text=r["error"])
+            # now, remove the temporary file
+            os.remove(required_file_name)
+    else:
+        await edrep(message, text="`Reply to a voice message`")
+        await asyncio.sleep(3)
+        await message.delete()
diff --git a/nana/modules/vulgar.py b/nana/modules/vulgar.py
index 5d06fa4c..b3be5bd2 100644
--- a/nana/modules/vulgar.py
+++ b/nana/modules/vulgar.py
@@ -4,7 +4,7 @@
 from pyrogram import filters
 from pyrogram.errors import MessageNotModified
 
-from nana import app, Command
+from nana import app, Command, AdminSettings, edrep
 
 __MODULE__ = "Vulgar"
 __HELP__ = """
@@ -20,44 +20,45 @@
 
 vulgar_filter = False
 
-bad_words = ['nigga', 'nigger', 'coon', 'fuck', 'bitch']
+bad_words = ['nigga', 'nigger', 'coon', 'bitch']
+f_word = ['fuck', 'suck']
 
 
 @app.on_message(~filters.regex(r"^\.\w*") & filters.me)
 async def vulgar_f(_client, message):
-    if vulgar_filter:
-        try:
-            txt = None
-            if message.caption:
-                txt = message.caption
-            elif message.text:
-                txt = message.text
-
-            for word in bad_words:
-                txt = re.sub(word, 'bruh', txt, flags=re.IGNORECASE)
-
-            if message.caption:
-                if txt != message.caption:
-                    await message.edit_caption(txt)
-            elif message.text:
-                if txt != message.text:
-                    await message.edit(txt)
-        except MessageNotModified:
-            return
-    else:
+    if not vulgar_filter:
+        return
+    try:
+        txt = None
+        if message.caption:
+            txt = message.caption
+        elif message.text:
+            txt = message.text
+
+        for word in bad_words:
+            txt = re.sub(word, 'bruh', txt, flags=re.IGNORECASE)
+
+        for word in f_word:
+            txt = re.sub(word, 'duck', txt, flags=re.IGNORECASE)
+
+        if message.caption:
+            if txt != message.caption:
+                await message.edit_caption(txt)
+        elif message.text:
+            if txt != message.text:
+                await message.edit(txt)
+    except MessageNotModified:
         return
 
 
-@app.on_message(filters.me & filters.command(["vulgar"], Command))
+@app.on_message(filters.user(AdminSettings) & filters.command("vulgar", Command))
 async def vulgar_trigger(_client, message):
     global vulgar_filter
     if vulgar_filter:
         vulgar_filter = False
-        await message.edit("Message will not be filtered")
-        await sleep(5)
-        await message.delete()
+        await edrep(message, text="Message will not be filtered")
     else:
         vulgar_filter = True
-        await message.edit("Message will be filtered")
-        await sleep(5)
-        await message.delete()
\ No newline at end of file
+        await edrep(message, text="Message will be filtered")
+    await sleep(5)
+    await message.delete()
\ No newline at end of file
diff --git a/nana/modules/weather.py b/nana/modules/weather.py
index b317a4cf..d824238a 100644
--- a/nana/modules/weather.py
+++ b/nana/modules/weather.py
@@ -5,23 +5,23 @@
 import aiohttp
 from pyrogram import filters
 
-from nana import app, Command
+from nana import app, Command, AdminSettings, edrep
 
 __MODULE__ = "Weather"
 __HELP__ = """
 Get current weather in your location
 
 ──「 **Weather** 」──
--> `wttr (location)`
+-> `wtr (location)`
 Get current weather in your location.
 Powered by `wttr.in`
 """
 
 
-@app.on_message(filters.me & filters.command(["wttr"], Command))
+@app.on_message(filters.user(AdminSettings) & filters.command('wttr', Command))
 async def weather(_client, message):
     if len(message.command) == 1:
-        await message.edit("Usage: `wttr Maldives`")
+        await edrep(message, text="Usage: `wttr Maldives`")
         await asyncio.sleep(3)
         await message.delete()
 
@@ -35,10 +35,10 @@ async def weather(_client, message):
                     data = await resp.text()
         except Exception as e:
             print(e)
-            await message.edit("Failed to get the weather forecast")
+            await edrep(message, text="Failed to get the weather forecast")
 
         if 'we processed more than 1M requests today' in data:
-            await message.edit("`Sorry, we cannot process this request today!`")
+            await edrep(message, text="`Sorry, we cannot process this request today!`")
         else:
             weather_data = f"{escape(data.replace('report', 'Report'))}"
-            await message.edit(weather_data, parse_mode='html')
+            await edrep(message, text=weather_data, parse_mode='html')
diff --git a/nana/modules/webss.py b/nana/modules/webss.py
index 9c06927a..7273b8cb 100644
--- a/nana/modules/webss.py
+++ b/nana/modules/webss.py
@@ -1,12 +1,10 @@
 import os
-import shutil
 
-import requests
 from pyrogram import filters
 
-from nana import app, Command, thumbnail_API, screenshotlayer_API
+from nana import app, Command, thumbnail_API, screenshotlayer_API, AdminSettings, edrep
 
-__MODULE__ = "Screenshot Website"
+__MODULE__ = "SS Website"
 __HELP__ = """
 Take a picture of website. You can select one for use this.
 
@@ -22,87 +20,52 @@
 """
 
 
-@app.on_message(filters.me & filters.command(["print"], Command))
-async def ss_web(client, message):
+@app.on_message(filters.user(AdminSettings) & filters.command("print", Command))
+async def print_web(client, message):
     if len(message.text.split()) == 1:
-        await message.edit("Usage: `print web.url`")
+        await edrep(message, text="Usage: `print web.url`")
         return
     if not thumbnail_API:
-        await message.edit("You need to fill thumbnail_API to use this!")
+        await edrep(message, text="You need to fill thumbnail_API to use this!")
         return
-    await message.edit("Please wait...")
     args = message.text.split(None, 1)
     teks = args[1]
-    if "http://" in teks or "https://" in teks:
-        teks = teks
-    else:
-        teks = "http://" + teks
+    teks = teks if "http://" in teks or "https://" in teks else "http://" + teks
     capt = f"Website: `{teks}`"
-
     await client.send_chat_action(message.chat.id, action="upload_photo")
-    r = requests.get("https://api.thumbnail.ws/api/{}/thumbnail/get?url={}&width=1280".format(thumbnail_API, teks),
-                     stream=True
-                     )
-    if r.status_code != 200:
-        await message.edit(r.text, disable_web_page_preview=True)
-        return
-    with open("nana/cache/web.png", "wb") as stk:
-        shutil.copyfileobj(r.raw, stk)
-    await client.send_photo(message.chat.id, photo="nana/cache/web.png", caption=capt,
+    web_photo = f"https://api.thumbnail.ws/api/{thumbnail_API}/thumbnail/get?url={teks}&width=1280"
+    await client.send_photo(message.chat.id, photo=web_photo, caption=capt,
                             reply_to_message_id=message.message_id)
-    os.remove("nana/cache/web.png")
-    await client.send_chat_action(message.chat.id, action="cancel")
-    message.edit(capt)
 
 
-@app.on_message(filters.me & filters.command(["ss"], Command))
+@app.on_message(filters.user(AdminSettings) & filters.command("ss", Command))
 async def ss_web(client, message):
     if len(message.text.split()) == 1:
-        await message.edit("Usage: `print web.url`")
+        await edrep(message, text="Usage: `print web.url`")
         return
     if not screenshotlayer_API:
-        await message.edit("You need to fill screenshotlayer_API to use this!")
+        await edrep(message, text="You need to fill screenshotlayer_API to use this!")
         return
-    await message.edit("Please wait...")
     args = message.text.split(None, 1)
     teks = args[1]
     full = False
-    if len(message.text.split()) >= 3:
-        if message.text.split(None, 2)[2] == "full":
-            full = True
+    if (
+        len(message.text.split()) >= 3
+        and message.text.split(None, 2)[2] == "full"
+    ):
+        full = True
 
-    if "http://" in teks or "https://" in teks:
-        teks = teks
-    else:
-        teks = "http://" + teks
-    capt = "Website: `{}`".format(teks)
+    teks = teks if "http://" in teks or "https://" in teks else "http://" + teks
+    capt = f"Website: `{teks}`"
 
     await client.send_chat_action(message.chat.id, action="upload_photo")
     if full:
-        r = requests.get(
-            f"http://api.screenshotlayer.com/api/capture?access_key={screenshotlayer_API}&url={teks}&fullpage=1",
-            stream=True)
+        r = f"http://api.screenshotlayer.com/api/capture?access_key={screenshotlayer_API}&url={teks}&fullpage=1"
     else:
-        r = requests.get(
-            f"http://api.screenshotlayer.com/api/capture?access_key={screenshotlayer_API}&url={teks}&fullpage=0",
-            stream=True)
-
-    try:
-        catcherror = r.json()
-        if not catcherror['success']:
-            await message.edit(r.json(), disable_web_page_preview=True)
-            return
-    except Exception as err:
-        print(err)
-        pass
-
-    with open("nana/cache/web.png", "wb") as stk:
-        for chunk in r:
-            stk.write(chunk)
+        r = f"http://api.screenshotlayer.com/api/capture?access_key={screenshotlayer_API}&url={teks}&fullpage=0"
 
-    await client.send_document(message.chat.id, document="nana/cache/web.png", caption=capt,
+    await client.send_photo(message.chat.id, photo=r, caption=capt,
                                reply_to_message_id=message.message_id
                                )
     os.remove("nana/cache/web.png")
     await client.send_chat_action(message.chat.id, action="cancel")
-    await message.edit(capt)
diff --git a/nana/modules/whois.py b/nana/modules/whois.py
deleted file mode 100644
index fbd1ab1c..00000000
--- a/nana/modules/whois.py
+++ /dev/null
@@ -1,149 +0,0 @@
-from datetime import datetime
-from time import sleep
-
-from pyrogram import filters
-from pyrogram.errors import PeerIdInvalid
-from pyrogram.raw import functions
-from pyrogram.types import User
-
-from nana import app, Command
-from nana.helpers.PyroHelpers import ReplyCheck
-
-__MODULE__ = "Whois"
-__HELP__ = """
-──「 **Whois** 」──
--> `whois` @username
--> `whois` "reply to a text"
-To find information about a person.
-
-"""
-
-WHOIS = (
-    "**WHO IS \"{full_name}\"?**\n"
-    "[Link to profile](tg://user?id={user_id})\n"
-    "════════════════\n"
-    "UserID: `{user_id}`\n"
-    "First Name: `{first_name}`\n"
-    "Last Name: `{last_name}`\n"
-    "Username: `{username}`\n"
-    "Last Online: `{last_online}`\n"
-    "Common Groups: `{common_groups}`\n"
-    "════════════════\n"
-    "Bio:\n{bio}")
-
-WHOIS_PIC = (
-    "**WHO IS \"{full_name}\"?**\n"
-    "[Link to profile](tg://user?id={user_id})\n"
-    "════════════════\n"
-    "UserID: `{user_id}`\n"
-    "First Name: `{first_name}`\n"
-    "Last Name: `{last_name}`\n"
-    "Username: `{username}`\n"
-    "Last Online: `{last_online}`\n"
-    "Common Groups: `{common_groups}`\n"
-    "════════════════\n"
-    "Profile Pics: `{profile_pics}`\n"
-    "Last Updated: `{profile_pic_update}`\n"
-    "════════════════\n"
-    "Bio:\n{bio}")
-
-
-def LastOnline(user: User):
-    if user.is_bot:
-        return ""
-    elif user.status == 'recently':
-        return "Recently"
-    elif user.status == 'within_week':
-        return "Within the last week"
-    elif user.status == 'within_month':
-        return "Within the last month"
-    elif user.status == 'long_time_ago':
-        return "A long time ago :("
-    elif user.status == 'online':
-        return "Currently Online"
-    elif user.status == 'offline':
-        return datetime.fromtimestamp(user.last_online_date).strftime("%a, %d %b %Y, %H:%M:%S")
-
-
-async def GetCommon(client, get_user):
-    common = await client.send(
-        functions.messages.GetCommonChats(
-            user_id=await client.resolve_peer(get_user),
-            max_id=0,
-            limit=0))
-    return common
-
-
-def FullName(user: User):
-    return user.first_name + " " + user.last_name if user.last_name else user.first_name
-
-
-def ProfilePicUpdate(user_pic):
-    return datetime.fromtimestamp(user_pic[0].date).strftime("%d.%m.%Y, %H:%M:%S")
-
-
-@app.on_message(filters.me & filters.command(["whois"], Command))
-async def whois(client, message):
-    cmd = message.command
-    if not message.reply_to_message and len(cmd) == 1:
-        get_user = message.from_user.id
-    elif message.reply_to_message and len(cmd) == 1:
-        get_user = message.reply_to_message.from_user.id
-    elif len(cmd) > 1:
-        get_user = cmd[1]
-        try:
-            get_user = int(cmd[1])
-        except ValueError:
-            pass
-    try:
-        user = await client.get_users(get_user)
-    except PeerIdInvalid:
-        await message.edit("I don't know that User.")
-        sleep(2)
-        await message.delete()
-        return
-    desc = await client.get_chat(get_user)
-    desc = desc.description
-    user_pic = await client.get_profile_photos(user.id)
-    pic_count = await client.get_profile_photos_count(user.id)
-    common = await GetCommon(client, user.id)
-
-    if not user.photo:
-        await message.edit(
-            WHOIS.format(
-                full_name=FullName(user),
-                user_id=user.id,
-                first_name=user.first_name,
-                last_name=user.last_name if user.last_name else "",
-                username=user.username if user.username else "",
-                last_online=LastOnline(user),
-                common_groups=len(common.chats),
-                bio=desc if desc else "`No bio set up.`"),
-            disable_web_page_preview=True)
-    elif user.photo:
-        await client.send_photo(
-            message.chat.id,
-            user_pic[0].file_id,
-            caption=WHOIS_PIC.format(
-                full_name=FullName(user),
-                user_id=user.id,
-                first_name=user.first_name,
-                last_name=user.last_name if user.last_name else "",
-                username=user.username if user.username else "",
-                last_online=LastOnline(user),
-                profile_pics=pic_count,
-                common_groups=len(common.chats),
-                bio=desc if desc else "`No bio set up.`",
-                profile_pic_update=ProfilePicUpdate(user_pic)),
-            reply_to_message_id=ReplyCheck(message),
-            file_ref=user_pic[0].file_ref,
-        )
-        await message.delete()
-
-
-# add_command_help(
-#     'whois', [
-#         ['.whois', 'Finds out who the person is. Reply to message sent by the person'
-#                    'you want information from and send the command. Without the dot also works.']
-#     ]
-# )
\ No newline at end of file
diff --git a/nana/modules/youtube.py b/nana/modules/youtube.py
index 7d89c4c7..4b5d299c 100644
--- a/nana/modules/youtube.py
+++ b/nana/modules/youtube.py
@@ -8,24 +8,17 @@
 
 import pafy
 import requests
-from bs4 import BeautifulSoup
 from pyrogram import filters
 from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
 from pytube import YouTube
 
-from nana import app, setbot, Command
+from nana import app, setbot, Command, AdminSettings, edrep
 from nana.helpers.parser import escape_markdown
 from nana.modules.downloads import download_url
 
 __MODULE__ = "YouTube"
 __HELP__ = """
-Search, download, convert music from youtube!
-Enjoy~
-
-──「 **Search video** 」──
--> `youtube (text)`
--> `yt (text)`
-Give text as args for search from youtube, will send result more than 10 depending on yt page.
+download, convert music from youtube!
 
 ──「 **Download video** 」──
 -> `ytdl (url) (resolution*)`
@@ -33,95 +26,55 @@
 
 ──「 **Convert to music** 」──
 -> `ytmusic (url)`
--> `ytaudio (url)`
 Download youtube music, and then send to tg as music.
 """
 
 
-@app.on_message(filters.user("self") & filters.command(["youtube", "yt"], Command))
-async def youtube_search(_client, message):
-	args = message.text.split(None, 1)
-	if len(args) == 1:
-		await message.edit("Write any args here!")
-		return
-	teks = args[1]
-	responce = requests.get('https://www.youtube.com/results?search_query=' + teks.replace(" ", "%20"))
-	soup = BeautifulSoup(responce.content, "html.parser")
-	divs = soup.find_all("div", {"class": "yt-lockup"})
-	yutub = "Results of {}\n".format(teks)
-	nomor = 0
-	for i in divs:
-		title = i.find('h3', {'class': "yt-lockup-title"}).a.get('title')
-		url = i.find('h3', {'class': "yt-lockup-title"}).a.get('href')
-		vidtime = i.find("span", {"class": "video-time"})
-		if vidtime:
-			vidtime = str("(" + vidtime.text + ")")
-		else:
-			vidtime = ""
-		nomor += 1
-		yutub += '{}. {} {}\n'.format(nomor, "https://www.youtube.com" + url, title, vidtime)
-	await message.edit(yutub, disable_web_page_preview=True, parse_mode="html")
-
-
-@app.on_message(filters.user("self") & filters.command(["ytdl"], Command))
+@app.on_message(filters.user(AdminSettings) & filters.command("ytdl", Command))
 async def youtube_download(_client, message):
 	args = message.text.split(None, 2)
-	await message.edit("Checking")
+	await edrep(message, text="Checking")
 	if len(args) == 1:
-		await message.edit("Write any args here!")
+		await edrep(message, text="Write any args here!")
 		return
 	try:
 		yt = YouTube(args[1])
 	except ValueError:
-		await message.edit("Invalid URL!")
+		await edrep(message, text="Invalid URL!")
 		return
 
 	if len(args) == 2:
 		link = args[1]
 		text = "🎬 **Title:** [{}]({})\n".format(escape_markdown(yt.title), link)
-		status = "**Downloading video...**\n"
-		await message.edit(status + text, disable_web_page_preview=True)
 		YouTube(link).streams.first().download('nana/downloads', filename="tempvid")
-		status = "**Uploading File To Telegram...**\n"
-		await message.edit(status + text, disable_web_page_preview=True)
 		await app.send_video(message.chat.id, video="nana/downloads/tempvid.mp4")
-		status = "**Removing Temp File...**"
-		await message.edit(status)
 		os.remove('nana/downloads/tempvid.mp4')
-		status = "** Done ✔️✔️**\n"
-		await message.edit(status + text, disable_web_page_preview=True)
+		await edrep(message, text=text, disable_web_page_preview=True)
 
 		return
 	if len(args) == 3:
 		link = args[1]
 		reso = args[2]
 		text = "🎬 **Title:** [{}]({})\n".format(escape_markdown(yt.title), link)
-		status = "**Downloading video...**\n"
-		await message.edit(status + text, disable_web_page_preview=True)
 		stream = yt.streams.filter(file_extension='mp4').filter(resolution="{}".format(reso)).first()
 		stream.download('nana/downloads', filename="tempvid")
-		status = "**Uploading File To Telegram...**\n"
-		await message.edit(status + text, disable_web_page_preview=True)
 		await app.send_video(message.chat.id, video="nana/downloads/tempvid.mp4")
-		status = "**Removing Temp File...**"
-		await message.edit(status)
 		os.remove('nana/downloads/tempvid.mp4')
-		status = "**Done ✔️✔️**\n"
-		await message.edit(status + text, disable_web_page_preview=True)
+		await edrep(message, text=text, disable_web_page_preview=True)
 		return
 
 
-@app.on_message(filters.user("self") & filters.command(["ytmusic", "ytaudio"], Command))
+@app.on_message(filters.user(AdminSettings) & filters.command("ytmusic", Command))
 async def youtube_music(_client, message):
 	args = message.text.split(None, 1)
 	if len(args) == 1:
-		await message.edit("Send URL here!")
+		await edrep(message, text="Send URL here!")
 		return
 	teks = args[1]
 	try:
 		video = pafy.new(teks)
 	except ValueError:
-		await message.edit("Invaild URL!")
+		await edrep(message, text="Invaild URL!")
 		return
 	try:
 		audios = [audio for audio in video.audiostreams]
@@ -136,25 +89,23 @@ async def youtube_music(_client, message):
 		origtitle = re.sub(r'[\\/*?:"<>|\[\]]', "", str(music.title + "." + music._extension))
 		musictitle = re.sub(r'[\\/*?:"<>|\[\]]', "", str(music.title))
 		musicdate = video._ydl_info['upload_date'][:4]
-		titletext = "**Downloading music...**\n"
-		await message.edit(titletext + text, disable_web_page_preview=False)
-		r = requests.get("https://i.ytimg.com/vi/{}/maxresdefault.jpg".format(video.videoid), stream=True)
+		r = requests.get(f"https://i.ytimg.com/vi/{video.videoid}/maxresdefault.jpg", stream=True)
+		if r.status_code != 200:
+			r = requests.get(f"https://i.ytimg.com/vi/{video.videoid}/hqdefault.jpg", stream=True)
+		if r.status_code != 200:
+			r = requests.get(f"https://i.ytimg.com/vi/{video.videoid}/sddefault.jpg", stream=True)
 		if r.status_code != 200:
-			r = requests.get("https://i.ytimg.com/vi/{}/hqdefault.jpg".format(video.videoid), stream=True)
-			if r.status_code != 200:
-				r = requests.get("https://i.ytimg.com/vi/{}/sddefault.jpg".format(video.videoid), stream=True)
-				if r.status_code != 200:
-					r = requests.get("https://i.ytimg.com/vi/{}/mqdefault.jpg".format(video.videoid), stream=True)
-					if r.status_code != 200:
-						r = requests.get("https://i.ytimg.com/vi/{}/default.jpg".format(video.videoid), stream=True)
-						if r.status_code != 200:
-							avthumb = False
+			r = requests.get(f"https://i.ytimg.com/vi/{video.videoid}/mqdefault.jpg", stream=True)
+		if r.status_code != 200:
+			r = requests.get(f"https://i.ytimg.com/vi/{video.videoid}/default.jpg", stream=True)
+		if r.status_code != 200:
+			avthumb = False
 		if r.status_code == 200:
 			avthumb = True
 			with open("nana/cache/thumb.jpg", "wb") as stk:
 				shutil.copyfileobj(r.raw, stk)
 		try:
-			os.remove("nana/downloads/{}".format(origtitle))
+			os.remove(f"nana/downloads/{origtitle}")
 		except FileNotFoundError:
 			pass
 		# music.download(filepath="nana/downloads/{}".format(origtitle))
@@ -163,14 +114,12 @@ async def youtube_music(_client, message):
 		else:
 			download = await download_url(music.url, origtitle)
 		if download == "Failed to download file\nInvaild file name!":
-			return await message.edit(download)
-		titletext = "**Converting music...**\n"
-		await message.edit(titletext + text, disable_web_page_preview=False)
+			return await edrep(message, text=download)
 		try:
 			subprocess.Popen("ffmpeg", stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 		except Exception as err:
 			if "The system cannot find the file specified" in str(err) or "No such file or directory" in str(err):
-				await message.edit("You need to install ffmpeg first!\nCheck your assistant for more information!")
+				await edrep(message, text="You need to install ffmpeg first!\nCheck your assistant for more information!")
 				await setbot.send_message(message.from_user.id,
 										"Hello 🙂\nYou need to install ffmpeg to make audio works better, here is guide how to install it:\n\n**If you're using linux**, go to your terminal, type:\n`sudo apt install ffmpeg`\n\n**If you're using Windows**, download ffmpeg here:\n`https://ffmpeg.zeranoe.com/builds/`\nAnd then extract (if was archive), and place ffmpeg.exe to workdir (in current dir)\n\n**If you're using heroku**, type this in your workdir:\n`heroku buildpacks:add https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git`\nOr if you not using heroku term, follow this guide:\n1. Go to heroku.com\n2. Go to your app in heroku\n3. Change tabs/click Settings, then search for Buildpacks text\n4. Click button Add build pack, then type `https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest`\n5. Click Save changes, and you need to rebuild your heroku app to take changes!\n\nNeed help?\nGo @nanabotsupport and ask there")
 				return
@@ -184,13 +133,11 @@ async def youtube_music(_client, message):
 			os.remove("nana/downloads/{}".format(origtitle))
 		except FileNotFoundError:
 			pass
-		titletext = "**Uploading...**\n"
-		await message.edit(titletext + text, disable_web_page_preview=False)
 		getprev = requests.get(video.thumb, stream=True)
 		with open("nana/cache/prev.jpg", "wb") as stk:
 			shutil.copyfileobj(getprev.raw, stk)
-		await app.send_audio(message.chat.id, audio="nana/downloads/{}.mp3".format(musictitle),
-							thumb="nana/cache/prev.jpg", title=music.title, caption="🕦 `{}`".format(video.duration),
+		await app.send_audio(message.chat.id, audio=f"nana/downloads/{musictitle}.mp3",
+							thumb="nana/cache/prev.jpg", title=music.title, caption=f"🕦 `{video.duration}`",
 							reply_to_message_id=message.message_id
 						)
 		try:
@@ -202,10 +149,10 @@ async def youtube_music(_client, message):
 		except FileNotFoundError:
 			pass
 		titletext = "**Done! 🤗**\n"
-		await message.edit(titletext + text, disable_web_page_preview=False)
+		await edrep(message, text=titletext + text, disable_web_page_preview=True)
 	except Exception as err:
 		if "command not found" in str(err) or "is not recognized" in str(err):
-			await message.edit("You need to install ffmpeg first!\nCheck your assistant for more information!")
+			await edrep(message, text="You need to install ffmpeg first!\nCheck your assistant for more information!")
 			await setbot.send_message(message.from_user.id,
 									"Hello 🙂\nYou need to install ffmpeg to make audio works better, here is guide "
 									"how to install it:\n\n**If you're using linux**, go to your terminal, "
@@ -219,11 +166,11 @@ async def youtube_music(_client, message):
 									"text\n4. Click button Add build pack, then type "
 									"`https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest`\n5. Click Save "
 									"changes, and you need to rebuild your heroku app to take changes!\n\nNeed "
-									"help?\nGo @AyraSupport and ask there")
+									"help?\nGo to @NanaBotSupport and ask there")
 			return
 		exc_type, exc_obj, exc_tb = sys.exc_info()
 		errors = traceback.format_exception(etype=exc_type, value=exc_obj, tb=exc_tb)
-		await message.edit("**An error has accured!**\nCheck your assistant for more information!")
+		await edrep(message, text="**An error has accured!**\nCheck your assistant for more information!")
 		button = InlineKeyboardMarkup([[InlineKeyboardButton("🐞 Report bugs", callback_data="report_errors")]])
 		await setbot.send_message(message.from_user.id, "**An error has accured!**\n```{}```".format("".join(errors)),
 								reply_markup=button)
diff --git a/nana/modules/yts.py b/nana/modules/yts.py
index a9ed65cd..c74ade28 100644
--- a/nana/modules/yts.py
+++ b/nana/modules/yts.py
@@ -5,28 +5,51 @@
 import asyncio
 import os
 import re
+from urllib.parse import quote as urlencode
 
+import aiohttp
+import htmlement
 import requests
 from pyrogram import filters
 
-from nana import app, Command
+from nana import app, Command, setbot, AdminSettings, edrep
+from nana.helpers.aiohttp_helper import AioHttp
 
 __MODULE__ = "YTS"
 __HELP__ = """
-This module is to send .torrent files into a chat.
+This module is to send .torrent files using assistant.
 
-──「 **Export chats** 」──
+──「 **YTS downloads** 」──
 -> `yts`
-Sends torrent file into the chat.
+Sends torrent file using assistant.
+usage: `yts [Movie name]`
+Example: `yts lion king`
 
-usage: `yts [Movie name] [-limit] [-quality]`
-Example: `yts lion king -l10 -q1080p`
+──「 **Magnet Links** 」──
+-> `ytsearch (movie name)`
+Sends magnetlink using assistant.
+
+──「 **Sakubei** 」──
+-> `sb (anime name)`
+return torrent link for anime or hentai.
 
 """
 
 
-@app.on_message(filters.me & filters.command(["yts"], Command))
-async def yts(client, message):
+async def sukebei_search(query):
+    async with aiohttp.ClientSession() as session:
+        async with session.get(f'https://sukebei.nyaa.si/?page=rss&c=0_0&f=0&q={urlencode(query)}') as resp:
+            root = htmlement.fromstring(await resp.text())
+    results = []
+    for i in root.iterfind('.//channel/item'):
+        title = i.find('title').text
+        link = i.find('link').tail
+        results.append((title, link))
+    return results
+
+
+@app.on_message(filters.user(AdminSettings) & filters.command("yts", Command))
+async def yts(_client, message):
     qual = None
     max_limit = 5
     input_ = message.command[1]
@@ -43,7 +66,7 @@ async def yts(client, message):
     elif get_limit.search(input_):
         max_limit = int(get_limit.search(input_).group().strip('-l'))
     if len(input_) == 0:
-        await message.edit("No Input")
+        await edrep(message, text="No Input")
         await asyncio.sleep(3)
         await message.delete()
         return
@@ -51,17 +74,17 @@ async def yts(client, message):
     resp = requests.get(URL.format(query=_movie, limit=max_limit))
     datas = resp.json()
     if datas['status'] != "ok":
-        await message.edit("Wrong Status")
+        await edrep(message, text="Wrong Status")
         await asyncio.sleep(3)
         await message.delete()
         return
     if datas['data']['movie_count'] == 0 or len(datas['data']) == 3:
-        await message.edit(f"{_movie} Not Found!")
+        await edrep(message, text=f"{_movie} Not Found!")
         await asyncio.sleep(3)
         await message.delete()
         return
     _matches = datas['data']['movie_count']
-    await message.edit(f"{_matches} Matches Found!, Sending {len(datas['data']['movies'])}.")
+    await edrep(message, text=f"`{_matches} Matches Found!, Asisstant sending {len(datas['data']['movies'])}.`")
     await asyncio.sleep(5)
     await message.delete()
     for data in datas['data']['movies']:
@@ -69,7 +92,7 @@ async def yts(client, message):
         _rating = data['rating']
         _language = data['language']
         _torrents = data['torrents']
-        def_quality = "720p"
+        def_quality = "1080p"
         _qualities = []
         for i in _torrents:
             _qualities.append(i['quality'])
@@ -90,14 +113,91 @@ async def yts(client, message):
             files = files.replace('/', '\\')
             with open(files, 'wb') as f:
                 f.write(requests.get(_torrents[_qualities.index(def_quality)]['url']).content)
-            await client.send_document(chat_id=message.chat.id,
-                                       document=files,
-                                       caption=capts,
-                                       disable_notification=True)
+            await setbot.send_document(message.from_user.id,
+            files,
+            caption=capts
+            )
             os.remove(files)
         else:
-            message.edit("Not Found")
-            await asyncio.sleep(3)
-            await message.delete()
+            await edrep(message, text="Not Found")
             return
     return
+
+
+@app.on_message(filters.user(AdminSettings) & filters.command("ytsearch", Command))
+async def yts_search(_client, message):
+    cmd = message.command
+    query = ""
+    if len(cmd) > 1:
+        query = " ".join(cmd[1:])
+    elif message.reply_to_message and len(cmd) == 1:
+        query = message.reply_to_message.text
+    elif len(cmd) == 1:
+        await edrep(message, text="`No search query given for torrent search`")
+        await asyncio.sleep(2)
+        await message.delete()
+        return
+    rep = ""
+    await edrep(message, text="`please check assistant for magnet urls`")
+    count = 0
+    try:
+        torrents = await AioHttp().get_json(f"https://sjprojectsapi.herokuapp.com/torrent/?query={query}")
+        for torrent in torrents:
+            count += 1
+            if count % 10 == 0:
+                break
+            title = torrent['name']
+            size = torrent['size']
+            seeders = torrent['seeder']
+            leechers = torrent['leecher']
+            magnet = torrent['magnet']
+            try:
+                rep = f"\n\n{title}\n"
+                rep +=f"Size: {size}\n"
+                rep +=f"Seeders: {seeders}\n"
+                rep +=f"Leechers: {leechers}\n"
+                rep +=f"{magnet}"
+                await setbot.send_message(message.from_user.id, rep, parse_mode="html")
+            except Exception as e:
+                print(e)
+        if rep == "":
+            await edrep(message, text=f"No torrents found: __{query}__")
+    except Exception as e:
+        print(e)
+        await edrep(message, text="API is Down!\nTry again later")
+        await asyncio.sleep(2)
+        await message.delete()
+    await message.delete()
+
+
+@app.on_message(filters.user(AdminSettings) & filters.command("sb", Command))
+async def saku_bei(client, message):
+    cmd = message.command
+    query = ""
+    if len(cmd) > 1:
+        query = " ".join(cmd[1:])
+    elif message.reply_to_message and len(cmd) == 1:
+        query = message.reply_to_message.text
+    elif len(cmd) == 1:
+        await edrep(message, text="`cant sakubei the void.`")
+        await asyncio.sleep(2)
+        await message.delete()
+        return
+    try:
+        results = await sukebei_search(query)
+    except Exception as e:
+        print(e)
+        await edrep(message, text="`something went wrong please check logs!")
+        await asyncio.sleep(2)
+        await message.delete()
+    await edrep(message, text="`check assistant for magnet links`")
+    await asyncio.sleep(7)
+    await message.delete()
+    count = 0
+    for i, j in results:
+        count += 1
+        if count % 10 == 0:
+            break
+        rep = f'Sakubei Torrent:\n{i}: {j}'
+        await setbot.send_message(message.from_user.id, rep)
+    
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 6eeda00d..ccc51e31 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -36,4 +36,10 @@ PTable
 emoji==0.5.4
 beautifulsoup4==4.9.1
 pathlib==1.0.1
-typing==3.7.4.1
\ No newline at end of file
+typing==3.7.4.1
+aiofiles
+reportlab
+svglib
+spamwatch
+timeago
+htmlement
\ No newline at end of file