Last active
August 27, 2022 16:59
-
-
Save uburuntu/b9688f786e4988d5b4468c3bb2d96dee to your computer and use it in GitHub Desktop.
Telegram channel table of contents generation with links | t.me/unrelated
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import Counter | |
import telebot | |
def md_link(text, link): | |
return f'[{text}]({link})' | |
def md_bold(text): | |
return f'*{text}*' | |
def md_italic(text): | |
return f'_{text}_' | |
class Channel: | |
def __init__(self, channel_name, channel_posts_num, token, proxy=None): | |
self.channel = channel_name | |
self.channel_mention = '@{}'.format(self.channel) | |
self.channel_posts_num = channel_posts_num | |
self.bot = telebot.TeleBot(token) | |
if proxy: | |
# Proxy format: 'socks5://user:pswd@host:port' | |
telebot.apihelper.proxy = {'https': proxy} | |
def link(self, text, number=None, outer_channel=None): | |
return md_link(outer_channel and f'{outer_channel}/{text}' or text, f't.me/{outer_channel or self.channel}/{number or text}') | |
def item(self, text, *numbers, final=None, outer_channel=None): | |
links = ', '.join(map(lambda x: self.link(x, outer_channel=outer_channel), numbers)) | |
if links and final: | |
links = f'{links}, ' | |
return f'{text} ({links}итоговый: {self.link(final, outer_channel=outer_channel)})' if final else f'{text} ({links})' | |
@staticmethod | |
def listed(*args, sep=', '): | |
return '• {}:{}{}\n\n'.format(md_bold(args[0]), sep if '\n' in sep else ' ', sep.join(args[1:])) | |
@staticmethod | |
def post_header(): | |
# Animated preview: canva.com + imgur.com/upload, 1280x720, keep audio for better fit | |
text = md_link('📝', 'https://i.imgur.com/MVdfBYI.mp4') + md_bold(' Содержание канала\n\n') | |
return text | |
def post_body(self): | |
text = '' | |
item = self.item | |
text += self.listed( | |
'Путешествия', | |
item('🇷🇺 / Переславль-Залесский', 378, final=415), | |
item('🇨🇿 / Прага', 421, final=446), | |
item('🇩🇪 / Мюнхен', 447, final=456), | |
item('🇮🇹 / Милан и Комо', 457, final=486), | |
item('🇪🇺 / Итоговый про Евротур\'18', 488), | |
item('🇬🇪 / Тбилиси', final=548), | |
item('🇬🇪 / Казбеги', 549, final=571), | |
item('🇬🇪 / Батуми и Кобулети', 572, final=575), | |
item('🇷🇺 / Мурманск', final=691), | |
item('🇷🇺 / Кострома', 701, final=708), | |
item('🇷🇺 / Питер\'19', final=759), | |
item('🇩🇪 / Берлин', 835), | |
item('🇩🇰 / Копенгаген', 8, outer_channel='faroes'), | |
item('🇫🇴 / Фарерские острова', 169, outer_channel='faroes'), | |
item('🇷🇺 / Йошкар-Ола и Чебоксары', 892, final=912), | |
item('🇷🇺 / Байкал', 944, final=975), | |
item('🇷🇺 / Калининград', 1019), | |
item('🇷🇺 / Шерегеш', final=1074), | |
sep='\n— ' | |
) | |
text += self.listed( | |
'Проекты', | |
item('бот знакомств', 800), | |
item('Rawg', 866), | |
item('Skobochka', 941), | |
item('репосты из VK в Telegram', 1007), | |
item('MSU Hub Bot', 1043), | |
item('Yandex Weather', 1059), | |
) | |
text += self.listed( | |
'Мысли и лонгриды', | |
item('почему Firefox', 982), | |
item('как сидеть в интернете', 986), | |
item('преподавание Python', 987), | |
item('как пользоваться Windows', 1016, 1017), | |
item('облачный гейминг', 1060), | |
) | |
text += self.listed( | |
'Что-то полезное', | |
item('to-do листы', 276), | |
item('учёт трат с друзьями', 576), | |
item('интернет заграницей', 580), | |
item('обход рекламы в метро', 607), | |
item('халява от GitHub', 620), | |
item('чистить сайты', 992), | |
) | |
text += self.listed( | |
'Про дизайн и типографию', | |
item('тире и дефисы', 270), | |
item('типографская раскладка', 350), | |
item('курс благородного набора', 351), | |
'а также много маленьких постов по всему каналу', | |
) | |
text += self.listed( | |
'Про игры', | |
item('отыгрыш в Project Zomboid', 307), | |
item('Minecraft', 612), | |
item('выбор в Divinity', 633), | |
item('Marvel\'s Spider-Man', 664), | |
item('ролёвка с пепой', 732), | |
item('Java-игры', 811), | |
item('Uncharted', 824), | |
item('Cyberpunk 2077', 1062), | |
) | |
text += self.listed( | |
'YouTube и рекомендации к просмотру', | |
item('канал Chuck\_review', 305), | |
item('Final Space', 538), | |
item('выхожу из дома', 660), | |
item('Jetson Nano', 846), | |
item('Eyes Wide Shut', 936), | |
item('канал Stopgame', 978), | |
) | |
text += self.listed( | |
'Философия жизни и опросы', | |
item('порядок в мелочах', 348), | |
item('убираться в маке', 541), | |
item('если ты зол', 595), | |
item('грустные пепы', 621), | |
item('бытие и сознание', 622, 623), | |
item('нахуй человеков', 915), | |
) | |
text += self.listed( | |
'Разное', | |
item('про тазик и кипяток', 294), | |
item('Banksy', 352), | |
item('фестиваль Бессонница', 492), | |
item('чеченская свадьба', 507), | |
item('экспорт данных Telegram', 578), | |
item('Uno Moralez', 602), | |
item('Ramzan is dead', 641), | |
item('армейская стори', 684), | |
item('лагерь Университетский', 790), | |
item('бал МГУ', 814), | |
item('посылки из прошлого', 758, 883), | |
item('дрон как кулер', 1037), | |
) | |
return text | |
def post_footer(self, with_markers=False, with_delimiter=False): | |
text = '' | |
if with_markers: | |
text += self.listed('Указатели', self.markers_gen()) | |
if with_delimiter: | |
text += f'```{"—" * 60}```\n' | |
text += 'Автор канала: @rm\_bk, rmbk.me.\n' | |
return text | |
def whole_post(self): | |
text = self.post_header() + self.post_body() + self.post_footer() | |
print(text, '—' * 30, sep='\n', end='\n\n') | |
print('Symbols in message: ', len(text)) | |
return text | |
def markers_gen(self, step=200): | |
text = self.link('1') | |
for curr in range(step, self.channel_posts_num, step): | |
text += ', {}'.format(self.link(curr)) | |
text += ', {}'.format(self.link(self.channel_posts_num)) | |
return text | |
def send_post(self, chat_id): | |
result_msg = self.bot.send_message(text=self.whole_post(), | |
chat_id=chat_id or self.channel_mention, | |
parse_mode='Markdown') | |
print('Message sent, message_id: {}'.format(result_msg.message_id)) | |
return result_msg | |
def edit_post(self, chat_id, message_id): | |
result_msg = self.bot.edit_message_text(text=self.whole_post(), | |
chat_id=chat_id or self.channel_mention, message_id=message_id, | |
parse_mode='Markdown') | |
print('Message edited, message_id: {}'.format(result_msg.message_id)) | |
return result_msg | |
if __name__ == '__main__': | |
# Script arguments | |
channel_name = 'unrelated' | |
channel_posts_num = 1080 | |
token = 'TOKEN' | |
message_to_edit = 582 # None for new message | |
message_testing_dest = None # None for posting in channel | |
# Run | |
channel = Channel(channel_name, channel_posts_num, token) | |
if message_to_edit: | |
msg = channel.edit_post(message_testing_dest, message_to_edit) | |
else: | |
msg = channel.send_post(message_testing_dest) | |
if msg and msg.entities: | |
# Only first 100 markdown entities are displayed | |
print('Entities: ', Counter(map(lambda x: x.type, msg.entities)).most_common()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment