├── requirements.txt ├── .gitattributes ├── Screenshot.png ├── README.md ├── .gitignore └── silvertgosint.py /requirements.txt: -------------------------------------------------------------------------------- 1 | telethon 2 | termcolor 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/silverxcyber/silvertgosint/HEAD/Screenshot.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Silvertgosint - Telegram OSINT Tool 2 | 3 | This tool connects to your Telegram account using the API ID and API hash and retrieves all messages of the target user from the groups you are in, saving them to a TXT file and additionally storing them in a database. 4 | 5 | When logging in, you need to access your Telegram account via [my.telegram.org](https://my.telegram.org) and generate an API ID and API hash. 6 | 7 | Additionally, if the target group is publicly accessible, various details such as ID, username, name, number, etc., can be collected. 8 | 9 | **Useful Note:** You can add the account linked to this tool to hundreds of groups and collect the target’s messages from all those groups. 10 | 11 | ![Image Alt](https://github.com/silverxpymaster/silvertgosint/blob/main/Screenshot.png?raw=true) 12 | 13 | ## Features 14 | ``` 15 | - All groups the target user is in and all messages they have sent in those groups are collected. 16 | - Statistics on how many messages the target has sent in each group are gathered (this allows you to see which group they are most active in). 17 | - All members of the target group (in ID, name, username, and number format) are collected and saved to a TXT file. 18 | - All media from the target group is downloaded. 19 | ``` 20 | 21 | ## Installation 22 | 23 | ### Setup 24 | 1. Obtain API credentials from [my.telegram.org](https://my.telegram.org): 25 | - Login and navigate to "API development tools." 26 | - Create a new app and note the `API ID` and `API Hash`. 27 | 2. Clone this repository: 28 | ```bash 29 | git clone https://github.com/silverxpymaster/silvertgosint.git 30 | ``` 31 | 3. Navigate into the project folder: 32 | ```bash 33 | cd silvertgosint 34 | ``` 35 | 4. Download the required libraries 36 | ```bash 37 | pip install -r requirements.txt 38 | ``` 39 | 4. Run the tool: 40 | ```bash 41 | python silvertgosint.py 42 | ``` 43 | ## YouTube Tutorial 44 | [![Video Title](https://img.youtube.com/vi/U9mA-wkfxY4/0.jpg)](https://www.youtube.com/watch?v=U9mA-wkfxY4) 45 | 46 | Click photo and watch youtube tutorial :) 47 | 48 | ## Notes 49 | - This tool requires authentication with Telegram using a phone number and an active session. 50 | - The SQLite database stores collected messages for further analysis. 51 | 52 | ## Author 53 | **SilverX** 54 | [YouTube Channel](https://youtube.com/@silverxcyber) 55 | [Telegram Channel](https://t.me/silverxvip) 56 | 57 | --- 58 | **Disclaimer:** This tool is for educational and research purposes only. Use it responsibly and ensure compliance with Telegram's terms of service. 59 | 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 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 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 105 | __pypackages__/ 106 | 107 | # Celery stuff 108 | celerybeat-schedule 109 | celerybeat.pid 110 | 111 | # SageMath parsed files 112 | *.sage.py 113 | 114 | # Environments 115 | .env 116 | .venv 117 | env/ 118 | venv/ 119 | ENV/ 120 | env.bak/ 121 | venv.bak/ 122 | 123 | # Spyder project settings 124 | .spyderproject 125 | .spyproject 126 | 127 | # Rope project settings 128 | .ropeproject 129 | 130 | # mkdocs documentation 131 | /site 132 | 133 | # mypy 134 | .mypy_cache/ 135 | .dmypy.json 136 | dmypy.json 137 | 138 | # Pyre type checker 139 | .pyre/ 140 | 141 | # pytype static type analyzer 142 | .pytype/ 143 | 144 | # Cython debug symbols 145 | cython_debug/ 146 | 147 | # PyCharm 148 | # JetBrains specific template is maintainted in a separate JetBrains.gitignore that can 149 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 150 | # and can be added to the global gitignore or merged into this file. For a more nuclear 151 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 152 | #.idea/ 153 | -------------------------------------------------------------------------------- /silvertgosint.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | from telethon import TelegramClient 3 | from telethon.sync import TelegramClient 4 | from telethon.tl.types import InputMessagesFilterPhotos, InputMessagesFilterVideo 5 | import os 6 | from termcolor import colored 7 | 8 | os.system("cls || clear") 9 | print(colored(""" 10 | 11 | ███████ ██ ██ ██ ██ ███████ ██████ ████████ ██████ ██████ ███████ ██ ███ ██ ████████ 12 | ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██ 13 | ███████ ██ ██ ██ ██ █████ ██████ ██ ██ ███ ██ ██ ███████ ██ ██ ██ ██ ██ 14 | ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 15 | ███████ ██ ███████ ████ ███████ ██ ██ ██ ██████ ██████ ███████ ██ ██ ████ ██ 16 | 17 | ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣾⣿⣿⣿⡄ 18 | ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣶⣿⣿⡿⠿⠛⢙⣿⣿⠃ 19 | ⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣶⣾⣿⣿⠿⠛⠋⠁⠀⠀⠀⣸⣿⣿⠀ 20 | ⠀⠀⠀⠀⣀⣤⣴⣾⣿⣿⡿⠟⠛⠉⠀⠀⣠⣤⠞⠁⠀⠀⣿⣿⡇⠀ 21 | ⠀⣴⣾⣿⣿⡿⠿⠛⠉⠀⠀⠀⢀⣠⣶⣿⠟⠁⠀⠀⠀⢸⣿⣿⠀⠀ 22 | ⠸⣿⣿⣿⣧⣄⣀⠀⠀⣀⣴⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⣼⣿⡿⠀⠀ 23 | ⠀⠈⠙⠻⠿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⢠⣿⣿⠇⠀⠀ 24 | ⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡇⠀⣀⣄⡀⠀⠀⠀⠀⢸⣿⣿⠀⠀⠀ 25 | ⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣠⣾⣿⣿⣿⣦⡀⠀⠀⣿⣿⡏⠀⠀⠀ 26 | ⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⡿⠋⠈⠻⣿⣿⣦⣸⣿⣿⠁⠀⠀⠀ 27 | ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠛⠁⠀⠀⠀⠀⠈⠻⣿⣿⣿⠏⠀⠀⠀⠀ 28 | 29 | 30 | Author : SilverX Tg: t.me/silverxvip 31 | """, 'blue')) 32 | 33 | sessiya_adi = 'session_file' 34 | 35 | sessiya_moevcuddur = os.path.exists(f"{sessiya_adi}.session") 36 | 37 | if not sessiya_moevcuddur: 38 | try: 39 | api_id = input("Enter the API ID: ").strip() 40 | except KeyboardInterrupt: 41 | print("\nProgram Stopped!") 42 | exit() 43 | try: 44 | api_hash = input("Enter the API Hash: ").strip() 45 | except KeyboardInterrupt: 46 | print("\nProgram Stopped!") 47 | exit() 48 | try: 49 | telefon_nomresi = input("Enter the phone number (starting with +994):").strip() 50 | except KeyboardInterrupt: 51 | print("\nProgram Stopped!") 52 | exit() 53 | 54 | musteri = TelegramClient(sessiya_adi, api_id, api_hash) 55 | musteri.start(telefon_nomresi) 56 | 57 | else: 58 | api_id = '12345' 59 | api_hash = '0123456789abcdef0123456789abcdef' 60 | telefon_nomresi = None 61 | 62 | musteri = TelegramClient(sessiya_adi, api_id, api_hash) 63 | 64 | 65 | def database_yarat(): 66 | try: 67 | connection = sqlite3.connect('telegram_messages.db') 68 | cursor = connection.cursor() 69 | 70 | cursor.execute(''' 71 | CREATE TABLE IF NOT EXISTS messages ( 72 | id INTEGER PRIMARY KEY AUTOINCREMENT, 73 | username TEXT, 74 | tg_id INTEGER, 75 | group_name TEXT, 76 | message_text TEXT, 77 | message_date TEXT 78 | ) 79 | ''') 80 | 81 | connection.commit() 82 | connection.close() 83 | print("Database successfully created!") 84 | except sqlite3.Error as error: 85 | print(f"An error occurred while creating the database: {error}") 86 | 87 | 88 | def mesaj_elave_et(username, tg_id, group_name, message_text, message_date): 89 | try: 90 | connection = sqlite3.connect('telegram_messages.db') 91 | cursor = connection.cursor() 92 | 93 | cursor.execute(''' 94 | SELECT COUNT(*) FROM messages WHERE message_text = ? AND message_date = ? AND username = ?; 95 | ''', (message_text, message_date, username)) 96 | 97 | message_exists = cursor.fetchone()[0] 98 | 99 | if message_exists == 0: 100 | cursor.execute(''' 101 | INSERT INTO messages (username, tg_id, group_name, message_text, message_date) 102 | VALUES (?, ?, ?, ?, ?); 103 | ''', (username, tg_id, group_name, message_text, message_date)) 104 | 105 | connection.commit() 106 | 107 | with open(f"{username}_messages.txt", "a", encoding="utf-8") as file: 108 | file.write(f"Group: {group_name}\n") 109 | file.write(f"Message: {message_text}\n") 110 | file.write(f"Date: {message_date}\n") 111 | print(f"New message added: {group_name}") 112 | else: 113 | print(f"Message already exists: {group_name}") 114 | 115 | connection.close() 116 | except sqlite3.Error as error: 117 | print(f"An error occurred while adding the message to the database: {error}") 118 | except Exception as error: 119 | print(f"Error: {error}") 120 | 121 | 122 | async def mesajlari_topla(search_value): 123 | try: 124 | if telefon_nomresi: 125 | await musteri.start(telefon_nomresi) 126 | else: 127 | await musteri.start() 128 | 129 | dialogs = await musteri.get_dialogs() 130 | 131 | for dialog in dialogs: 132 | if dialog.is_group: 133 | group_name = dialog.name 134 | group_id = dialog.id 135 | 136 | print(f"Search is being performed in the {group_name} group...") 137 | messages = await musteri.get_messages(dialog.id, from_user=search_value, limit=10000000) 138 | 139 | for message in messages: 140 | tg_id = message.sender_id 141 | mesaj_elave_et(str(search_value), tg_id, group_name, message.text, str(message.date)) 142 | 143 | print("Search completed. Messages saved in database and txt file!") 144 | except Exception as error: 145 | print(f"An error occurred while connecting with Telegram: {error}") 146 | 147 | 148 | async def qrup_melumatlarini_topla(group_link): 149 | try: 150 | if telefon_nomresi: 151 | await musteri.start(telefon_nomresi) 152 | else: 153 | await musteri.start() 154 | 155 | group = await musteri.get_entity(group_link) 156 | group_name = group.title 157 | group_description = group.about if hasattr(group, 'about') and group.about else "No information" 158 | 159 | group_bio_summary = ( 160 | f"Group ID: {group.id}\n" 161 | f"Creator: {'Yes' if group.creator else 'No'}\n" 162 | f"Verified: {'Yes' if group.verified else 'No'}\n" 163 | f"Number of members: {len(await musteri.get_participants(group))} members\n" 164 | f"Mega Group: {'Yes' if group.megagroup else 'No'}\n" 165 | f"Group Link: {group.username or 'No information'}\n" 166 | ) 167 | 168 | print(f"Collecting information for group: {group_name}...") 169 | 170 | members = await musteri.get_participants(group) 171 | 172 | with open(f"{group_name}_info.txt", "w", encoding="utf-8") as file: 173 | file.write("🛡️ Group Information 🛡️\n") 174 | file.write(f"Group Name : {group_name}\n") 175 | file.write(f"Group Description : {group_description}\n") 176 | file.write(f"Group Bio Summary:\n{group_bio_summary}\n") 177 | file.write(f"Number of members: {len(members)} members\n") 178 | file.write("=" * 50 + "\n\n") 179 | 180 | for idx, member in enumerate(members, start=1): 181 | file.write(f"Member #{idx}:\n") 182 | file.write(f" Full Name : {member.first_name or ''} {member.last_name or ''}\n") 183 | file.write(f" Telegram ID : {member.id}\n") 184 | file.write(f" Phone Number : {member.phone or 'No information'}\n") 185 | file.write(f" Status : {'Bot' if member.bot else 'User'}\n") 186 | file.write("-" * 50 + "\n") 187 | 188 | print(f"Group information successfully saved: {group_name}_info.txt") 189 | except Exception as error: 190 | print(f"An error occurred while collecting group information: {error}") 191 | 192 | 193 | async def mesaj_statistikasini_topla(search_value): 194 | try: 195 | if telefon_nomresi: 196 | await musteri.start(telefon_nomresi) 197 | else: 198 | await musteri.start() 199 | 200 | dialogs = await musteri.get_dialogs() 201 | 202 | message_counts = {} 203 | 204 | for dialog in dialogs: 205 | if dialog.is_group: 206 | group_name = dialog.name 207 | group_id = dialog.id 208 | 209 | print(f"Search is being performed in the {group_name} group...") 210 | messages = await musteri.get_messages(dialog.id, from_user=search_value, limit=10000000) 211 | 212 | if len(messages) > 0: 213 | message_counts[group_name] = len(messages) 214 | 215 | print(f"\nUser '{search_value}' message statistics across groups:") 216 | 217 | with open(f"{search_value}_message_statistics.txt", "a", encoding="utf-8") as file: 218 | file.write(f"User: {search_value}\n") 219 | file.write("Group Name - Message Count\n") 220 | file.write("=" * 30 + "\n") 221 | 222 | for group, count in message_counts.items(): 223 | print(f"Group: {group} - Message Count: {count}") 224 | file.write(f"Group: {group} - Message Count: {count}\n") 225 | 226 | file.write("=" * 30 + "\n") 227 | print(f"\nStatistics saved to file: {search_value}_message_statistics.txt") 228 | 229 | except Exception as error: 230 | print(f"Error: {error}") 231 | 232 | 233 | async def qrup_mediasini_yukle(group_link): 234 | try: 235 | group = await musteri.get_entity(group_link) 236 | 237 | messages = await musteri.get_messages(group, limit=5000, filter=InputMessagesFilterPhotos) 238 | messages += await musteri.get_messages(group, limit=5000, filter=InputMessagesFilterVideo) 239 | 240 | print(f"Group: {group_link} - Starting media download...") 241 | 242 | for message in messages: 243 | if message.media: 244 | media_file = await musteri.download_media(message.media, file="media_downloads/") 245 | print(f"Downloaded: {media_file}") 246 | else: 247 | print(f"No media found: {message.id}") 248 | 249 | except Exception as error: 250 | print(f"An error occurred: {error}") 251 | 252 | 253 | def restart_program(): 254 | while True: 255 | choice = input("Would you like to add a new target? (Yes/No): ").strip().lower() 256 | if choice == "yes": 257 | with musteri: 258 | try: 259 | new_choice = input("Select search type (1: Username, 2: ID): ").strip() 260 | if new_choice == '1': 261 | try: 262 | search_value = input("Enter the Telegram username to search for (username): ").strip() 263 | except KeyboardInterrupt: 264 | print("\nProgram Stopped!") 265 | exit() 266 | elif new_choice == '2': 267 | try: 268 | search_value = int(input("Enter the Telegram user ID to search for: ").strip()) 269 | except KeyboardInterrupt: 270 | print("\nProgram Stopped!") 271 | exit() 272 | else: 273 | print("Invalid selection! Program will stop.") 274 | exit(1) 275 | 276 | musteri.loop.run_until_complete(mesajlari_topla(search_value)) 277 | except Exception as error: 278 | print(f"Error: {error}") 279 | elif choice == "no": 280 | print("Program stopped...") 281 | break 282 | else: 283 | print("Please enter 'Yes' or 'No'.") 284 | 285 | 286 | def main_menu(): 287 | while True: 288 | print(colored("\nSILVERTGOSINT MENU:", 'white')) 289 | print("1. Collect user messages") 290 | print("2. Collect group info") 291 | print("3. Collect user message statistics") 292 | print("4. Download all media in group") 293 | print("5. Exit") 294 | choice = input("Select an option: ").strip() 295 | 296 | if choice == "1": 297 | with musteri: 298 | try: 299 | print("Select search type:") 300 | print("1. By Username") 301 | print("2. By Telegram ID") 302 | search_type = input("Select option: ").strip() 303 | 304 | if search_type == "1": 305 | search_value = input("Enter the Telegram username to search for (username): ").strip() 306 | elif search_type == "2": 307 | search_value = int(input("Enter the Telegram user ID to search for: ").strip()) 308 | else: 309 | print("Invalid choice! Going back...") 310 | continue 311 | 312 | musteri.loop.run_until_complete(mesajlari_topla(search_value)) 313 | except Exception as error: 314 | print(f"Error: {error}") 315 | elif choice == "2": 316 | with musteri: 317 | try: 318 | group_link = input("Enter the group link: ").strip() 319 | musteri.loop.run_until_complete(qrup_melumatlarini_topla(group_link)) 320 | except Exception as error: 321 | print(f"Error: {error}") 322 | elif choice == "3": 323 | with musteri: 324 | try: 325 | search_type = input("Select search type (1: Username, 2: ID): ").strip() 326 | 327 | if search_type == "1": 328 | search_value = input("Enter the Telegram username to search for (username): ").strip() 329 | elif search_type == "2": 330 | search_value = int(input("Enter the Telegram user ID to search for: ").strip()) 331 | else: 332 | print("Invalid choice! Going back...") 333 | continue 334 | 335 | musteri.loop.run_until_complete(mesaj_statistikasini_topla(search_value)) 336 | except Exception as error: 337 | print(f"Error: {error}") 338 | elif choice == "4": 339 | with musteri: 340 | try: 341 | group_link = input("Enter the group link: ").strip() 342 | musteri.loop.run_until_complete(qrup_mediasini_yukle(group_link)) 343 | except Exception as error: 344 | print(f"Error: {error}") 345 | elif choice == "5": 346 | print("Exiting program...") 347 | break 348 | else: 349 | print("Invalid choice! Please make a correct selection.") 350 | 351 | database_yarat() 352 | 353 | main_menu() 354 | 355 | restart_program() 356 | 357 | --------------------------------------------------------------------------------