Skip to content

Commit

Permalink
Init
Browse files Browse the repository at this point in the history
  • Loading branch information
lynrayy committed Apr 24, 2024
0 parents commit 11c6237
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 0 deletions.
39 changes: 39 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import auth
from peewee import Model, BigIntegerField, BooleanField, SqliteDatabase, FloatField
from pyrogram import Client


app = Client("ChannelArchiver",
auth.api_id,
auth.api_hash,
app_version='Archiver 0.0.5',
device_model='Xiaomi MI 9',
system_version='Android 11 R', phone_number=auth.phone_number)

_db = SqliteDatabase('posts.db')


class Post(Model):
source_channel_id = BigIntegerField()
source_msg_id = BigIntegerField()
source_post_timestamp = FloatField(null=True)
archive_channel_id = BigIntegerField(null=True)
archive_msg_id = BigIntegerField(null=True)

is_media_group = BooleanField(default=False)
restored_to_deleted_msgs_channel = BooleanField(default=False)

class Meta:
database = _db


class MediaGroup(Model):
source_channel_id = BigIntegerField()
source_mg_id = BigIntegerField()

class Meta:
database = _db


_db.connect()
_db.create_tables([Post, MediaGroup])
23 changes: 23 additions & 0 deletions auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Где взять api ID и api HASH?
# Логинимся на https://my.telegram.org/auth
# Переходим на API development tools (https://my.telegram.org/apps)
# Заполните данные как вам будет удобнее
# После чего вам станут доступны app api ID и app api HASH

# App api_id
api_id = 12345678

# App api_hash
api_hash = "a1b2c3d4e5f6g7h8i9"

# Здесь вам нужно ввести свой номер телефона.
# Это нужно т.к. этот бот работает от лица человека, а не бота. По-другому сохранение
# каналов сделать невозможно.

# Номер телефона от телеграм аккаунта
phone_number = "+79994441122"

# После первого запуска бота вам придёт в лс код авторизации, его надо будет ввести в консоль.
# Если у вас установлен облачный пароль, после кода авторизации вам надо будет ввести его в консоль.

# Что-бы удалить аккаунт, остановите бота и удалите файл ChannelArchiver.session
26 changes: 26 additions & 0 deletions config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Как узнать ID канала?
# Способ 1 (Универсальный):
# Переслать пост из канала боту https://t.me/MissRose_bot
# В ответ на пересланный пост написать команду /id
#
# Способ 2 (Для ПК, Telegram Desktop):
# Зайдите в продвинутые настройки
# Перейдите в экспериментальные настройки
# Включите [Show Peer IDs in Profile]
# Откройте описание канала, там будет его ID

# ID канала ВСЕГДА начинается с -100. Способ 1 даст вам именно такой ID.
# В способе 2 надо вручную дописать -100 в начале

# ID Канала, откуда бот берёт посты (источник)
source_channel_id = -10011111111

# ID Канала, куда бот сохраняет вообще все посты из источника (архив)
archive_channel_id = -10022222222

# ID Канала, куда бот пересылает удалённые в источнике посты (из архива в удалёнки)
deleted_channel_id = -10033333333

# Сохранять ли посты репостами или от лица канала-архива?
# False - Хранить репосты, True - Хранить от лица архива
store_as_archive = True
2 changes: 2 additions & 0 deletions handlers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .channel_post_new import on_new_post, PostNewHandler
from .channel_post_deleted import on_del_post, PostDelHandler
34 changes: 34 additions & 0 deletions handlers/channel_post_deleted.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from pyrogram.types import Message
from pyrogram import Client, filters
from app import app, Post
from typing import List
from datetime import datetime, timedelta
import config


async def send_notif(client, chat_id, timestamp, title):
time = datetime.fromtimestamp(timestamp) + timedelta(hours=3)
try:
await client.send_message(chat_id, f"<b>🗑️ В канале {title} \n"
f"удалён пост от</b> {time.strftime(f'%d.%m.%Y %H:%M')} по МСК ⬇️")
except Exception as e:
print(f"{datetime.now().strftime('%H:%M %d.%m.%Y')} Нет доступа к каналу для сохранения удалённых сообщений, пост не сохранён.", e)


@app.on_deleted_messages(filters.channel & filters.chat(config.source_channel_id))
async def on_del_post(client: Client, messages_list: List[Message]):
src_channel = await client.get_chat(messages_list[0].chat.id)
src_title = src_channel.title
for message in messages_list:
source_post: Post = Post.get_or_none(source_channel_id=message.chat.id, source_msg_id=message.id)
if source_post is None: continue
if source_post.is_media_group:
messages = await client.get_media_group(source_post.archive_channel_id, source_post.archive_msg_id)
message_ids = [_message.id for _message in messages]
await send_notif(client, config.deleted_channel_id, source_post.source_post_timestamp, src_title)
await client.forward_messages(config.deleted_channel_id, source_post.archive_channel_id, message_ids)
else:
await send_notif(client, config.deleted_channel_id, source_post.source_post_timestamp, src_title)
await client.forward_messages(config.deleted_channel_id, source_post.archive_channel_id, source_post.archive_msg_id)

PostDelHandler = ...
57 changes: 57 additions & 0 deletions handlers/channel_post_new.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from pyrogram.types import Message
from pyrogram import Client, filters
from app import app, Post, MediaGroup
from datetime import datetime
import config


@app.on_message(filters.channel & filters.chat(config.source_channel_id))
async def on_new_post(client: Client, message: Message):
if message.media_group_id is not None:
mgid, is_mgid_new = MediaGroup.get_or_create(source_channel_id=message.chat.id, source_mg_id=message.media_group_id)
if not is_mgid_new: return
title = message.chat.title
try:
archive = await app.get_chat(config.archive_channel_id)
except Exception as e:
print(f"{datetime.now().strftime('%H:%M %d.%m.%Y')} Нет доступа к каналу-архиву, новый пост из источника ({title}) не сохранён!", e)
return
archive_title = archive.title

post, _ = Post.get_or_create(source_channel_id=message.chat.id, source_msg_id=message.id)
post: Post
if message.media_group_id is None:
try:
if config.store_as_archive:
sent = await client.copy_message(config.archive_channel_id, message.chat.id, message.id) # Вариант с копированием постов
else:
sent = await client.forward_messages(config.archive_channel_id, message.chat.id, message.id) # Вариант с репостом
except Exception as e:
print(f"{datetime.now().strftime('%H:%M %d.%m.%Y')} Невозможно сохранить пост в канал-архив ({archive_title}), новый пост из источника ({title}) не сохранён!", e)
return
else:
try:
if config.store_as_archive:
sents = await client.copy_media_group(config.archive_channel_id, message.chat.id, message.id) # Вариант с копированием
else:
messages = await client.get_media_group(message.chat.id, message.id)
message_ids = [_message.id for _message in messages]
sents = await client.forward_messages(config.archive_channel_id, message.chat.id, message_ids)
except Exception as e:
print(f"{datetime.now().strftime('%H:%M %d.%m.%Y')} Невозможно сохранить пост в канал-архив ({archive_title}), новый пост из источника ({title}) не сохранён!", e)
return


sent: Message = sents[0]
post.is_media_group = True


# print("\n\nMESSAGE", message)
# print("\n\nSENT", sent)
post.archive_channel_id = sent.chat.id
post.archive_msg_id = sent.id
post.source_post_timestamp = datetime.utcnow().timestamp()
post.save()
print(f"{datetime.now().strftime('%H:%M %d.%m.%Y')} В источнике ({title}) опубликован новый пост, сохранено.")

PostNewHandler = ...
13 changes: 13 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from app import app


def main():
while True:
try:
app.run()
except Exception as e:
print(e)


if __name__ == '__main__':
main()
3 changes: 3 additions & 0 deletions start.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
title TG Channel-Archiver Bot
"venv/Scripts/python.exe" "main.py"
pause

0 comments on commit 11c6237

Please sign in to comment.