├── run.sh ├── Procfile ├── vt ├── __init__.py ├── README.md ├── core │ ├── module_class.py │ └── funtions.py └── vt.py ├── requirements.txt ├── docker-compose.yml ├── Dockerfile ├── README.md ├── telegram ├── botfunctions.py └── main.py └── .gitignore /run.sh: -------------------------------------------------------------------------------- 1 | python3 telegram/main.py -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: python3 telegram/main.py -------------------------------------------------------------------------------- /vt/__init__.py: -------------------------------------------------------------------------------- 1 | from vt.vt import Virustotal -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.28.0 2 | rich==12.4.4 3 | pyrogram 4 | tgcrypto 5 | pydantic 6 | free-proxy 7 | telegraph 8 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.9" 2 | services: 3 | workerdisk: 4 | build: . 5 | environment: 6 | - ID=${ID} 7 | - HASH=${HASH} 8 | - TOKEN=${TOKEN} -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9 2 | 3 | WORKDIR /app 4 | 5 | COPY requirements.txt /app/ 6 | 7 | RUN pip3 install -r requirements.txt 8 | 9 | COPY . /app 10 | 11 | CMD ["bash","run.sh"] -------------------------------------------------------------------------------- /vt/README.md: -------------------------------------------------------------------------------- 1 | # Virustotal-scrapper 2 | 3 | To upload file to virustotal and get the results without API 4 | 5 | ## Installation 6 | 7 | ``` 8 | pip3 install https://github.com/Brijeshkrishna/virustotal-scrapper 9 | ``` 10 | # Usage 11 | ### Import module 12 | 13 | ```python 14 | from vt import Visustotal 15 | ``` 16 | 17 | ### File upload 18 | 19 | ```python 20 | vt= Visustotal() 21 | vt.upload_file(file name) 22 | ``` 23 | returns a SHA256 Hash ( file id ) using that you can check the details of the file 24 | 25 | ``` 26 | https://www.virustotal.com/gui/file/file-hash 27 | ``` 28 | 29 | ## Url upload 30 | ```python 31 | vt.upload_url(url) 32 | ``` 33 | returns a id , using that you can check the details of the website 34 | 35 | ``` 36 | https://www.virustotal.com/gui/url/id 37 | ``` 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VirusTotal Bot 2 | 3 | a Telegram Bot to check file in [VirusTotal](http://virustotal.com/) with over 70 different antiviruses. 4 | 5 | Inspired from https://github.com/Brijeshkrishna/virustotal-scrapper 6 | 7 | --- 8 | 9 | ## Variables 10 | 11 | - `HASH` Your API Hash from my.telegram.org 12 | - `ID` Your API ID from my.telegram.org 13 | - `TOKEN` Your bot token from @BotFather 14 | 15 | --- 16 | 17 | # Usage 18 | 19 | You can send a file up to **650 MB** in size to the bot or forward it from another chat, and it will check file in **[VirusTotal](http://virustotal.com/)** with over **70** different antiviruses to get scan results and you will receive a detailed analysis of it. 20 | 21 | --- 22 | 23 | # Deploy 24 | 25 | You can use the bot locally by running 'main.py' in 'telegram' folder or deploy using Procfile, Dokerfile, docker-compose.yml 26 | -------------------------------------------------------------------------------- /vt/core/module_class.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Dict, List, Optional 3 | from pydantic import BaseModel 4 | 5 | 6 | class AnalysisResults(BaseModel): 7 | engine_name: str 8 | engine_version: Optional[str] 9 | result: Optional[str] 10 | category:str 11 | 12 | 13 | class AnalysisStats(BaseModel): 14 | harmless: int 15 | type_unsupported: int 16 | suspicious: int 17 | confirmed_timeout: int 18 | timeout: int 19 | failure: int 20 | malicious: int 21 | undetected: int 22 | 23 | 24 | class FileInfo(BaseModel): 25 | filename: str 26 | id: str 27 | magic:Optional[str] 28 | type_description: str 29 | file_type_info: Dict[str, str] 30 | first_submission_date: datetime 31 | last_modification_date: datetime 32 | times_submitted: int 33 | total_votes: Dict[str, int] 34 | size: int 35 | file_extension: str 36 | last_submission_date: datetime 37 | results: List[AnalysisResults] 38 | tags: List[str] 39 | last_analysis_date: datetime 40 | list_hash: Dict[str, Optional[str]] 41 | analysis_stats: AnalysisStats 42 | file_type: str 43 | 44 | 45 | -------------------------------------------------------------------------------- /telegram/botfunctions.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append(".") 3 | from vt import Virustotal 4 | 5 | vtapi = Virustotal() 6 | 7 | def uploadfile(file): 8 | hash = vtapi.upload_file(file) 9 | return hash 10 | 11 | def counttests(obj): 12 | dcount = 0 13 | ucount = 0 14 | ncount = 0 15 | detected = [] 16 | undetected = [] 17 | notsupported = [] 18 | dresult = [] 19 | 20 | for ele in obj.results: 21 | if ele.category == "malicious": 22 | dcount += 1 23 | detected.append(ele.engine_name) 24 | dresult.append(ele.result) 25 | 26 | elif ele.category == "undetected": 27 | ucount += 1 28 | undetected.append(ele.engine_name) 29 | 30 | else: 31 | ncount += 1 32 | notsupported.append(ele.engine_name) 33 | 34 | return dcount,ucount,ncount,detected,undetected,notsupported,dresult 35 | 36 | def cleaninfo(hash): 37 | obj = vtapi.file_info(hash) 38 | if obj == None: 39 | print("File does not Exist") 40 | return None,None,None, None 41 | 42 | D,U,N,DL,UL,NL,DR = counttests(obj) 43 | 44 | fronttext = f'🧬 **Detections**: __{D} / {D+U}__\ 45 | \n\n🔖 **File Name**: __{obj.filename}__\ 46 | \n🔒 **File Type**: __{obj.type_description} ({obj.file_type_info["file_type"]})__\ 47 | \n📁 **File Size**: __{pow(2,-20)*obj.size:.2f} MB__\ 48 | \n⏱ **Times Submited**: __{obj.times_submitted}__\ 49 | \n\n🔬 **First Analysis**\n• __{obj.first_submission_date}__\ 50 | \n🔭 **Last Analysis**\n• __{obj.last_modification_date}__\ 51 | \n\n🎉 **Magic**\n• __{obj.magic}__' 52 | #\n\n⚜️ [Link to VirusTotal](https://virustotal.com/gui/file/{hash})' 53 | 54 | testtext = '**❌ - Malicious\n✅ - UnDetected\n⚠️ - Not Suported**\n➖➖➖➖➖➖➖➖➖➖\n' 55 | for ele in DL: 56 | testtext = f'{testtext}❌ {ele}\n' 57 | for ele in UL: 58 | testtext = f'{testtext}✅ {ele}\n' 59 | for ele in NL: 60 | testtext = f'{testtext}⚠️ {ele}\n' 61 | 62 | signatures = '' 63 | for i in range(len(DR)): 64 | signatures = f'{signatures}❌ {DL[i]}\ 65 | \n╰ {DR[i]}\n' 66 | 67 | if D == 0: 68 | signatures = "✅ Your File is Safe" 69 | 70 | link = f'https://virustotal.com/gui/file/{hash}' 71 | return fronttext,testtext,signatures,link 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | build/ 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | testing/ -------------------------------------------------------------------------------- /vt/core/funtions.py: -------------------------------------------------------------------------------- 1 | import random 2 | import json 3 | import string 4 | from .module_class import * 5 | 6 | 7 | def random_header_id(): 8 | return ("".join(random.choice(string.ascii_letters) for _ in range(59))) + "==" 9 | 10 | 11 | def file_info_fill(data: json,raw=0): 12 | if raw: 13 | return data 14 | 15 | data = data["data"] 16 | file_type_info = {} 17 | total_votes = {} 18 | last_analysis_results = [] 19 | tags = [] 20 | 21 | file_type = data["type"] 22 | id = data["id"] 23 | attributes = data["attributes"] 24 | type_description = attributes["type_description"] 25 | for i in attributes["trid"]: 26 | file_type_info.update( 27 | {"file_type": i["file_type"], "probability": i["probability"]} 28 | ) 29 | try : 30 | filename = attributes["names"][0] 31 | except: 32 | filename="" 33 | 34 | last_modification_date = datetime.fromtimestamp( 35 | attributes["last_modification_date"] 36 | ) 37 | times_submitted = attributes["times_submitted"] 38 | 39 | total_votes.update( 40 | { 41 | "harmless": attributes["total_votes"]["harmless"], 42 | "malicious": attributes["total_votes"]["malicious"], 43 | } 44 | ) 45 | size = attributes["size"] 46 | file_extension = attributes["type_extension"] 47 | last_submission_date = datetime.fromtimestamp(attributes["last_modification_date"]) 48 | 49 | for _, value in attributes["last_analysis_results"].items(): 50 | 51 | temp = { 52 | "engine_name": value["engine_name"], 53 | "engine_version": value["engine_version"], 54 | "result": value["result"], 55 | "category":value["category"] 56 | } 57 | last_analysis_results.append(AnalysisResults(**temp)) 58 | 59 | list_hash = { 60 | "sha256": attributes["sha256"], 61 | "md5": attributes["md5"], 62 | "sha1": attributes["sha1"], 63 | "vhash": attributes["vhash"] if "vhash" in attributes else None, 64 | "ssdeep": attributes["ssdeep"] if "ssdeep" in attributes else None, 65 | "tlsh": attributes["tlsh"] if "tlsh" in attributes else None, 66 | } 67 | magic= attributes["magic"] if "magic" in attributes else None 68 | first_submission_date = datetime.fromtimestamp(attributes["first_submission_date"]) 69 | for i in attributes["tags"]: 70 | tags.append(i) 71 | last_analysis_date = datetime.fromtimestamp(attributes["last_analysis_date"]) 72 | 73 | attributes = attributes["last_analysis_stats"] 74 | temp = { 75 | "harmless": attributes["harmless"], 76 | "type_unsupported": attributes["type-unsupported"], 77 | "suspicious": attributes["suspicious"], 78 | "confirmed_timeout": attributes["confirmed-timeout"], 79 | "timeout": attributes["timeout"], 80 | "failure": attributes["failure"], 81 | "malicious": attributes["malicious"], 82 | "undetected": attributes["undetected"], 83 | } 84 | last_analysis_stats = AnalysisStats(**temp) 85 | 86 | temp = { 87 | "filename": filename, 88 | "id": id, 89 | "type_description": type_description, 90 | "file_type_info": file_type_info, 91 | "first_submission_date": first_submission_date, 92 | "last_modification_date": last_modification_date, 93 | "times_submitted": times_submitted, 94 | "total_votes": total_votes, 95 | "size": size, 96 | "file_extension": file_extension, 97 | "last_submission_date": last_submission_date, 98 | "results": last_analysis_results, 99 | "tags": tags, 100 | "last_analysis_date": last_analysis_date, 101 | "list_hash": list_hash, 102 | "analysis_stats": last_analysis_stats, 103 | "file_type": file_type, 104 | "magic": magic, 105 | } 106 | 107 | return FileInfo(**temp) 108 | -------------------------------------------------------------------------------- /vt/vt.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import hashlib 3 | from vt.core.funtions import * 4 | import urllib.parse 5 | from fp.fp import FreeProxy 6 | 7 | class Virustotal: 8 | def __init__(self): 9 | self.session = requests.Session() 10 | proxy = FreeProxy().get() 11 | self.session.proxies = {proxy} 12 | self.update_headers() 13 | 14 | 15 | def update_headers(self): 16 | self.x_vt_header = random_header_id() 17 | self.basic_header = { 18 | "X-Tool": "vt-ui-main", 19 | "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36", 20 | "content-type": "application/json", 21 | "x-app-version": "v1x98x0", 22 | "accept": "application/json", 23 | "Referer": "https://www.virustotal.com/", 24 | "Accept-Ianguage": "en-US,en;q=0.9,es;q=0.8", 25 | "X-VT-Anti-Abuse-Header": self.x_vt_header, 26 | } 27 | 28 | self.upload_headers = { 29 | "authority": "www.virustotal.com", 30 | "accept": "*/*", 31 | "accept-ianguage": "en-US,en;q=0.9,es;q=0.8", 32 | "accept-language": "en-GB,en-US;q=0.9,en;q=0.8", 33 | "cookie": "VT_PREFERRED_LANGUAGE=en", 34 | "origin": "https://www.virustotal.com", 35 | "referer": "https://www.virustotal.com/", 36 | "sec-fetch-dest": "empty", 37 | "sec-fetch-mode": "cors", 38 | "sec-fetch-site": "same-origin", 39 | "sec-gpc": "1", 40 | "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36", 41 | "x-app-version": "v1x98x0", 42 | "x-tool": "vt-ui-main", 43 | "x-vt-anti-abuse-header": self.x_vt_header, 44 | } 45 | 46 | def check_file_exist(self, file_hash): 47 | response = self.session.get( 48 | f"https://www.virustotal.com/ui/files/{file_hash}", 49 | headers=self.upload_headers, 50 | allow_redirects=False 51 | ) 52 | 53 | return 1 if response.status_code == 200 else 0 54 | 55 | def upload_file(self, filename, force=False): 56 | if self.check_file_exist(self.get_file_hash(filename)) and not force: 57 | return self.get_file_hash(filename) 58 | 59 | upload_url = self.get_upload_url() 60 | 61 | response = requests.post( 62 | upload_url, 63 | cookies={ 64 | "VT_PREFERRED_LANGUAGE": "en", 65 | }, 66 | headers=self.upload_headers, 67 | files={"file": open(filename, "rb")}, 68 | ) 69 | 70 | if response.status_code == 200: 71 | return self.get_file_hash(filename=filename) 72 | else: 73 | return 0 74 | 75 | def get_upload_url(self): 76 | response = self.session.get( 77 | "https://www.virustotal.com/ui/files/upload_url", headers=self.basic_header 78 | ) 79 | if response.ok: 80 | return response.text[15:-3] 81 | else: 82 | raise f"Invalid response: {response.status_code}" 83 | 84 | 85 | def upload_url(self, url): 86 | url_id = self.session.post("https://www.virustotal.com/ui/urls", data= f"url={urllib.parse.quote_plus(url)}",headers=self.upload_headers) 87 | if url_id.ok: 88 | url_id =url_id.json()['data']['id'] 89 | response = self.session.get(f"https://www.virustotal.com/ui/analyses/{url_id}",headers=self.upload_headers) 90 | if response.ok: 91 | return url_id[2:66] 92 | else: 93 | raise f"Error in validing the URL {url}" 94 | else : 95 | raise "Error in uploading url" 96 | 97 | def check_url_exists(self, url): 98 | return 0 if self.session.get(f"https://www.virustotal.com/ui/search?query={urllib.parse.quote_plus(url)}",headers=self.upload_headers).json()['data'] == [] else 1 99 | 100 | @staticmethod 101 | def get_file_hash(filename): 102 | with open(filename, "rb") as f: 103 | return hashlib.sha256(f.read()).hexdigest() 104 | 105 | def file_info(self,file_hash): 106 | 107 | if not self.check_file_exist(file_hash): 108 | return None 109 | 110 | return file_info_fill(self.session.get(f"https://www.virustotal.com/ui/files/{file_hash}",headers=self.upload_headers).json()) 111 | 112 | def url_info(self,url_hash): 113 | 114 | if not self.check_file_exist(url_hash): 115 | return None 116 | 117 | return self.session.get(f"https://www.virustotal.com/ui/urls/{url_hash}",headers=self.upload_headers).json() 118 | 119 | 120 | -------------------------------------------------------------------------------- /telegram/main.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, filters 2 | from pyrogram.types import InlineKeyboardMarkup,InlineKeyboardButton 3 | import pyrogram 4 | import os 5 | import botfunctions 6 | import threading 7 | import time 8 | from telegraph import Telegraph 9 | 10 | # bot 11 | bot_token = os.environ.get("TOKEN", "") 12 | api_hash = os.environ.get("HASH", "") 13 | api_id = os.environ.get("ID", "") 14 | app = Client("my_bot",api_id=api_id, api_hash=api_hash,bot_token=bot_token) 15 | MAXSIZE = 681574400 16 | telegraph = Telegraph() 17 | telegraph.create_account(short_name='VirusTotal') 18 | 19 | # start command 20 | @app.on_message(filters.command(["start"])) 21 | def strt(client: pyrogram.client.Client, message: pyrogram.types.messages_and_media.message.Message): 22 | 23 | START = f'👋🏻 Hello! {message.from_user.mention}\ 24 | \nI am a Bot based on **[VT-SCRAP](https://github.com/Brijeshkrishna/virustotal-scrapper)**\ 25 | \ 26 | \n\n__• You can send the file to the bot or forward it from another channel, and it will check file to **[VirusTotal](http://virustotal.com/)** with over **70** different antiviruses.\ 27 | \ 28 | \n\n• To get scan results - send me any a file up to **650 MB** in size, and you will receive a detailed analysis of it.\ 29 | \ 30 | \n\n• With the help of a bot, you can analyse suspicious files to identify virus and other bad programs.\ 31 | \ 32 | \n\n• You can also add me to your chats, and I will be able to analyse the files sent by participants.__' 33 | 34 | app.send_message(message.chat.id, START, reply_to_message_id=message.id, disable_web_page_preview=True, 35 | reply_markup=InlineKeyboardMarkup([[ 36 | InlineKeyboardButton( "📦 Source Code", url="https://github.com/bipinkrish/VirusTotal-Bot" ) 37 | ]])) 38 | 39 | 40 | # status updater 41 | def downstatus(statusfile,message): 42 | while True: 43 | if os.path.exists(statusfile): 44 | break 45 | while os.path.exists(statusfile): 46 | with open(statusfile,"r") as upread: 47 | txt = upread.read() 48 | try: 49 | app.edit_message_text(message.chat.id, message.id, f"🔽 Downloaded... {txt}") 50 | time.sleep(10) 51 | except: 52 | time.sleep(5) 53 | 54 | 55 | # progress function 56 | def progress(current, total, message): 57 | with open(f'{message.id}downstatus.txt',"w") as fileup: 58 | fileup.write(f"{current * 100 / total:.1f}%") 59 | 60 | 61 | # check function 62 | def checkvirus(message): 63 | msg = app.send_message(message.chat.id, '🔽 Downloading...', reply_to_message_id=message.id) 64 | print(f"Downloading: ID: {message.id} size: {message.document.file_size}") 65 | dnsta = threading.Thread(target=lambda:downstatus(f'{message.id}downstatus.txt',msg),daemon=True) 66 | dnsta.start() 67 | 68 | file = app.download_media(message,progress=progress, progress_args=[message]) 69 | os.remove(f'{message.id}downstatus.txt') 70 | app.edit_message_text(message.chat.id, msg.id, '🔼 Uploading to VirusTotal...') 71 | print(f"Uploading: ID: {message.id} size: {message.document.file_size}") 72 | 73 | hash = botfunctions.uploadfile(file) 74 | os.remove(file) 75 | print(f'ID: {message.id} HASH: {hash}') 76 | 77 | if hash == 0: 78 | app.edit_message_text(message.chat.id, msg.id, "✖️ Failed") 79 | print("HASH is 0") 80 | return 81 | 82 | app.edit_message_text(message.chat.id, msg.id, '⚙️ Checking...') 83 | print(f"Checking: ID: {message.id} size: {message.document.file_size}") 84 | maintext, checktext, signatures, link = botfunctions.cleaninfo(hash) 85 | 86 | if maintext == None: 87 | app.edit_message_text(message.chat.id, msg.id, "✖️ Failed") 88 | print("Function returned None") 89 | return 90 | 91 | response = telegraph.create_page('VT',content=[f'{maintext}-|-{checktext}-|-{signatures}-|-{link}']) 92 | tlink = response['url'] 93 | 94 | app.edit_message_text(message.chat.id, msg.id, maintext, 95 | reply_markup=InlineKeyboardMarkup([[ 96 | InlineKeyboardButton( "🧪 Detections", callback_data=f"D|{tlink}"), 97 | InlineKeyboardButton( "🌡 Signatures", callback_data=f"S|{tlink}"), 98 | ], 99 | [ 100 | InlineKeyboardButton( "🔗 View on VirusTotal", url=link ) 101 | ]])) 102 | 103 | 104 | # document 105 | @app.on_message(filters.document) 106 | def docu(client: pyrogram.client.Client, message: pyrogram.types.messages_and_media.message.Message): 107 | if int(message.document.file_size) > MAXSIZE: 108 | app.send_message(message.chat.id, "⭕️ File is too Big for VirusTotal. It should be less than 650 MB", reply_to_message_id=message.id) 109 | return 110 | vt = threading.Thread(target=lambda:checkvirus(message),daemon=True) 111 | vt.start() 112 | 113 | 114 | # call back functon 115 | @app.on_callback_query() 116 | def callbck(client: pyrogram.client.Client, message: pyrogram.types.CallbackQuery): 117 | url = message.message.reply_markup.inline_keyboard[1][0].url 118 | datas = message.data.split("|") 119 | action = datas[0] 120 | tlink = datas[1] 121 | res = telegraph.get_page(tlink.split("https://telegra.ph/")[1], return_content=True, return_html=False) 122 | result = res["content"][0].split("-|-") 123 | maintext = result[0] 124 | checktext = result[1] 125 | signatures = result[2] 126 | 127 | if action == "B": 128 | app.edit_message_text(message.message.chat.id, message.message.id, maintext, 129 | reply_markup=InlineKeyboardMarkup([[ 130 | InlineKeyboardButton( "🧪 Detections", callback_data=f"D|{tlink}"), 131 | InlineKeyboardButton( "🌡 Signatures", callback_data=f"S|{tlink}") 132 | ], 133 | [ 134 | InlineKeyboardButton( "🔗 View on VirusTotal", url=url ) 135 | ]])) 136 | 137 | if action == "D": 138 | app.edit_message_text(message.message.chat.id, message.message.id, checktext, 139 | reply_markup=InlineKeyboardMarkup([[ 140 | InlineKeyboardButton( "🔙 Back", callback_data=f"B|{tlink}"), 141 | InlineKeyboardButton( "🌡 Signatures", callback_data=f"S|{tlink}"), 142 | ], 143 | [ 144 | InlineKeyboardButton( "🔗 View on VirusTotal", url=url ) 145 | ]])) 146 | 147 | if action == "S": 148 | app.edit_message_text(message.message.chat.id, message.message.id, signatures, 149 | reply_markup=InlineKeyboardMarkup([[ 150 | InlineKeyboardButton( "🔙 Back", callback_data=f"B|{tlink}"), 151 | InlineKeyboardButton( "🧪 Detections", callback_data=f"D|{tlink}") 152 | ], 153 | [ 154 | InlineKeyboardButton( "🔗 View on VirusTotal", url=url ) 155 | ]])) 156 | 157 | 158 | # app run 159 | app.run() 160 | --------------------------------------------------------------------------------