diff --git a/example_config.yaml b/example_config.yaml index dafac10..eb86d17 100644 --- a/example_config.yaml +++ b/example_config.yaml @@ -11,16 +11,36 @@ config: storage_chat: -1001222674489 storage_message_id: 1367 send_to_chats: - - goodanimemes: - - goodanimemes - - -1001327025649: - - ProgrammerAnimemes - - memes10k: - - linuxmemes - - dankmemes - - memes - - ShitPostCrusaders + gooanimemes: + subreddits: + - goodanimemes + cron_duration: 0 * * * * + allow_selfposts: true + allow_nsfw: true + allow_spoilers: true + show_nsfw_warning: true + show_spoilers_warning: true + -1001284025455: + subreddits: + - HentaiMemes + cron_duration: 0 * * * * + allow_selfposts: true + allow_nsfw: true + allow_spoilers: true + show_nsfw_warning: false + show_spoilers_warning: true + memes10k: + subreddits: + - linuxmemes + - dankmemes + - memes + - ShitPostCrusaders + cron_duration: "*/30 * * * *" + allow_selfposts: false + allow_nsfw: true + allow_spoilers: true + show_nsfw_warning: true + show_spoilers_warning: true bot_admins: - thekneesocks - 214416808 - cron_duration: 0 * * * * diff --git a/redditbot.py b/redditbot.py index a781a5d..66a86be 100644 --- a/redditbot.py +++ b/redditbot.py @@ -32,20 +32,26 @@ reddit_client_secret = config_data['reddit']['client_secret'] storage_chat = config_data['config'].get('storage_chat') storage_msg_id = config_data['config'].get('storage_message_id') _bkup_subreddits = config_data['config'].get('subreddits') -_send_to_chats = config_data['config']['send_to_chats'] -send_to_chats = dict() -for chat in _send_to_chats: - subs = None - if isinstance(chat, dict): - subs = tuple(chat.values())[0] - chat = tuple(chat.keys())[0] - send_to_chats[chat] = subs +_send_to_chats = send_to_chats = config_data['config']['send_to_chats'] +if isinstance(_send_to_chats, list): + send_to_chats = dict() + for i in _send_to_chats: + j = None + if isinstance(i, dict): + j = tuple(i.values())[0] + i = tuple(i.keys())[0] + if isinstance(j, list) or not j: + j = {'subreddits': j, 'cron_duration': config_data['config']['cron_duration'], + 'allow_selfposts': True, 'allow_nsfw': True, + 'allow_spoilers': True, 'show_nsfw_warning': True, + 'show_spoilers_warning': True} + send_to_chats[i] = j bot_admins = config_data['config']['bot_admins'] -cron_duration = config_data['config']['cron_duration'] logging.basicConfig(level=logging.INFO) async def main(): zws = '\u200b' + _added_chats = [] client = await TelegramClient('redditbot', tg_api_id, tg_api_hash).start(bot_token=bot_token) client.parse_mode = 'html' session = aiohttp.ClientSession() @@ -63,62 +69,112 @@ async def main(): seen_posts = {'version': 0, 'chats': {'global': []}} # chat dict: {chatid: [array of submission ids]} + uploading_lock = asyncio.Lock() async def write_seen_posts(): with open('redditbot.json', 'w') as file: json.dump(seen_posts, file) if storage_chat and storage_msg_id: - await client.edit_message(storage_chat, storage_msg_id, file='redditbot.json') + async with uploading_lock: + await client.edit_message(storage_chat, storage_msg_id, file='redditbot.json') - @aiocron.crontab(cron_duration) - async def start_post(): - global_sp = seen_posts['chats']['global'] - for chat in send_to_chats: - uses_bkupsub = False - subreddits = send_to_chats[chat] - if not subreddits: - subreddits = _bkup_subreddits - uses_bkupsub = True + async def add_chat(chat, chat_data): + global_sp = chat_sp = seen_posts['chats']['global'] + subreddits = chat_data['subreddits'] + if subreddits: chat = await client.get_peer_id(chat) if str(chat) not in seen_posts['chats']: seen_posts['chats'][str(chat)] = [] - chat_sp = global_sp if uses_bkupsub else seen_posts['chats'][str(chat)] + chat_sp = seen_posts['chats'][str(chat)] + else: + subreddits = _bkup_subreddits.copy() + cron_duration = chat_data['cron_duration'] + allow_selfposts = chat_data['allow_selfposts'] + allow_nsfw = chat_data['allow_nsfw'] + allow_spoilers = chat_data['allow_spoilers'] + show_nsfw_warning = chat_data['show_nsfw_warning'] + show_spoilers_warning = chat_data['show_spoilers_warning'] + + @aiocron.crontab(cron_duration) + async def start_post(): while True: random.shuffle(subreddits) - to_break = False for subreddit_name in subreddits: subreddit = reddit.subreddit(subreddit_name) while True: random_post = subreddit.random() - cpid = None + cpid = cpp = None if random_post is None: for submission in subreddit.hot(): cpid = getattr(submission, 'crosspost_parent', None) - if cpid: + if cpid and getattr(random_post, 'crosspost_parent_list', None): cpid = cpid[3:] if submission.id in chat_sp + global_sp or cpid in chat_sp + global_sp: continue + if not (allow_selfposts and allow_nsfw and allow_spoilers): + is_self = submission.is_self + nsfw = submission.over_18 + spoilers = submission.spoiler + if cpid: + cpp = reddit.submission(cpid) + if not allow_selfposts: + is_self = cpp.is_self + if not (nsfw and allow_nsfw): + nsfw = cpp.over_18 + if not (spoilers and allow_spoilers): + nsfw = cpp.spoiler + if is_self and not allow_selfposts: + continue + if nsfw and not allow_nsfw: + continue + if spoilers and not allow_spoilers: + continue random_post = submission break cpid = getattr(random_post, 'crosspost_parent', None) - if cpid: + if cpid and getattr(random_post, 'crosspost_parent_list', None): cpid = cpid[3:] if random_post.id in chat_sp + global_sp or cpid in chat_sp + global_sp: continue + if not (allow_selfposts and allow_nsfw and allow_spoilers): + is_self = random_post.is_self + nsfw = random_post.over_18 + spoilers = random_post.spoiler + if cpid and not cpp: + cpp = reddit.submission(cpid) + if cpid: + if not allow_selfposts: + is_self = cpp.is_self + if not (nsfw and allow_nsfw): + nsfw = cpp.over_18 + if not (spoilers and allow_spoilers): + nsfw = cpp.spoiler + if is_self and not allow_selfposts: + continue + if nsfw and not allow_nsfw: + continue + if spoilers and not allow_spoilers: + continue chat_sp.append(cpid or random_post.id) print(random_post.id, random_post.shortlink) - to_break = True - break - if to_break: break + else: + continue + break try: - await _actual_start_post(random_post, [chat]) + await _actual_start_post(random_post, [chat], cpp, show_nsfw_warning, show_spoilers_warning) except Exception: logging.exception(random_post.id) for i in bot_admins: await client.send_message(i, f'{random_post.id}\n{traceback.format_exc()}', parse_mode=None) else: break - await write_seen_posts() + await write_seen_posts() + + _added_chats.append(start_post) + + for chat in send_to_chats: + print(chat, send_to_chats[chat]) + await add_chat(chat, send_to_chats[chat]) async def _start_broadcast(text, file, chats): uploaded_files = [] @@ -162,12 +218,24 @@ async def main(): ext = '.' + ext return ext - async def _actual_start_post(random_post, chats): + async def _actual_start_post(random_post, chats, cpp=None, snw=None, ssw=None): text = f'{html.escape(random_post.title)}' + nsfw = random_post.over_18 + spoilers = random_post.spoiler cpid = getattr(random_post, 'crosspost_parent', None) - if cpid and getattr(random_post, 'crosspost_parent_list', None): - random_post = reddit.submission(cpid[3:]) + if cpid and getattr(random_post, 'crosspost_parent_list', None) and not cpp: + cpp = reddit.submission(cpid[3:]) + if cpp: + random_post = cpp + if snw and not nsfw: + nsfw = random_post.over_18 + if ssw and not spoilers: + spoilers = random_post.spoiler text += f' (crosspost of {html.escape(random_post.title)})' + if spoilers and ssw: + text = '🙈🙈🙈 SPOILERS 🙈🙈🙈\n' + text + if nsfw and snw: + text = '🔞🔞🔞 18+ / NSFW 🔞🔞🔞\n' + text if not random_post.is_self: with tempfile.TemporaryDirectory() as tempdir: url = random_post.url @@ -333,20 +401,23 @@ async def main(): await e.reply(('/start - /help\n' '/help - /start\n' '/poweroff - shuts down bot\n' - '/test - tests sending submission'), parse_mode=None) + '/test [ns] - tests sending submission'), parse_mode=None) @register('/poweroff') async def poweroff(e): await e.reply('ok') await e.client.disconnect() - @register('/test (.+)') + @register(r'/test (\S+)(?: ([ns]+))?') async def test_post(e): await e.reply('ok') post = reddit.submission(e.pattern_match.group(1)) - await _actual_start_post(post, [e.chat_id]) + flags = e.pattern_match.group(2) or '' + snw = 'n' in flags + ssw = 's' in flags + await _actual_start_post(post, [e.chat_id], None, snw, ssw) -# await start_post.func() +# await asyncio.gather(*[i.func() for i in _added_chats]) try: await client.run_until_disconnected() finally: