Browse Source

Updated to allow custom logic for filter articles in an rss feed, updated gitignore, updated examples/configs

bot_curator 20170630.1
Mike C 4 years ago
  1. 9
  2. 30
  3. 8
  4. 23


@ -1,3 +1,12 @@
# Credential files
# Cache files from examples
# VIM temp files
# Byte-compiled / optimized / DLL files


@ -0,0 +1,30 @@
# Define a static toot that's send via the bot
# Most useful for a single toot that's send on a regular basis as a reminder
# Think generic follow friday, weekly reminders, etc
# The name of the app that's registered on the instance
app_name = rss_bot_include_logic
# The base URL for the instance
api_base_url =
# Where to store the client secret for the bot (THIS NEEDS TO BE SECURE!)
client_cred_file = /root/rss_bot/rss_bot.secret
# Where to store the user credentials for the bot (THIS NEEDS TO BE SECURE!)
user_cred_file = /root/rss_bot/rss_bot_user_cred.secret
# This section is optional in RSS mode
#Values can span multiple lines as long as they are indented more than the key that holds them
cw_text = A new article has been posted!
# The main RSS feed
feed =
# Custom article include implementation file
# add an include_article(article) function to this file that returns True or False if you want custom logic for cross-posting articles from rss feeds
# Think cross posting challenges from a photography website
custom_article_include_file = /root/rss_bot/
# The number of articles to fetch, must be between 1 and 150 (150 is a standard instance rate limit)
article_limit = 1
# File that holds the cache of RSS articles previously seen (sqlite3)
cache_file = /root/rss_bot/rss_cache.db


@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
# Custom include logic for dPS photog challenges posted on main RSS feed
def include_article(article):
if 'Weekly' in article.title and 'Challenge' in article.title:
return True
return False


@ -60,7 +60,20 @@ def toot(api_base_url, client_cred_file, user_cred_file, cw_text, toot, subtoots
# Return the parent toot dict just in case it's needed elsewhere
return parent_toot
def rss(api_base_url, client_cred_file, user_cred_file, rss_feed, rss_article_limit, rss_cache_file, cw_text):
# Default implementation on whether or not to include an RSS article
# Returns true and has the same method signature as what end users can setup for custom logic
def default_include_article(article):
return True
def rss(api_base_url, client_cred_file, user_cred_file, custom_article_include_file, rss_feed, rss_article_limit, rss_cache_file, cw_text):
# Setup custom include logic before opening any database connections
include_article_fn = default_include_article
if custom_article_include_file is not None and os.path.exists(os.path.abspath(custom_article_include_file)):
from importlib.machinery import SourceFileLoader
custom_logic = SourceFileLoader('custom.logic', os.path.abspath(custom_article_include_file)).load_module()
include_article_fn = custom_logic.include_article
# Crash on reading the feed before doing any database operations or tooting
feed = feedparser.parse(rss_feed)
@ -73,6 +86,9 @@ def rss(api_base_url, client_cred_file, user_cred_file, rss_feed, rss_article_li
# Run through all articles in feed
for entry in feed['entries']:
if not include_article_fn(entry):
# Check if article is in cache already and skip if found
c.execute('select count(1) as found from article_cache where id = ?', (,))
if c.fetchone()[0] > 0:
@ -171,6 +187,9 @@ if __name__ == '__main__':
toot(config_api_base_url, config_client_cred_file, config_user_cred_file, config_cw_text, config_toot, config_sub_toots)
# Deal with rss command
if args.command == 'rss':
config_custom_article_include_file = None
if config.has_option('rss', 'custom_article_include_file'):
config_custom_article_include_file = config['rss']['custom_article_include_file']
config_rss_feed = config['rss']['feed']
config_rss_article_limit = int(config['rss']['article_limit'])
if config_rss_article_limit < 1 or config_rss_article_limit > 150:
@ -180,4 +199,4 @@ if __name__ == '__main__':
sys.exit('rss_cache_file directory does not exist')
if not os.path.exists(config_rss_cache_file):
print('warning: rss_cache_file file will be created')
rss(config_api_base_url, config_client_cred_file, config_user_cred_file, config_rss_feed, config_rss_article_limit, config_rss_cache_file, config_cw_text)
rss(config_api_base_url, config_client_cred_file, config_user_cred_file, config_custom_article_include_file, config_rss_feed, config_rss_article_limit, config_rss_cache_file, config_cw_text)