Skip to content

Commit 8751bdc

Browse files
committed
Добавлен перебор папки с аккаунтами для парсинга на наличие аккаунтов в формате session.
1 parent 8dbf308 commit 8751bdc

1 file changed

Lines changed: 142 additions & 75 deletions

File tree

handlers/admin/admin.py

Lines changed: 142 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
22
import asyncio
3+
from pathlib import Path
34

45
from aiogram import F
56
from aiogram.fsm.context import FSMContext
@@ -57,22 +58,27 @@ async def admin_panel(message: Message, state: FSMContext):
5758
logger.exception(e)
5859

5960

61+
import os
62+
from pathlib import Path
63+
64+
6065
@router.message(F.text == "Актуализация базы данных")
6166
async def update_db(message: Message):
6267
"""
6368
Актуализация базы данных:
6469
обновление ID и типа групп/каналов.
6570
6671
Последовательность действий:
72+
- Сканирует папку accounts/parsing для поиска доступных сессий;
6773
- Подключается к Telegram API для получения метаданных по username;
6874
- Определяет тип сущности (канал, супергруппа и т.д.);
6975
- Обновляет записи в базе через прямой UPDATE-запрос;
70-
- Отправляет прогресс и статистику в чат администратора;
71-
- Обрабатывает FloodWaitError и другие исключения.
76+
- При FloodWaitError переключается на следующий аккаунт;
77+
- Отправляет прогресс и статистику в чат администратора.
7278
7379
Особенности:
7480
- Доступ только для администраторов;
75-
- Реализована защита от FloodWait;
81+
- Автоматическое переключение между аккаунтами при FloodWait;
7682
- Используется режим WAL для избежания блокировок БД.
7783
7884
:param message: (Message) Входящее сообщение от администратора.
@@ -82,25 +88,36 @@ async def update_db(message: Message):
8288
# 1. Выполняем миграцию (один раз за вызов)
8389
add_id_column()
8490

85-
# 2. Подключаемся к Telegram
86-
client = TelegramClient('accounts/parsing/998771571378', api_id, api_hash)
87-
await client.connect()
91+
# 2. Сканируем папку на наличие session-файлов
92+
sessions_dir = Path('accounts/parsing')
93+
session_files = list(sessions_dir.glob('*.session'))
94+
95+
if not session_files:
96+
await message.answer("❌ Не найдено ни одного session-файла в папке accounts/parsing")
97+
logger.error("Session-файлы не найдены")
98+
return
8899

89-
# 3. Небольшая пауза для стабильности
90-
await asyncio.sleep(1)
100+
# Получаем имена сессий (без расширения .session)
101+
available_sessions = [str(f.stem) for f in session_files]
102+
logger.info(f"Найдено {len(available_sessions)} аккаунтов: {available_sessions}")
103+
104+
await message.answer(
105+
f"🔍 Найдено аккаунтов: {len(available_sessions)}\n"
106+
f"📱 Аккаунты: {', '.join([s.split('/')[-1] for s in available_sessions])}"
107+
)
91108

92109
try:
93110
# 3. Убедимся, что БД подключена
94111
if db.is_closed():
95112
db.connect()
96113

97114
# 4. Получаем записи с username и group_type='group', которые ещё НЕ обновлены
98-
groups_to_update = TelegramGroup.select().where(
115+
groups_to_update = list(TelegramGroup.select().where(
99116
(TelegramGroup.username.is_null(False)) &
100117
(TelegramGroup.group_type == 'group')
101-
)
118+
))
102119

103-
total_count = groups_to_update.count()
120+
total_count = len(groups_to_update)
104121
logger.info(f"Найдено {total_count} групп для обновления")
105122

106123
# Отправляем начальное сообщение
@@ -109,78 +126,129 @@ async def update_db(message: Message):
109126
processed = 0
110127
updated = 0
111128
errors = 0
129+
current_session_index = 0
130+
131+
# 5. Основной цикл обработки групп
132+
while processed < total_count and current_session_index < len(available_sessions):
133+
# Подключаемся к текущему аккаунту
134+
session_path = f'accounts/parsing/{available_sessions[current_session_index]}'
135+
client = TelegramClient(session_path, api_id, api_hash)
112136

113-
for group in groups_to_update:
114137
try:
115-
# 5. Получаем сущность Telegram по username
116-
entity = await client.get_entity(group.username)
117-
118-
# 6. Определяем тип сущности
119-
if entity.megagroup:
120-
new_group_type = 'Группа (супергруппа)'
121-
elif entity.broadcast:
122-
new_group_type = 'Канал'
123-
else:
124-
new_group_type = 'Обычный чат (группа старого типа)'
125-
126-
# 7. Обновляем запись через UPDATE запрос
127-
TelegramGroup.update(
128-
id=entity.id,
129-
group_type=new_group_type
130-
).where(
131-
TelegramGroup.group_hash == group.group_hash
132-
).execute()
133-
134-
processed += 1
135-
updated += 1
136-
137-
logger.info(
138-
f"[{processed}/{total_count}] Обновлено: {group.username} | ID: {entity.id} | Тип: {new_group_type}"
139-
)
140-
141-
# Каждые 10 обновлений отправляем прогресс
142-
if processed % 10 == 0:
143-
await message.answer(
144-
f"📊 Прогресс: {processed}/{total_count}\n"
145-
f"✅ Обновлено: {updated}\n"
146-
f"❌ Ошибок: {errors}"
147-
)
148-
149-
# 8. Пауза для избежания бана от Telegram
150-
await asyncio.sleep(5)
151-
152-
except FloodWaitError as e:
153-
wait_time = e.seconds
154-
processed += 1
155-
errors += 1
156-
157-
logger.warning(
158-
f"FloodWait для {group.username}: нужно подождать {wait_time} секунд "
159-
f"({wait_time / 3600:.1f} часов). Останавливаем обработку."
160-
)
161-
162-
# Отправляем итоговую статистику при FloodWait
163-
await message.answer(
164-
f"⚠️ Telegram ограничил запросы.\n\n"
165-
f"📊 Обработано: {processed}/{total_count}\n"
166-
f"✅ Обновлено: {updated}\n"
167-
f"❌ Ошибок: {errors}\n\n"
168-
f"⏱ Необходимо подождать {wait_time / 3600:.1f} часов ({wait_time} сек)"
169-
)
170-
break # Останавливаем обработку
138+
await client.connect()
139+
await asyncio.sleep(1)
140+
141+
current_account = available_sessions[current_session_index].split('/')[-1]
142+
logger.info(f"Используется аккаунт: {current_account}")
143+
await message.answer(f"📱 Используется аккаунт: {current_account}")
144+
145+
# Обрабатываем группы с текущим аккаунтом
146+
for group in groups_to_update[processed:]:
147+
try:
148+
# Получаем сущность Telegram по username
149+
entity = await client.get_entity(group.username)
150+
151+
# Определяем тип сущности
152+
if entity.megagroup:
153+
new_group_type = 'Группа (супергруппа)'
154+
elif entity.broadcast:
155+
new_group_type = 'Канал'
156+
else:
157+
new_group_type = 'Обычный чат (группа старого типа)'
158+
159+
# Обновляем запись через UPDATE запрос
160+
TelegramGroup.update(
161+
id=entity.id,
162+
group_type=new_group_type
163+
).where(
164+
TelegramGroup.group_hash == group.group_hash
165+
).execute()
166+
167+
processed += 1
168+
updated += 1
169+
170+
logger.info(
171+
f"[{processed}/{total_count}] Обновлено: {group.username} | "
172+
f"ID: {entity.id} | Тип: {new_group_type}"
173+
)
174+
175+
# Каждые 10 обновлений отправляем прогресс
176+
if processed % 10 == 0:
177+
await message.answer(
178+
f"📊 Прогресс: {processed}/{total_count}\n"
179+
f"✅ Обновлено: {updated}\n"
180+
f"❌ Ошибок: {errors}\n"
181+
f"📱 Аккаунт: {current_account}"
182+
)
183+
184+
# Пауза для избежания бана от Telegram
185+
await asyncio.sleep(5)
186+
187+
except FloodWaitError as e:
188+
wait_time = e.seconds
189+
errors += 1
190+
191+
logger.warning(
192+
f"FloodWait для {group.username} (аккаунт {current_account}): "
193+
f"нужно подождать {wait_time} секунд ({wait_time / 3600:.1f} часов)"
194+
)
195+
196+
# Отправляем уведомление о FloodWait
197+
await message.answer(
198+
f"⚠️ FloodWait на аккаунте {current_account}\n\n"
199+
f"📊 Обработано: {processed}/{total_count}\n"
200+
f"✅ Обновлено: {updated}\n"
201+
f"❌ Ошибок: {errors}\n\n"
202+
f"⏱ Ожидание: {wait_time / 3600:.1f} ч ({wait_time} сек)"
203+
)
204+
205+
# Переключаемся на следующий аккаунт
206+
current_session_index += 1
207+
208+
if current_session_index < len(available_sessions):
209+
await message.answer(
210+
f"🔄 Переключаюсь на аккаунт "
211+
f"{available_sessions[current_session_index].split('/')[-1]}"
212+
)
213+
else:
214+
await message.answer(
215+
"❌ Все аккаунты исчерпаны. Актуализация остановлена."
216+
)
217+
218+
break # Выходим из цикла групп, переключаемся на новый аккаунт
219+
220+
except Exception as e:
221+
processed += 1
222+
errors += 1
223+
logger.error(
224+
f"[{processed}/{total_count}] Ошибка при обработке "
225+
f"{group.username}: {e}"
226+
)
171227

172228
except Exception as e:
173-
processed += 1
174-
errors += 1
175-
logger.error(f"[{processed}/{total_count}] Ошибка при обработке {group.username}: {e}")
229+
logger.error(f"Ошибка подключения к аккаунту {current_account}: {e}")
230+
await message.answer(f"❌ Ошибка аккаунта {current_account}: {e}")
231+
current_session_index += 1
176232

177-
# Финальная статистика (если не было FloodWait)
178-
else:
233+
finally:
234+
await client.disconnect()
235+
236+
# Финальная статистика
237+
if processed >= total_count:
179238
await message.answer(
180239
f"✅ Актуализация завершена!\n\n"
181240
f"📊 Всего обработано: {processed}/{total_count}\n"
182241
f"✅ Успешно обновлено: {updated}\n"
183-
f"❌ Ошибок: {errors}"
242+
f"❌ Ошибок: {errors}\n"
243+
f"📱 Использовано аккаунтов: {current_session_index + 1}/{len(available_sessions)}"
244+
)
245+
else:
246+
await message.answer(
247+
f"⚠️ Актуализация остановлена.\n\n"
248+
f"📊 Обработано: {processed}/{total_count}\n"
249+
f"✅ Успешно обновлено: {updated}\n"
250+
f"❌ Ошибок: {errors}\n"
251+
f"📱 Все {len(available_sessions)} аккаунтов исчерпаны"
184252
)
185253

186254
except Exception as e:
@@ -191,7 +259,6 @@ async def update_db(message: Message):
191259
if not db.is_closed():
192260
db.close()
193261

194-
await client.disconnect()
195262
logger.info("Актуализация завершена.")
196263

197264

0 commit comments

Comments
 (0)