Alert первый комит
Основной функционал: * Портативная среда выполнения на виндовс * Пересылка сообщений из публичного канала по ключевым словам * Отслеживание изменений пересланных сообщений * Очистка от системных
This commit is contained in:
commit
2bfa13b023
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.env
|
||||
venv*
|
||||
python*
|
||||
298
main.py
Normal file
298
main.py
Normal file
@ -0,0 +1,298 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from telethon import TelegramClient, events
|
||||
import re
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from dotenv import find_dotenv, load_dotenv
|
||||
|
||||
# ==== Настройка логирования ====
|
||||
logging.basicConfig(
|
||||
format='[%(levelname)s] %(asctime)s | %(message)s',
|
||||
level=logging.INFO,
|
||||
handlers=[
|
||||
logging.StreamHandler() # Вывод в консоль
|
||||
# logging.FileHandler("bot.log", encoding="utf-8") # Раскомментируй, чтобы сохранять логи в файл
|
||||
]
|
||||
)
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# === Загрузка переменных окружения ===
|
||||
env = find_dotenv()
|
||||
log.info(f'Использую: {env}')
|
||||
load_dotenv(env)
|
||||
|
||||
# === Данные юзер-бота ===
|
||||
api_id=os.getenv('api_id')
|
||||
api_hash=os.getenv('api_hash')
|
||||
session_name=os.getenv('session_name')
|
||||
|
||||
# === Настройки ===
|
||||
source_channel_username=os.getenv('source_channel_username') # Канал, который слушаем
|
||||
target_group_chat_id=int(os.getenv('target_group_chat_id')) # Группа, куда пересылаем
|
||||
|
||||
filter_keywords=os.getenv('filter_keywords') # Строки или регулярное выражение для поиска
|
||||
filter_keywords=filter_keywords.split(',')
|
||||
filter_negative_keywords=os.getenv('filter_negative_keywords') # Строки или регулярное выражение для поиска
|
||||
filter_negative_keywords=filter_negative_keywords.split(',')
|
||||
DATA_FILE=os.getenv('DATA_FILE') # Файл для сохранения сообщений
|
||||
MAX_MESSAGES=int(os.getenv('MAX_MESSAGES')) # Количество хранящихся сообщений
|
||||
CHECK_INTERVAL=int(os.getenv('CHECK_INTERVAL')) # Периодичность проверки удалений на канале
|
||||
|
||||
# =======================
|
||||
|
||||
client = TelegramClient(session_name, api_id, api_hash)
|
||||
|
||||
# ==== Загрузка/сохранение состояния ====
|
||||
def load_state():
|
||||
if os.path.exists(DATA_FILE):
|
||||
with open(DATA_FILE, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
return {}
|
||||
|
||||
def save_state(data):
|
||||
with open(DATA_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
# ==== Хранение данных ====
|
||||
source_messages = load_state() # {msg_id: {'text': ..., 'forwarded_msg_id': ...}}
|
||||
|
||||
# =======================
|
||||
def shorten(text: str, length: int = 80) -> str:
|
||||
'''Возвращает короткое сообщение для логов'''
|
||||
text = text.replace('\n', ' ↵ ')
|
||||
if len(text)>length:
|
||||
return f'{text[:length-1]}…'
|
||||
return text
|
||||
|
||||
# ==== Обработчик сообщений из источника ====
|
||||
@client.on(events.NewMessage(chats=source_channel_username))
|
||||
async def handler(event):
|
||||
message_text = event.message.text or ""
|
||||
msg_id = event.message.id
|
||||
|
||||
if message_text:
|
||||
log.info(f"Новое сообщение: {shorten(message_text)}")
|
||||
|
||||
# Проверяем само сообщение
|
||||
if any(re.search(keyword, message_text, re.IGNORECASE) for keyword in filter_keywords) \
|
||||
and not any(re.search(keyword, message_text, re.IGNORECASE) for keyword in filter_negative_keywords):
|
||||
new_msg = await client.forward_messages(target_group_chat_id, event.message)
|
||||
source_messages[msg_id] = {
|
||||
'text': message_text,
|
||||
'timestamp': datetime.now().timestamp(),
|
||||
'forwarded_msg_id': new_msg.id
|
||||
}
|
||||
# Ограничиваем размер словаря
|
||||
if len(source_messages) > MAX_MESSAGES:
|
||||
oldest = min(source_messages.keys(), key=lambda k: source_messages[k]['timestamp'])
|
||||
del source_messages[oldest]
|
||||
save_state(source_messages)
|
||||
log.info(f"📩 Переслано: {shorten(message_text)}")
|
||||
return
|
||||
|
||||
# Проверяем цепочку ответов
|
||||
reply = event.message.reply_to
|
||||
if reply and reply.reply_to_msg_id:
|
||||
founded = await check_reply_chain(event, reply.reply_to_msg_id, depth=1)
|
||||
if founded:
|
||||
await client.forward_messages(target_group_chat_id, event.message)
|
||||
log.info(f"⛓ Переслано по цепочке: {shorten(message_text)} | Глубина: {founded}")
|
||||
|
||||
|
||||
# ==== Фоновая задача: проверка удалений и изменений ====
|
||||
async def monitor_messages():
|
||||
while True:
|
||||
await asyncio.sleep(CHECK_INTERVAL)
|
||||
|
||||
now = datetime.now().timestamp()
|
||||
cutoff_time = now - 86400 # 24 часа
|
||||
|
||||
for str_msg_id, stored_m_info in list(source_messages.items()):
|
||||
msg_id = int(str_msg_id)
|
||||
|
||||
# Удаление по возрасту
|
||||
if stored_m_info['timestamp'] < cutoff_time:
|
||||
del source_messages[str_msg_id]
|
||||
continue
|
||||
|
||||
# Получаем данные о пересланном сообщении
|
||||
try:
|
||||
target_msg = await client.get_messages(target_group_chat_id, ids=stored_m_info['forwarded_msg_id'])
|
||||
except Exception as e:
|
||||
log.warning(f"⚠ Не удалось получить пересланное сообщение {msg_id}: {e}")
|
||||
target_msg = None
|
||||
continue
|
||||
# Если пересланного сообщения нет (удалено)
|
||||
if target_msg is None or getattr(target_msg, 'empty', False):
|
||||
log.info(f"🗑 Пересланное сообщение отсутвует (удалено администратором): {shorten(stored_m_info['text'])}")
|
||||
del source_messages[str_msg_id]
|
||||
continue
|
||||
|
||||
# Получаем сообщение из источника
|
||||
try:
|
||||
source_msg = await client.get_messages(source_channel_username, ids=msg_id)
|
||||
except Exception as e:
|
||||
log.warning(f"⚠ Не удалось получить исходное сообщение {msg_id}: {e}")
|
||||
source_msg = None
|
||||
continue
|
||||
# Если исходного сообщения нет (удалено)
|
||||
if source_msg is None or getattr(source_msg, 'empty', False):
|
||||
log.info(f"🗑 Исходное сообщение удалено. Удаляю пересланное: {shorten(stored_m_info['text'])}")
|
||||
await client.delete_messages(target_group_chat_id, msg_id)
|
||||
del source_messages[str_msg_id]
|
||||
continue
|
||||
|
||||
# Если текст изменился
|
||||
if source_msg.text != target_msg.text:
|
||||
log.info(f"📝 Сообщение изменено: {shorten(target_msg.text)} → {shorten(source_msg.text)}")
|
||||
# Редактируем пересланное сообщение
|
||||
try:
|
||||
# Получаем ID последнего сообщения в целевом чате
|
||||
last_msg = await client.get_messages(target_group_chat_id, limit=1)
|
||||
last_msg_id = last_msg[0].id if last_msg else None
|
||||
|
||||
# Проверяем, является ли наше пересланное сообщение последним
|
||||
if target_msg.id == last_msg_id:
|
||||
# Это последнее сообщение — можно удалить и переслать заново
|
||||
await client.delete_messages(target_group_chat_id, target_msg.id)
|
||||
new_msg = await client.forward_messages(target_group_chat_id, source_msg)
|
||||
source_messages[str(source_msg.id)] = {
|
||||
'text': source_msg.text,
|
||||
'timestamp': datetime.now().timestamp(),
|
||||
'forwarded_msg_id': new_msg.id
|
||||
}
|
||||
log.info("🔁 Сообщение было последним → Заменено")
|
||||
else:
|
||||
# Не последнее → отправляем изменённый текст как ответ
|
||||
new_msg = await client.send_message(
|
||||
target_group_chat_id,
|
||||
f"🔄 Текст изменён:\n{source_msg.text}",
|
||||
reply_to=stored_m_info['forwarded_msg_id']
|
||||
)
|
||||
source_messages[str(source_msg.id)] = {
|
||||
'text': source_msg.text,
|
||||
'timestamp': datetime.now().timestamp(),
|
||||
'forwarded_msg_id': new_msg.id
|
||||
}
|
||||
log.info("💬 Сообщение не последнее → Отправлен ответ")
|
||||
except Exception as e:
|
||||
log.error(f"❌ Не удалось обновить: {e}")
|
||||
|
||||
# Сохраняем состояние
|
||||
save_state(source_messages)
|
||||
|
||||
|
||||
async def check_reply_chain(event, msg_id, depth=1, max_depth=10) -> bool|int:
|
||||
"""Рекурсивная проверка цепочки ответов"""
|
||||
if depth > max_depth:
|
||||
log.warning(f"🔁 Превышена максимальная глубина цепочки ({max_depth}), остановлено.")
|
||||
return False
|
||||
|
||||
try:
|
||||
replied_msg = await event.get_reply_message()
|
||||
except Exception as e:
|
||||
log.warning(f"⚠ Не удалось получить сообщение по ID {msg_id}: {e}")
|
||||
return False
|
||||
|
||||
if not replied_msg:
|
||||
return False
|
||||
|
||||
text = replied_msg.text or ""
|
||||
|
||||
log.info(f"🔍 Проверяю сообщение на уровне {depth}: {shorten(text,30)}")
|
||||
|
||||
if any(re.search(keyword, text, re.IGNORECASE) for keyword in filter_keywords) \
|
||||
and not any(re.search(keyword, text, re.IGNORECASE) for keyword in filter_negative_keywords):
|
||||
return depth
|
||||
|
||||
if replied_msg.reply_to:
|
||||
return await check_reply_chain(event, replied_msg.reply_to.reply_to_msg_id, depth + 1)
|
||||
|
||||
return False
|
||||
|
||||
# ==== Удаление системных сообщений о входе/выходе в целевой группе ====
|
||||
@client.on(events.ChatAction(chats=target_group_chat_id))
|
||||
async def del_join_leave(event: events):
|
||||
actions = {
|
||||
'добавлен': event.user_added,
|
||||
'присодинился': event.user_joined,
|
||||
'покинул': event.user_left,
|
||||
}
|
||||
if True in actions.values():
|
||||
action = [act for act, param in actions.items() if param]
|
||||
action = ', '.join(action)
|
||||
full_name = ' '.join([name for name in (event.user.first_name, event.user.last_name) if name])
|
||||
await event.delete()
|
||||
log.info(f"Удалено сообщение: Пользователь {full_name}({event.user_id}) {action} чат {target_group_chat_id}")
|
||||
|
||||
|
||||
async def fetch_system_messages(days_to_check=5) -> tuple[int, int]:
|
||||
"""Собирает системные сообщения за последние N дней"""
|
||||
system_messages = []
|
||||
|
||||
async with client:
|
||||
try:
|
||||
chat = await client.get_entity(target_group_chat_id)
|
||||
except ValueError:
|
||||
log.info("❌ Не удалось найти чат. Убедитесь, что вы состоите в группе.")
|
||||
return system_messages
|
||||
|
||||
log.info(f"🔍 Ищем системные сообщения в '{chat.title}' за последние {days_to_check} дней…\n")
|
||||
|
||||
today = datetime.now()
|
||||
cutoff_date = today - timedelta(days=days_to_check)
|
||||
|
||||
async for message in client.iter_messages(chat):
|
||||
# Проверяем дату
|
||||
if message.date.replace(tzinfo=None) < cutoff_date:
|
||||
continue
|
||||
|
||||
# Проверяем, является ли сообщение системным (ChatAction)
|
||||
if message.action:
|
||||
time_str = message.date.strftime('%Y-%m-%d %H:%M:%S')
|
||||
log.info(f"[{time_str}] | Тип действия: {message.action}")
|
||||
system_messages.append((chat.id, message.id))
|
||||
|
||||
log.info(f"✅ Найдено {len(system_messages)} системных сообщений для удаления")
|
||||
return system_messages
|
||||
|
||||
|
||||
async def delete_system_msgs(messages_list):
|
||||
"""Удаляет найденные системные сообщения"""
|
||||
if not messages_list:
|
||||
log.info("🚫 Нет сообщений для удаления")
|
||||
return
|
||||
|
||||
async with client:
|
||||
chat_id, _ = messages_list[0]
|
||||
message_ids = [msg_id for _, msg_id in messages_list]
|
||||
|
||||
result = await client.delete_messages(chat_id, message_ids)
|
||||
deleted_count = len(result._deleted)
|
||||
|
||||
log.info(f"🗑 Удалено {deleted_count} из {len(message_ids)} сообщений")
|
||||
|
||||
|
||||
# ==== Запуск бота ====
|
||||
async def main():
|
||||
await client.start()
|
||||
|
||||
# log.info("🧹 Начинаем очистку старых системных сообщений…")
|
||||
# messages = await fetch_system_messages(days_to_check=5)
|
||||
# await delete_system_msgs(messages)
|
||||
# if not client.is_connected():
|
||||
# log.info("🔄 Клиент не подключён, пытаемся восстановить соединение…")
|
||||
# await client.connect()
|
||||
|
||||
asyncio.create_task(monitor_messages())
|
||||
|
||||
log.info("😊 Бот запущен. Ожидание событий…")
|
||||
await client.run_until_disconnected()
|
||||
|
||||
# =======================
|
||||
if __name__ == '__main__':
|
||||
client.loop.run_until_complete(main())
|
||||
220
portable_install.bat
Normal file
220
portable_install.bat
Normal file
@ -0,0 +1,220 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
cd /d "%~dp0%"
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
REM Установка переменных
|
||||
set home_dir=%~dp0%
|
||||
set python_dir=python312
|
||||
set python_url=https://www.python.org/ftp/python/3.12.10/python-3.12.10-embed-amd64.zip
|
||||
|
||||
:start
|
||||
REM Проверяем, установлен ли уже 7za.exe
|
||||
if exist "%python_dir%\7za.exe" (move /y %python_dir%\7za.exe 7za.exe) >nul
|
||||
if exist 7za.exe (
|
||||
echo [ ] 7zip уже скачан: Использую локальную версию
|
||||
) else (
|
||||
echo [*] Скачивание 7zip
|
||||
certutil.exe -urlcache -split -f "https://www.7-zip.org/a/7zr.exe" 7zr.exe >nul
|
||||
certutil.exe -urlcache -split -f "https://www.7-zip.org/a/7z2500-extra.7z" 7z2500-extra.7z >nul
|
||||
7zr.exe x 7z2500-extra.7z 7za.exe -y >nul
|
||||
del 7zr.exe
|
||||
del 7z2500-extra.7z
|
||||
)
|
||||
|
||||
if exist "%python_dir%/python.exe" (
|
||||
for /f "tokens=2" %%V in ('cmd /c ^""%python_dir%\python.exe" --version^"') do set "python_version=%%V"
|
||||
echo [ ] Python уже скачан: Использую локальную версию !python_version!
|
||||
) else (
|
||||
echo [*] Скачивание Python
|
||||
certutil.exe -urlcache -split -f "https://www.python.org/ftp/python/3.12.10/python-3.12.10-embed-amd64.zip" python.zip >nul
|
||||
7za.exe x python.zip -o"%python_dir%" >nul
|
||||
for /f "tokens=2" %%V in ('cmd /c ^""%python_dir%\python.exe" --version^"') do set "python_version=%%V"
|
||||
for /f "tokens=1,2 delims=." %%a in ("!python_version!") do set "python_short_version=python%%a%%b"
|
||||
echo [*] Скачан Python !python_version!
|
||||
del python.zip
|
||||
|
||||
echo [*] Установка pip
|
||||
cd "%python_dir%"
|
||||
certutil.exe -urlcache -split -f "https://bootstrap.pypa.io/get-pip.py" get-pip.py >nul
|
||||
python.exe get-pip.py --no-warn-script-location
|
||||
del get-pip.py
|
||||
echo [*] Изменение !python_short_version!._pth
|
||||
echo Lib>> !python_short_version!._pth
|
||||
echo Lib\site-packages>> !python_short_version!._pth
|
||||
echo import site>> !python_short_version!._pth
|
||||
python.exe -m pip install --upgrade pip setuptools wheel --no-cache-dir --no-warn-script-location
|
||||
cd ..
|
||||
if exist "requirements.txt" (
|
||||
%python_dir%\python.exe -m pip install -r requirements.txt --no-cache-dir --no-warn-script-location
|
||||
)
|
||||
)
|
||||
|
||||
:venv_setup
|
||||
set update=False
|
||||
set no_changes=False
|
||||
if exist "%python_dir%\Scripts\activate.bat" (
|
||||
if exist "%python_dir%\pyvenv.cfg" (
|
||||
echo [ ] Виртуальное окружение уже сконфигурировано\
|
||||
|
||||
for /f "tokens=2 delims==" %%H in ('findstr /r "^base-executable[ ]*=" "%python_dir%\pyvenv.cfg"') do (set "installed_home=%%H")
|
||||
rem Удаляем пробелы и кавычки по краям
|
||||
for /f "tokens=* delims= " %%B in ("!installed_home!") do (set "installed_home=%%B")
|
||||
set "installed_home=!installed_home:"=!"
|
||||
rem Выводим для отладки
|
||||
echo Текущий путь в pyvenv.cfg: !installed_home!
|
||||
echo Ожидаемый путь: %home_dir%%python_dir%\python.exe
|
||||
|
||||
rem Сравниваем пути
|
||||
if /i "!installed_home!"=="%home_dir%%python_dir%\python.exe" (
|
||||
echo Конфигурация верная. Обновление не требуется
|
||||
set no_changes=True
|
||||
goto skip_venv
|
||||
) else (
|
||||
echo Путь портативной устаноки изменился.
|
||||
set /p "update=Требуется обновление. Обновить? [Y/Д] нет по умолчанию: "
|
||||
if /i "!update!"=="Y" (
|
||||
set update=True
|
||||
echo Обновляем...
|
||||
) else (
|
||||
if /i "!update!"=="Д" (
|
||||
set update=True
|
||||
echo Обновляем...
|
||||
goto venv_config
|
||||
)
|
||||
echo Пропускаем обновление.
|
||||
goto skip_venv
|
||||
)
|
||||
)
|
||||
))
|
||||
|
||||
:venv_config
|
||||
echo [*] Конфигурация виртуального окружения
|
||||
|
||||
if exist %python_dir%\Lib\site-packages\sitecustomize.py (
|
||||
echo [ ] Lib\site-packages\sitecustomize.py существует и не требует обновления
|
||||
goto skip_sitecustomize
|
||||
) else (
|
||||
echo [*] Создание sitecustomize.py для исправления site.getsitepackages и sys.prefix
|
||||
)
|
||||
(
|
||||
echo import site
|
||||
echo import os
|
||||
echo import sys
|
||||
echo project_root = os.path.abspath^(os.path.join^(os.getenv^('VIRTUAL_ENV'^), '..'^)^)
|
||||
echo if project_root in sys.path:
|
||||
echo sys.path.remove^(project_root^)
|
||||
echo sys.prefix = os.getenv^('VIRTUAL_ENV'^)
|
||||
echo sys.exec_prefix = os.getenv^('VIRTUAL_ENV'^)
|
||||
echo def getsitepackages^(^):
|
||||
echo return [os.path.join^(os.getenv^('VIRTUAL_ENV'^), 'Lib', 'site-packages'^)]
|
||||
echo site.getsitepackages = getsitepackages
|
||||
) > "%python_dir%\Lib\site-packages\sitecustomize.py"
|
||||
:skip_sitecustomize
|
||||
|
||||
echo [*] Создание %python_dir%\pyvenv.cfg
|
||||
(
|
||||
echo home = %home_dir%%python_dir%
|
||||
echo implementation = CPython
|
||||
echo version_info = %python_version%
|
||||
echo virtualenv = 20.31.2
|
||||
echo include-system-site-packages = false
|
||||
echo base-prefix = %home_dir%%python_dir%
|
||||
echo base-exec-prefix = %home_dir%%python_dir%
|
||||
echo base-executable = %home_dir%%python_dir%\python.exe
|
||||
) > "%python_dir%\pyvenv.cfg"
|
||||
|
||||
echo [*] Создание %python_dir%\Scripts\activate.bat
|
||||
(
|
||||
echo @echo off
|
||||
echo REM This file is UTF-8 encoded, so we need to update the current code page while executing it
|
||||
echo chcp 65001 ^> nul
|
||||
echo set "VIRTUAL_ENV=%home_dir%%python_dir%"
|
||||
echo set "VIRTUAL_ENV_PROMPT=%python_dir%"
|
||||
echo if defined _OLD_VIRTUAL_PROMPT ^(
|
||||
echo set "PROMPT=%%_OLD_VIRTUAL_PROMPT%%"
|
||||
echo ^) else ^(
|
||||
echo if not defined PROMPT ^(
|
||||
echo set "PROMPT=$P$G"
|
||||
echo ^)
|
||||
echo if not defined VIRTUAL_ENV_DISABLE_PROMPT ^(
|
||||
echo set "_OLD_VIRTUAL_PROMPT=%%PROMPT%%"
|
||||
echo ^)
|
||||
echo ^)
|
||||
echo if not defined VIRTUAL_ENV_DISABLE_PROMPT ^(
|
||||
echo set "PROMPT=(%%VIRTUAL_ENV_PROMPT%%) %%PROMPT%%"
|
||||
echo ^)
|
||||
echo if defined _OLD_VIRTUAL_PYTHONHOME ^(
|
||||
echo set "PYTHONHOME=%%_OLD_VIRTUAL_PYTHONHOME%%"
|
||||
echo ^) else ^(
|
||||
echo set "_OLD_VIRTUAL_PYTHONHOME=%%PYTHONHOME%%"
|
||||
echo ^)
|
||||
echo set "PYTHONHOME="
|
||||
echo if defined _OLD_VIRTUAL_PATH ^(
|
||||
echo set "PATH=%%_OLD_VIRTUAL_PATH%%"
|
||||
echo ^) else ^(
|
||||
echo set "_OLD_VIRTUAL_PATH=%%PATH%%"
|
||||
echo ^)
|
||||
echo set "PATH=%%VIRTUAL_ENV%%;%%VIRTUAL_ENV%%\Scripts;%%PATH%%"
|
||||
echo set "PYTHONPATH=%%VIRTUAL_ENV%%\Lib\site-packages"
|
||||
echo chcp %%_OLD_CODEPAGE%% ^> nul
|
||||
) > %python_dir%\Scripts\activate.bat
|
||||
:skip_venv
|
||||
|
||||
call %python_dir%\Scripts\activate.bat
|
||||
|
||||
if exist run_me.bat (
|
||||
echo [ ] run_me.bat существует, не требует обновления
|
||||
goto skip_run_me
|
||||
)
|
||||
echo [+] Создание run_me.bat
|
||||
(
|
||||
echo cd /d "%%~dp0%%"
|
||||
echo call %python_dir%\Scripts\activate.bat
|
||||
echo call python main.py
|
||||
echo pause
|
||||
) > run_me.bat
|
||||
:skip_run_me
|
||||
|
||||
REM Храним 7zip внутри папки Python
|
||||
if exist 7za.exe (move /y 7za.exe %python_dir%\7za.exe )>nul
|
||||
|
||||
if %no_changes%==True (
|
||||
set /p "reinstall=Изменений не внесено. Желаете переустановить? [Y/Д] нет по умолчанию: "
|
||||
if /i "!reinstall!"=="Y" (
|
||||
goto clear_installation
|
||||
) else (
|
||||
if /i "!reinstall!"=="Д" (goto clear_installation)
|
||||
)
|
||||
goto end
|
||||
) else (
|
||||
echo [✔️] Установка завершена
|
||||
pause
|
||||
goto end
|
||||
)
|
||||
:clear_installation
|
||||
set /p "reinstall_python=Скачать Python и пакеты заново? [Y/Д] нет по умолчанию: "
|
||||
if /i "!reinstall_python!"=="Y" (
|
||||
goto del_all_python
|
||||
) else (
|
||||
if /i "!reinstall_python!"=="Д" (goto del_all_python)
|
||||
)
|
||||
goto del_only_settings
|
||||
|
||||
:del_all_python
|
||||
if exist "%python_dir%\7za.exe" (move /y %python_dir%\7za.exe 7za.exe) >nul
|
||||
move /y %python_dir%\7za.exe 7za.exe>nul
|
||||
echo [-] Удаление Python
|
||||
rmdir /s /q %python_dir%
|
||||
goto start
|
||||
|
||||
:del_only_settings
|
||||
echo [-] Удаление настроек окружения
|
||||
del "%python_dir%\Lib\site-packages\sitecustomize.py"
|
||||
del "%python_dir%\pyvenv.cfg"
|
||||
del "%python_dir%\Scripts\activate.bat"
|
||||
del run_me.bat
|
||||
goto venv_setup
|
||||
|
||||
|
||||
:end
|
||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
Telethon==1.40.0
|
||||
dotenv==0.9.9
|
||||
24
telethon_get_chat_list.py
Normal file
24
telethon_get_chat_list.py
Normal file
@ -0,0 +1,24 @@
|
||||
import os
|
||||
from telethon import TelegramClient
|
||||
from dotenv import find_dotenv, load_dotenv
|
||||
|
||||
# === Загрузка переменных окружения ===
|
||||
env = find_dotenv()
|
||||
print(f'Использую: {env}')
|
||||
load_dotenv(env)
|
||||
|
||||
# === Данные юзер-бота ===
|
||||
api_id=26507458
|
||||
api_hash='9bf31965a06209eadd1995cec266d3ae'
|
||||
session_name='Joshua_session'
|
||||
|
||||
client = TelegramClient(session_name, api_id, api_hash)
|
||||
|
||||
async def get_group_info():
|
||||
async with client:
|
||||
groups = await client.get_dialogs()
|
||||
for dialog in groups:
|
||||
if dialog.is_group or dialog.is_channel:
|
||||
print(f'Название: {dialog.name} | ID: {dialog.entity.id}')
|
||||
|
||||
client.loop.run_until_complete(get_group_info())
|
||||
Loading…
x
Reference in New Issue
Block a user