def main(mods, defaults, cousins): if defaults: mods = set(mods) mods.union(settings.DEFAULT_MODS) mods = list(mods) if not mods: print('No moderators specified. Quitting.') return r = Reddit('Mass Moderator Invite v0.1 /u/{}'.format(settings.USERNAME)) r.oauth() subs = [sub['name'] for sub in settings.CHILD_SUBS] if cousins: cuzs = set(sub['name'] for sub in settings.COUSIN_SUBS) cuzs.update(subs) subs = sorted(cuzs) for sub in subs: s = r.get_subreddit(sub) cur_mods = [u.name for u in s.get_moderators()] need_mods = [m for m in mods if m not in cur_mods] if not need_mods: print('No mods needed for /r/{}.'.format(sub)) for mod in need_mods: print('Inviting {} to moderate /r/{}.'.format(mod, sub)) s.add_moderator(mod)
def main(): """Discord Announcer Bot to relay specified information to designated Discord channels.""" r = Reddit('{} Discord Announcer v1.0 - /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() b = DiscordBot(r) b.run()
def main(no_post): """Reddit Network scraper and x-poster bot.""" r = Reddit('{} v6.0 /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() b = Bot(r, should_post=not no_post) b.run()
def main(): """Discord Announcer Bot to relay specified information to designated Discord channels.""" r = Reddit('{} Discord Announcer v1.0 - /u/{}'.format( settings.NETWORK_NAME, settings.USERNAME)) r.oauth() b = DiscordBot(r) b.run()
def main(): """ Check for blacklist requests and add users to blacklist. """ r = Reddit('{} Update User-Requested Blacklist v0.3 /u/{}' .format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() process_modmail(r) process_inbox(r)
def on_ready(): LOG.info('discord.client: on_ready...') LOG.info('discord.client: Logged in as {}'.format(CLIENT.user.name)) inbox_id = '183018837883617280' inbox_chan = CLIENT.get_channel(inbox_id) falsepos_id = '183605928514420736' falsepos_chan = CLIENT.get_channel(falsepos_id) LOG.info('Logging into reddit...') r = Reddit('{} Inbox-to-Discord Relay v0.1 - /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() LOG.info('Checking for new messages...') for message in r.get_unread(limit=None): sleep(1) if (message.body == 'remove') or ('mod removal' in message.body): # Don't announce 'remove' replies LOG.info('Not announcing message type: "remove"') message.mark_as_read() continue elif 'blacklist me' in message.subject: # Don't announce blacklist requests LOG.info('Not announcing message type: "blacklist request"') message.mark_as_read() continue elif (message.author.name == 'AutoModerator') or (message.author.name == 'reddit'): message.mark_as_read() LOG.info('Not announcing message type: "AutoMod Response"') continue else: LOG.info('Announcing new inbox item type: {}'.format(types[message.name[:2]])) if 'false positive' in message.body.lower(): LOG.info('- Announcing false-positive reply...') notification = "**New __false-positive__:** {}\n---".format(message.permalink[:-7]) yield from CLIENT.send_message(falsepos_chan, notification) else: notification = format_message(message) LOG.info('- Announcing inbox message...') yield from CLIENT.send_message(inbox_chan, notification) message.mark_as_read() exit
def main(topic, start_at, only, dry_run): """Prop up new subreddit and set it for the network.""" global DRY_RUN DRY_RUN = dry_run if not DRY_RUN: r = Reddit('Expand {} Network v0.2 /u/{}' .format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() else: r = None topic = ' '.join(topic) nice_topic = ''.join(re.findall('[A-Za-z0-9]', topic)) sub = settings.NETWORK_NAME + ''.join(nice_topic) # little helper script to check if we're at or after # where we want to start. def should_do(point): point_idx = _start_points.index(point) if only: only_idx = _start_points.index(only) return only_idx == point_idx elif start_at: start_idx = _start_points.index(start_at) return start_idx <= point_idx return True if should_do('creation'): create_sub(r, sub) if should_do('settings'): copy_settings(r, sub, topic) if should_do('mods'): invite_mods(r, sub) if should_do('wiki'): copy_wiki_pages(r, sub) if should_do('flair'): setup_flair(r, sub) if should_do('multireddit'): add_to_multi(r, sub) if should_do('notifications'): setup_notifications(r, sub)
def main(topic, start_at, only, dry_run): """Prop up new subreddit and set it for the network.""" global DRY_RUN DRY_RUN = dry_run if not DRY_RUN: r = Reddit('Expand {} Network v0.2 /u/{}'.format( settings.NETWORK_NAME, settings.USERNAME)) r.oauth() else: r = None topic = ' '.join(topic) nice_topic = ''.join(re.findall('[A-Za-z0-9]', topic)) sub = settings.NETWORK_NAME + ''.join(nice_topic) # little helper script to check if we're at or after # where we want to start. def should_do(point): point_idx = _start_points.index(point) if only: only_idx = _start_points.index(only) return only_idx == point_idx elif start_at: start_idx = _start_points.index(start_at) return start_idx <= point_idx return True if should_do('creation'): create_sub(r, sub) if should_do('settings'): copy_settings(r, sub, topic) if should_do('mods'): invite_mods(r, sub) if should_do('wiki'): copy_wiki_pages(r, sub) if should_do('flair'): setup_flair(r, sub) if should_do('multireddit'): add_to_multi(r, sub) if should_do('notifications'): setup_notifications(r, sub)
def main(automod, wiki, force): """Propigate settings across the network""" dom = settings.MASTER_SUB subs = [slave['name'] for slave in settings.SLAVE_SUBS] r = Reddit('Copy Network Settings v0.1 /u/{}'.format(settings.USERNAME)) r.oauth() if automod: wiki = set(wiki) wiki.update('config/automoderator') wiki = list(wiki) for page in wiki: copy_wiki_page(r, page, dom, subs, force)
def main(): r = Reddit('posts relevant feeds to the {} - /u/{}'.format( settings.NETWORK_NAME, settings.USERNAME)) r.oauth() for child_settings in settings.CHILD_SUBS: sub = Subreddit(**child_settings) posted = 0 feeds = sub.feeds[:] random.shuffle(feeds) for feed in feeds: thisfeed = feedparser.parse(feed) comment = 'This content brought to you from "{}"\n{}'.format( thisfeed.feed.title, settings.COMMENT_FOOTER.format( reason='off site feed', detail=thisfeed.feed.title )) for item in thisfeed.entries: if sub.feed_limit and posted >= sub.feed_limit: break LOG.info('Posting OC into /r/{}: {}'.format( sub.name, item.title)) try: xpost = r.submit( sub.name, title=item.title, url=item.link, captcha=None, send_replies=True, resubmit=False) xpost.add_comment(comment) except AlreadySubmitted: LOG.info('Already submitted. Skipping.') except KeyError: # XXX AlreadySubmitted isn't being raised for some reason LOG.info('Already Submitted (KeyError). Skipping.') except APIException as e: LOG.warning(e) else: posted += 1 LOG.info('Posted %s feed items into /r/%s', posted, sub.name)
def main(): """ Check for blacklist requests and add users to blacklist. """ r = Reddit('{} Update User-Requested Blacklist v0.2 /u/{}'.format( settings.NETWORK_NAME, settings.USERNAME)) r.oauth() add_users = set() orig_blacklist = set() requests = list() sub = settings.PARENT_SUB modmail_inbox = r.get_mod_mail(sub) for m in [i for i in modmail_inbox if not i.replies]: if any('blacklist me' in i.lower() for i in (m.subject, m.body)): if not len(orig_blacklist): orig_blacklist = get_user_blacklist(r) author = m.author.name.lower() if '/u/{}'.format(author) not in orig_blacklist: add_users.add(author) requests.append(m) else: m.reply( 'It appears that you are already on the {} Network blacklist. If your images are still being crossposted, please let us know so we can investigate.' .format(settings.NETWORK_NAME)) LOG.info('User {} is already in blacklist; skipping'.format( m.author.name)) if add_users: if update_user_blacklist(r, add_users, orig_blacklist): for m in requests: m.reply( 'You have been added to the user blacklist and your images will no longer be crossposted on the {} Network.' .format(settings.NETWORK_NAME)) else: LOG.info('No new blacklist requests to process')
def main(subject, message): ok = True if not subject: print('Subject may not be empty') ok = False if not message: print('Messgae may not be empty') ok = False if not ok: return r = Reddit('{} Network Mailer v0.1 /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() subs = ["/r/{}".format(sub['name']) for sub in settings.SLAVE_SUBS] for sub in subs: print('Mailing {}'.format(sub)) r.send_message(sub, subject, message)
def main(): """ Check for blacklist requests and add users to blacklist. """ r = Reddit('{} Update User-Requested Blacklist v0.2 /u/{}' .format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() add_users = set() orig_blacklist = set() requests = list() sub = settings.PARENT_SUB modmail_inbox = r.get_mod_mail(sub) for m in [i for i in modmail_inbox if not i.replies]: if any('blacklist me' in i.lower() for i in (m.subject, m.body)): if not len(orig_blacklist): orig_blacklist = get_user_blacklist(r) author = m.author.name.lower() if '/u/{}'.format(author) not in orig_blacklist: add_users.add(author) requests.append(m) else: m.reply('It appears that you are already on the {} Network blacklist. If your images are still being crossposted, please let us know so we can investigate.' .format(settings.NETWORK_NAME)) LOG.info('User {} is already in blacklist; skipping'.format(m.author.name)) if add_users: if update_user_blacklist(r, add_users, orig_blacklist): for m in requests: m.reply('You have been added to the user blacklist and your images will no longer be crossposted on the {} Network.' .format(settings.NETWORK_NAME)) else: LOG.info('No new blacklist requests to process')
def main(print_mods): """Find subs without mods and disenfranchised mods""" mods = settings.DEFAULT_MODS r = Reddit('Moderator Auditor v0.1') r.oauth() subs = sorted([sub['name'] for sub in settings.SLAVE_SUBS]) empty_subs = list() orphan_mods = dict() s = r.get_subreddit(settings.MASTER_SUB) main_sub_mods = [u.name for u in s.get_moderators()] for sub in subs: s = r.get_subreddit(sub) cur_mods = [u.name for u in s.get_moderators()] real_mods = [m for m in cur_mods if m not in mods] if not real_mods: empty_subs.append(sub) else: if print_mods: print('{} : {}'.format(sub, real_mods)) for m in [i for i in real_mods if i not in main_sub_mods]: orphan_mods[m] = orphan_mods.get(m, []) + [sub] print() print('Unmoderated Subreddits: {}'.format(len(empty_subs))) print('-----------------------') for sub in sorted(empty_subs): print(sub) print() print('Orphaned Moderators: {}'.format(len(orphan_mods))) print('-------------------------') for m, s in orphan_mods.items(): print('{} : {}'.format(m, s))
def main(): r = Reddit('posts relevant feeds to the {} - /u/{}'.format( settings.NETWORK_NAME, settings.USERNAME)) r.oauth() for child_settings in settings.CHILD_SUBS: sub = Subreddit(**child_settings) posted = 0 feeds = sub.feeds[:] random.shuffle(feeds) for feed in feeds: thisfeed = feedparser.parse(feed) comment = 'This content brought to you from "{}"\n{}'.format( thisfeed.feed.title, settings.COMMENT_FOOTER.format(reason='off site feed', detail=thisfeed.feed.title)) for item in thisfeed.entries: if sub.feed_limit and posted >= sub.feed_limit: break LOG.info('Posting OC into /r/{}: {}'.format( sub.name, item.title)) try: xpost = r.submit(sub.name, title=item.title, url=item.link, captcha=None, send_replies=True, resubmit=False) xpost.add_comment(comment) except AlreadySubmitted: LOG.info('Already submitted. Skipping.') except KeyError: # XXX AlreadySubmitted isn't being raised for some reason LOG.info('Already Submitted (KeyError). Skipping.') except APIException as e: LOG.warning(e) else: posted += 1 LOG.info('Posted %s feed items into /r/%s', posted, sub.name)
def main(no_github, no_modlog, no_oc, no_inbox, no_falsepositives, run_interval, stats_interval): """Discord Announcer Bot to relay specified information to designated Discord channels.""" reddit = Reddit('{} Discord Announcer v1.1 - /u/{}'.format( settings.NETWORK_NAME, settings.USERNAME)) reddit.oauth() discobot = DiscordBot(reddit) botsettings = DiscordBotSettings() botsettings.DO_GITHUB = not no_github botsettings.DO_MODLOG = not no_modlog botsettings.DO_OC = not no_oc botsettings.DO_INBOX = not no_inbox botsettings.DO_FALSEPOS = not no_falsepositives botsettings.RUN_INTERVAL = run_interval botsettings.STATS_INTERVAL = stats_interval discobot.run(botsettings)
def main(no_modlog, no_oc, no_inbox, no_falsepositives, run_interval, stats_interval): """Discord Announcer Bot to relay specified information to designated Discord channels. """ reddit = Reddit('{} Discord Announcer v1.1 - /u/{}' .format(settings.NETWORK_NAME, settings.USERNAME)) reddit.oauth() discobot = DiscordBot(reddit) botsettings = DiscordBotSettings() botsettings.DO_MODLOG = not no_modlog botsettings.DO_OC = not no_oc botsettings.DO_INBOX = not no_inbox botsettings.DO_FALSEPOS = not no_falsepositives botsettings.RUN_INTERVAL = run_interval botsettings.STATS_INTERVAL = stats_interval discobot.run(botsettings)
def main(): r = Reddit('{} hot_sister v3 - /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() # places multireddit places_multi = r.get_multireddit(settings.USERNAME, PLACES_MULTI_NAME) places_list_text = '' for post in places_multi.get_hot(limit=POSTS_TO_LIST): places_list_text += ' * [{}](https://redd.it/{})\n'.format(post.title, post.id) # decades multireddit decades_multi = r.get_multireddit(settings.USERNAME, DECADES_MULTI_NAME) decades_list_text = '' for post in decades_multi.get_hot(limit=POSTS_TO_LIST): decades_list_text += ' * [{}](https://redd.it/{})\n'.format(post.title, post.id) # bring it together combined_text = "* Places:\n{}\n\n* Times:\n{}".format(places_list_text, decades_list_text) # set up all the children children = sorted([sub['name'] for sub in settings.CHILD_SUBS]) for child in children: print("running on {}".format(child)) sub = r.get_subreddit(child) current_sidebar = sub.get_settings()['description'] current_sidebar = html.unescape(current_sidebar) # ew replace_pattern = re.compile('{}.*?{}'.format( re.escape(START_DELIM), re.escape(END_DELIM) ), re.IGNORECASE | re.DOTALL | re.UNICODE) # ew new_sidebar = re.sub( replace_pattern, '{}\\n\\n{}\\n{}'.format( START_DELIM, combined_text, END_DELIM ), current_sidebar ) try: sub.update_settings(description=new_sidebar) except HTTPException as e: LOG.error( "{0} on {1} while updating the sidebar".format( f_e_o(type(e), e)[0], child) ) continue
def main(): r = Reddit('{} hot_sister v3 - /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() # places multireddit places_multi = r.get_multireddit(settings.USERNAME, PLACES_MULTI_NAME) places_list_text = '' for post in places_multi.get_hot(limit=POSTS_TO_LIST): places_list_text += ' * [{}](https://redd.it/{})\n'.format( post.title, post.id) # decades multireddit decades_multi = r.get_multireddit(settings.USERNAME, DECADES_MULTI_NAME) decades_list_text = '' for post in decades_multi.get_hot(limit=POSTS_TO_LIST): decades_list_text += ' * [{}](https://redd.it/{})\n'.format( post.title, post.id) # bring it together combined_text = "* Places:\n{}\n\n* Times:\n{}".format( places_list_text, decades_list_text) # set up all the children children = sorted([sub['name'] for sub in settings.CHILD_SUBS]) for child in children: print("running on {}".format(child)) sub = r.get_subreddit(child) current_sidebar = sub.get_settings()['description'] current_sidebar = html.unescape(current_sidebar) # ew replace_pattern = re.compile( '{}.*?{}'.format(re.escape(START_DELIM), re.escape(END_DELIM)), re.IGNORECASE | re.DOTALL | re.UNICODE) # ew new_sidebar = re.sub( replace_pattern, '{}\\n\\n{}\\n{}'.format(START_DELIM, combined_text, END_DELIM), current_sidebar) try: sub.update_settings(description=new_sidebar) except HTTPException as e: LOG.error("{0} on {1} while updating the sidebar".format( f_e_o(type(e), e)[0], child)) continue
def main(): r = Reddit('{} hot_sister v3 - /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() # places multireddit places_multi = r.get_multireddit(settings.USERNAME, PLACES_MULTI_NAME) places_list_text = str() for post in places_multi.get_hot(limit=POSTS_TO_LIST): places_list_text += ' * [%s](%s)\n' % (post.title, post.permalink) # decades multireddit decades_multi = r.get_multireddit(settings.USERNAME, DECADES_MULTI_NAME) decades_list_text = str() for (i, post) in enumerate(DECADES_MULTI.get_hot(limit=POSTS_TO_LIST)): decades_list_text += ' * [%s](%s)\n' % (post.title, post.permalink) # bring it together combined_text = "* Places:\n{}\n\n* Times:\n{}".format( places_list_text, decades_list_text) # set up all the children children = sorted([sub['name'] for sub in settings.CHILD_SUBS]) for child in children: print("running on {}".format(child)) sub = r.get_subreddit(child) current_sidebar = sub.get_settings()['description'] current_sidebar = html.unescape(current_sidebar) # ew replace_pattern = re.compile( '%s.*?%s'.format(re.escape(START_DELIM), re.escape(END_DELIM)), re.IGNORECASE | re.DOTALL | re.UNICODE) # ew new_sidebar = re.sub( replace_pattern, '{}\\n\\n{}\\n{}'.format(START_DELIM, combinex_text, END_DELIM), current_sidebar) sub.update_settings(description=new_sidebar)
def main(automod, toolbox, wiki, force): """Propigate settings across the network""" dom = settings.PARENT_SUB subs = [sub['name'] for sub in settings.CHILD_SUBS] r = Reddit('Copy Network Settings v0.1 /u/{}'.format(settings.USERNAME)) r.oauth() if automod: wiki = set(wiki) wiki.update(['config/automoderator']) wiki = list(wiki) for page in wiki: copy_wiki_page(r, page, dom, subs, force) if toolbox: page = 'toolbox' content = r.get_wiki_page(dom, page).content_md for sub in subs: r.edit_wiki_page(sub, page, content)
def main(): r = Reddit('{} hot_sister v3 - /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() # places multireddit places_multi = r.get_multireddit(settings.USERNAME, PLACES_MULTI_NAME) places_list_text = str() for post in places_multi.get_hot(limit=POSTS_TO_LIST): places_list_text += ' * [%s](%s)\n' % (post.title, post.permalink) # decades multireddit decades_multi = r.get_multireddit(settings.USERNAME, DECADES_MULTI_NAME) decades_list_text = str() for (i, post) in enumerate(DECADES_MULTI.get_hot(limit=POSTS_TO_LIST)): decades_list_text += ' * [%s](%s)\n' % (post.title, post.permalink) # bring it together combined_text= "* Places:\n{}\n\n* Times:\n{}".format(places_list_text, decades_list_text) # set up all the children children = sorted([sub['name'] for sub in settings.CHILD_SUBS]) for child in children: print("running on {}".format(child)) sub = r.get_subreddit(child) current_sidebar = sub.get_settings()['description'] current_sidebar = html.unescape(current_sidebar) # ew replace_pattern = re.compile('%s.*?%s'.format( re.escape(START_DELIM), re.escape(END_DELIM)), re.IGNORECASE|re.DOTALL|re.UNICODE) # ew new_sidebar = re.sub(replace_pattern, '{}\\n\\n{}\\n{}'.format( START_DELIM, combinex_text, END_DELIM), current_sidebar) sub.update_settings(description=new_sidebar)
def main(subject, message): ok = True if not subject: print('Subject may not be empty') ok = False if not message: print('Messgae may not be empty') ok = False if not ok: return r = Reddit('{} Network Mailer v0.1 /u/{}'.format(settings.NETWORK_NAME, settings.USERNAME)) r.oauth() subs = ["/r/{}".format(sub['name']) for sub in settings.CHILD_SUBS] for sub in subs: print('Mailing {}'.format(sub)) r.send_message(sub, subject, message)
def main(print_mods): """Find subs without mods and disenfranchised mods""" mods = settings.DEFAULT_MODS r = Reddit('Moderator Auditor v0.1') r.oauth() subs = sorted([sub['name'] for sub in settings.CHILD_SUBS]) empty_subs = list() orphan_mods = dict() s = r.get_subreddit(settings.PARENT_SUB) main_sub_mods = [u.name for u in s.get_moderators()] for sub in subs: s = r.get_subreddit(sub) cur_mods = [u.name for u in s.get_moderators()] real_mods = [m for m in cur_mods if m not in mods] if not real_mods: empty_subs.append(sub) else: if print_mods: print('{} : {}'.format(sub, real_mods)) for m in [i for i in real_mods if i not in main_sub_mods]: orphan_mods[m] = orphan_mods.get(m, []) + [sub] print() print('Unmoderated Subreddits: {}'.format(len(empty_subs))) print('-----------------------') for sub in sorted(empty_subs): print(sub) print() print('Orphaned Moderators: {}'.format(len(orphan_mods))) print('-------------------------') for m, s in orphan_mods.items(): print('{} : {}'.format(m, s))
def main(history_days): """Process modlogs to identify inactive mods""" mods = settings.DEFAULT_MODS r = Reddit( '{} ModLog Auditor v0.1 - /u/{}'.format( settings.NETWORK_NAME, settings.USERNAME) ) r.oauth() subs = sorted([sub['name'] for sub in settings.CHILD_SUBS]) end_utc = gmtime(time.time() - 60 * 60 * 24 * history_days) end_date = date(end_utc[0], end_utc[1], end_utc[2]) for sub in subs: print('Processing {} modlog...'.format(sub)) done = False last = None count = 0 s = r.get_subreddit(sub) all_mods = [u.name for u in s.get_moderators()] real_mods = [m for m in all_mods if m not in mods] # If no real moderators, don't process this subreddit modlog if not real_mods: continue else: mod_action_count = dict() mod_last_action = dict() while not done: log = list(s.get_mod_log(limit=50, params={"after": last})) if len(log) == 0: done = True break else: last = log[-1].id for log_entry in [l for l in log if l.mod in real_mods]: created_utc = log_entry.created_utc time_utc = gmtime(created_utc) date_utc = date(time_utc[0], time_utc[1], time_utc[2]) if date_utc >= end_date: mod_action_count[log_entry.mod] = mod_action_count.get( log_entry.mod, 0) + 1 if date_utc > mod_last_action.get(log_entry.mod, date(1901, 1, 1)): mod_last_action[log_entry.mod] = date_utc else: # Reached end date done = True break if count >= 5000: done = True break count += 100 print('Subredit Moderation Log Stats ' 'for {}:\t\t({} entries parsed)'.format(sub, count)) for m in real_mods: print(' {}:\n\tActions: {}' ' \tLast Active: {}\n'.format( m, mod_action_count.get(m, 0), mod_last_action.get(m, date(1901, 1, 1))))