commit 22f175966a4776c6e546d4664d017b06d18b0651 Author: Alex55 Date: Wed Jun 25 14:08:37 2025 +0300 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f40304a --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/.venv +/logs +# Игнорируем файлы логов +*.log +.env +/tests +session.session \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/README.md b/README.md new file mode 100644 index 0000000..50bdfd5 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +Пример как следить когда пользователи были в онлайн) \ No newline at end of file diff --git a/__pycache__/config.cpython-312.pyc b/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..3ed0bd0 Binary files /dev/null and b/__pycache__/config.cpython-312.pyc differ diff --git a/envprimer b/envprimer new file mode 100644 index 0000000..f4fbfdd --- /dev/null +++ b/envprimer @@ -0,0 +1,2 @@ +API_ID= +API_HASH= \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..a3b1876 --- /dev/null +++ b/main.py @@ -0,0 +1,53 @@ +import asyncio +from datetime import datetime, timezone, timedelta +from telethon import TelegramClient +from telethon.tl.types import UserStatusOnline, UserStatusOffline + +import utils.config + +from utils.logging_setup import configure_global_logging + +logger = configure_global_logging() +config = utils.config + +# Список пользователей, которых отслеживаем + + +async def check_status(client, username): + try: + entity = await client.get_entity(username) + user_id = entity.id + username = entity.username or '' + user = await client.get_entity(user_id) + status = user.status + + # 1. Получаем тип статуса + status_type = type(status).__name__ + + logger.info(f"\nСледим за: {username} (ID: {user_id})") + + if status_type == 'UserStatusOffline': + was_online_utc = status.was_online + kiev_time = was_online_utc.astimezone(timezone(timedelta(hours=3))) + year, month, day = kiev_time.year, kiev_time.month, kiev_time.day + hour, minute, second = kiev_time.hour, kiev_time.minute, kiev_time.second + + logger.info(f"Статус: {status_type}") + logger.info(f"Последний онлайн (Киев): {year}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}") + + elif status_type == 'UserStatusOnline': + logger.info(f"Статус: {status_type} — Сейчас онлайн") + + else: + logger.info(f"Статус: {status_type} — Время скрыто или неизвестно") + + except Exception as e: + logger.info(f"⚠️ Ошибка при проверке {username}: {e}") + +async def main(): + async with TelegramClient('session', config.api_id, config.api_hash) as client: + tasks = [check_status(client, username) for username in config.target_usernames] + await asyncio.gather(*tasks) + +if __name__ == '__main__': + asyncio.run(main()) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a7b61ba --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "tgshka" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "python-dotenv>=1.1.1", + "telethon>=1.40.0", +] diff --git a/utils/__pycache__/config.cpython-312.pyc b/utils/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..6f953ce Binary files /dev/null and b/utils/__pycache__/config.cpython-312.pyc differ diff --git a/utils/__pycache__/logging_setup.cpython-312.pyc b/utils/__pycache__/logging_setup.cpython-312.pyc new file mode 100644 index 0000000..b009bdb Binary files /dev/null and b/utils/__pycache__/logging_setup.cpython-312.pyc differ diff --git a/utils/config.py b/utils/config.py new file mode 100644 index 0000000..0c275ba --- /dev/null +++ b/utils/config.py @@ -0,0 +1,10 @@ +from dotenv import load_dotenv +import os +load_dotenv() + + +# db_host = os.getenv('DB_HOST') +api_id = os.getenv('API_ID') # замени на свой +api_hash = os.getenv('API_HASH') + +target_usernames = ['vipertt', 'Prommm12'] \ No newline at end of file diff --git a/utils/logging_setup.py b/utils/logging_setup.py new file mode 100644 index 0000000..93aae2d --- /dev/null +++ b/utils/logging_setup.py @@ -0,0 +1,40 @@ +import logging +from logging.handlers import RotatingFileHandler +from pathlib import Path + +class MyAppFilter(logging.Filter): + def filter(self, record): + return record.name == "my_app" + +def configure_global_logging( + log_file="logs/app.log", + level=logging.INFO, + max_bytes=5_000_000, + backup_count=3 +): + log_file_path = Path(log_file) + log_file_path.parent.mkdir(parents=True, exist_ok=True) + + logger = logging.getLogger("my_app") + logger.setLevel(level) + + if not logger.hasHandlers(): + file_handler = RotatingFileHandler( + log_file, maxBytes=max_bytes, backupCount=backup_count + ) + file_handler.setLevel(level) + file_handler.setFormatter(logging.Formatter("%(asctime)s [%(filename)s:%(lineno)d] - %(message)s")) + file_handler.addFilter(MyAppFilter()) + + console_handler = logging.StreamHandler() + console_handler.setLevel(level) + console_handler.setFormatter(logging.Formatter("%(asctime)s [%(filename)s:%(lineno)d] - %(message)s")) + console_handler.addFilter(MyAppFilter()) + + logger.addHandler(file_handler) + logger.addHandler(console_handler) + + # Отключаем все другие логгеры + logging.getLogger().setLevel(logging.CRITICAL) + + return logger diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..5690fed --- /dev/null +++ b/uv.lock @@ -0,0 +1,67 @@ +version = 1 +revision = 2 +requires-python = ">=3.12" + +[[package]] +name = "pyaes" +version = "1.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/44/66/2c17bae31c906613795711fc78045c285048168919ace2220daa372c7d72/pyaes-1.6.1.tar.gz", hash = "sha256:02c1b1405c38d3c370b085fb952dd8bea3fadcee6411ad99f312cc129c536d8f", size = 28536, upload-time = "2017-09-20T21:17:54.23Z" } + +[[package]] +name = "pyasn1" +version = "0.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, +] + +[[package]] +name = "python-dotenv" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, +] + +[[package]] +name = "rsa" +version = "4.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" }, +] + +[[package]] +name = "telethon" +version = "1.40.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyaes" }, + { name = "rsa" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/af/9b7111e3f63fffe8e55b7ceb8bda023173e2052f420b6debcb25fd2fbc15/telethon-1.40.0.tar.gz", hash = "sha256:40e83326877a2e68b754d4b6d0d1ca5ac924110045b039e02660f2d67add97db", size = 646723, upload-time = "2025-04-21T09:12:10.506Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/5a/c5370edb3215d19a6e858f4169b8eec725ba55f9d39df0f557508048c037/Telethon-1.40.0-py3-none-any.whl", hash = "sha256:146fd4cb2a7afa66bc67f9c2167756096a37b930f65711a3e7399ec9874dcfa7", size = 722013, upload-time = "2025-04-21T09:12:08.399Z" }, +] + +[[package]] +name = "tgshka" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "python-dotenv" }, + { name = "telethon" }, +] + +[package.metadata] +requires-dist = [ + { name = "python-dotenv", specifier = ">=1.1.1" }, + { name = "telethon", specifier = ">=1.40.0" }, +]