Skip to content

Instantly share code, notes, and snippets.

@uburuntu
Last active August 27, 2022 16:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uburuntu/b9688f786e4988d5b4468c3bb2d96dee to your computer and use it in GitHub Desktop.
Save uburuntu/b9688f786e4988d5b4468c3bb2d96dee to your computer and use it in GitHub Desktop.
Telegram channel table of contents generation with links | t.me/unrelated
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