aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Aggrofile88
-rw-r--r--README.md22
-rw-r--r--app/server.py12
-rw-r--r--docker-compose.yml2
-rw-r--r--plugins/FeedSinkPlugin.py2
5 files changed, 46 insertions, 80 deletions
diff --git a/Aggrofile b/Aggrofile
index 623b8ef..96569da 100644
--- a/Aggrofile
+++ b/Aggrofile
@@ -3,15 +3,6 @@
"server_host": "0.0.0.0",
"server_port": 8080,
"plugins": {
- "plutonium74_fb": {
- "plugin": "FacebookSourcePlugin",
- "schedule_expr": "schedule.every(24).hours",
- "login_email": "${AGGRO_FB_LOGIN_EMAIL}",
- "login_password": "${AGGRO_FB_LOGIN_PASSWORD}",
- "page_id": "Plutonium74",
- "limit": 10,
- "__comment": "https://www.facebook.com/Plutonium74"
- },
"aaniwalli_scraper": {
"plugin": "ScraperSourcePlugin",
"schedule_expr": "schedule.every(10).seconds",
@@ -20,85 +11,30 @@
"selector_title": "post.select('h1')",
"selector_date": "post.select('.date')",
"selector_link": "post.select('a.event-link')",
- "selector_description": "detail_page.select('.event-page')",
+ "selector_description": "detail_page.select('.right-pane')",
"selector_image": "post.select('.event-link > .image')"
},
"aaniwalli_feed": {
"plugin": "FeedSinkPlugin",
"feed_id": "aaniwalli",
"feed_title": "Ääniwalli",
+ "feed_link": "https://www.ääniwalli.fi/",
"feed_description": "Ääniwalli events"
},
- "plutonium74_fb_feed": {
- "plugin": "FeedSinkPlugin",
- "feed_id": "plutonium74_fb",
- "feed_title": "Plutonium74 FB",
- "feed_description": "Plutonium74 FB posts"
- },
- "juusomikkonen_blog_rss": {
- "plugin": "FeedSourcePlugin",
- "schedule_expr": "schedule.every(10).seconds",
- "feed_url": "https://juusomikkonen.com/feed.xml"
- },
- "juusomikkonen_add_author": {
- "plugin": "MapPlugin",
- "map_expr": "set_field(item, 'author', 'Juuso Mikkonen')"
- },
- "mariusschulz_blog_atom": {
- "plugin": "FeedSourcePlugin",
+ "barloose_scraper": {
+ "plugin": "JsonApiSourcePlugin",
"schedule_expr": "schedule.every(10).seconds",
- "feed_url": "https://feeds.feedburner.com/mariusschulz"
- },
- "mariusschulz_add_author": {
- "plugin": "MapPlugin",
- "map_expr": "set_field(item, 'author', 'Marius Schulz')"
- },
- "typescript_digest": {
- "plugin": "DigestPlugin",
- "from_datetime": "2010-01-01T00:00:00Z",
- "interval": "2m",
- "max_length": 1000,
- "digest_title_prefix": "Only Typescript Bimonthly"
- },
- "concat": {
- "plugin": "ConcatPlugin"
- },
- "title_filter": {
- "plugin": "FilterPlugin",
- "filter_expr": "'TypeScript' in item.title"
- },
- "typescript_digest_feed": {
- "plugin": "FeedSinkPlugin",
- "feed_id": "typescript_digest",
- "feed_title": "Only Typescript Digest",
- "feed_description": "Bimonthly digest where all posts have Typescript in the title"
+ "url": "https://barloose.com/wp-json/tribe/events/v1/events",
+ "selector_post": "data['events']",
+ "selector_title": "post['title']",
+ "selector_link": "post['url']",
+ "selector_date": "post['start_date']",
+ "selector_description": "post['description']",
+ "selector_image": "post['image']['url']",
+ "show_image_in_description": true
}
},
"graph": {
- "juusomikkonen_blog_rss": [
- "juusomikkonen_add_author"
- ],
- "juusomikkonen_add_author": [
- "concat"
- ],
- "mariusschulz_blog_atom": [
- "mariusschulz_add_author"
- ],
- "mariusschulz_add_author": [
- "concat"
- ],
- "concat": [
- "title_filter"
- ],
- "title_filter": [
- "typescript_digest"
- ],
- "typescript_digest": [
- "typescript_digest_feed"
- ],
- "plutonium74_fb": [
- "plutonium74_fb_feed"
- ],
"aaniwalli_scraper": [
"aaniwalli_feed"
]
diff --git a/README.md b/README.md
index 1283ebe..a5944b2 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,22 @@
# aggro
-A feed manipulator & aggregator
+A feed manipulator & aggregator built with Python.
+
+Aggro is a tool for creating, manipulating and serving syndicated feeds based on data from arbitrary web pages with a post-like structure. Aggro is capable of sourcing content by scraping HTML, using JSON APIs, using existing RSS/Atom feeds and reading Facebook posts. These content streams can be manipulated (filtered, mapped over, concatenated, digested) to create new, transformed feeds.
+
+Aggro is based on a plugin system that is configured using a declarative JSON configuration file called Aggrofile. An Aggrofile defines the used plugin instances and a directed acyclic graph (DAG) between the plugins. Plugins are triggered either on a defined schedule or by propagating data through the DAG.
+
+Aggro was born from a concrete need to aggregate post-like data from various websites, such as event venues in my city and artists on social media. The design of Aggro is very pragmatic: features are implemented if I need them for my personal use case. As such, Aggro is a very personal project. Aggro is not mature and probably never will be.
+
+Aggro is free and open source, MIT licensed software.
+
+## Installation and running
+
+Aggro is intended to be run as a long-lived process on a server. I personally run it as a docker container on a DigitalOcean VPS, built with the Dockerfile in the repository root. See `docker-compose.yml` for a usage example. See the `Aggrofile` for a configuration example.
+
+## Plugins
+
+Plugin documentation is a work in progress. For now, check out the implementation (see `plugins -> *Plugin.py -> Plugin.__init__`) to figure out what parameters to give to each plugin.
+
+## Author
+
+Jan Tuomi <<jans.tuomi@gmail.com>>
diff --git a/app/server.py b/app/server.py
index 081c961..3ff981e 100644
--- a/app/server.py
+++ b/app/server.py
@@ -33,7 +33,8 @@ def index():
raise Exception("Database is not initialized")
Q = Query()
- feeds = database_manager.feeds.all()
+ _feeds = database_manager.feeds.all()
+ feeds: list[dict[str, str]] = _feeds # type: ignore
bottle.response.set_header("content-type", "text/html")
page = f"""
@@ -67,6 +68,10 @@ def index():
th, td {{
padding: 8px;
}}
+
+ footer {{
+ margin-top: 32px;
+ }}
</style>
</head>
<body>
@@ -74,6 +79,11 @@ def index():
<i>Feed manipulator</i>
<h2>Feeds served at this address</h2>
{feeds_to_table(feeds)}
+ <footer>
+ <p>
+ <a href="https://github.com/jantuomi/aggro">Aggro</a> is MIT licensed open source software.
+ </p>
+ </footer>
</body>
</html>
"""
diff --git a/docker-compose.yml b/docker-compose.yml
index 97b3d78..b0b5007 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3'
services:
aggro:
- image: registry.digitalocean.com/jan-systems-registry/aggro:latest
+ image: aggro:latest
build:
context: .
ports:
diff --git a/plugins/FeedSinkPlugin.py b/plugins/FeedSinkPlugin.py
index b51d64d..a49e0ae 100644
--- a/plugins/FeedSinkPlugin.py
+++ b/plugins/FeedSinkPlugin.py
@@ -121,5 +121,5 @@ class Plugin(PluginInterface):
Q = Query()
database_manager.feeds.upsert(ret, Q.feed_id == self.feed_id) # type: ignore
- self.log('build complete for feed id "{self.feed_id}"')
+ self.log(f'build complete for feed id "{self.feed_id}"')
return []