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