]> git.ipfire.org Git - ipfire.org.git/commitdiff
Add bot that automatically tweets some things
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Apr 2019 13:22:57 +0000 (14:22 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 18 Apr 2019 13:22:57 +0000 (14:22 +0100)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/base.py
src/backend/blog.py
src/backend/tweets.py [new file with mode: 0644]
src/crontab/ipfire.org

index 5150e96eddf63b63f9c7b6dc7c9210d0737c48f7..4f147c576c089e39179f3ff50778e95aba6633b6 100644 (file)
@@ -67,6 +67,7 @@ backend_PYTHON = \
        src/backend/releases.py \
        src/backend/settings.py \
        src/backend/talk.py \
+       src/backend/tweets.py \
        src/backend/util.py \
        src/backend/wiki.py \
        src/backend/zeiterfassung.py
index 86e34611ea62fc9eee6dae97befdb51a0b1cef05..6c79d8bf44406e4de7d85241b107a6ebabe1ef42 100644 (file)
@@ -18,6 +18,7 @@ from . import nopaste
 from . import releases
 from . import settings
 from . import talk
+from . import tweets
 from . import wiki
 from . import zeiterfassung
 from .decorators import *
@@ -92,6 +93,7 @@ class Backend(object):
                        "cleanup-messages"  : self.messages.queue.cleanup,
                        "scan-files"        : self.releases.scan_files,
                        "send-all-messages" : self.messages.queue.send_all,
+                       "tweet"             : self.tweets.tweet,
                        "update-blog-feeds" : self.blog.update_feeds,
                }
 
@@ -111,3 +113,7 @@ class Backend(object):
        @lazy_property
        def messages(self):
                return messages.Messages(self)
+
+       @lazy_property
+       def tweets(self):
+               return tweets.Tweets(self)
index de2b8b69f55251a4a3f815ca4b30779c0ca05730..e79dd308f2cad6ae5352b8185ff8ff9e3ff25ce8 100644 (file)
@@ -98,6 +98,18 @@ class Blog(misc.Object):
                                ORDER BY ts_rank(search_index.document, to_tsquery('english', %s)) DESC \
                        LIMIT %s", query, query, limit)
 
+       def has_had_recent_activity(self, t=None):
+               if t is None:
+                       t = datetime.timedelta(hours=24)
+
+               res = self.db.get("SELECT COUNT(*) AS count FROM blog \
+                       WHERE published_at IS NOT NULL AND published_at >= NOW() - %s", t)
+
+               if res and res.count > 0:
+                       return True
+
+               return False
+
        def create_post(self, title, text, author, tags=[], lang="markdown"):
                """
                        Creates a new post and returns the resulting Post object
diff --git a/src/backend/tweets.py b/src/backend/tweets.py
new file mode 100644 (file)
index 0000000..514581a
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/python3
+
+import datetime
+import logging
+import tornado.gen
+import twython
+
+from .misc import Object
+
+class Tweets(Object):
+       @tornado.gen.coroutine
+       def tweet(self):
+               """
+                       Sends a random promotional tweet
+               """
+               # Do not tweet too often
+               if self.has_had_recent_activity():
+                       logging.debug("Won't tweet because we recently did it")
+                       return
+
+               # Do not tweet when there was a blog post
+               if self.backend.blog.has_had_recent_activity():
+                       logging.debug("Won't tweet because the blog has had activity")
+                       return
+
+               # Select a tweet
+               tweet = self._get_random_tweet()
+               if not tweet:
+                       logging.warning("Could not find anything to tweet")
+                       return
+
+               # Tweet the tweet
+               with self.db.transaction():
+                       self._tweet(tweet)
+
+       def has_had_recent_activity(self, t=None):
+               if t is None:
+                       t = datetime.timedelta(days=3)
+
+               res = self.db.get("SELECT COUNT(*) AS count FROM tweets \
+                       WHERE last_tweeted_at IS NOT NULL AND last_tweeted_at >= NOW() - %s", t)
+
+               if res and res.count > 0:
+                       return True
+
+               return False
+
+       def _get_random_tweet(self):
+               res = self.db.get(
+                       "WITH candidate_tweets AS (SELECT id, \
+                               (CURRENT_TIMESTAMP - COALESCE(last_tweeted_at, '1970-01-01')) * RANDOM() AS age \
+                               FROM tweets \
+                               WHERE (last_tweeted_at IS NULL OR last_tweeted_at <= CURRENT_TIMESTAMP - INTERVAL '1 month') \
+                       ) \
+                       SELECT tweets.* FROM candidate_tweets \
+                               LEFT JOIN tweets ON candidate_tweets.id = tweets.id \
+                               ORDER BY age DESC LIMIT 1")
+
+               return res
+
+       def _tweet(self, tweet):
+               logging.info("Tweeting: %s" % tweet.message)
+
+               # Update database status
+               self.db.execute("UPDATE tweets \
+                       SET last_tweeted_at = CURRENT_TIMESTAMP, total_tweets = total_tweets + 1 \
+                       WHERE id = %s", tweet.id)
+
+               # Connect to twitter
+               twitter = twython.Twython(
+                       self.settings.get("twitter_consumer_key"),
+                       self.settings.get("twitter_consumer_secret"),
+                       self.settings.get("twitter_%s_access_token" % tweet.account),
+                       self.settings.get("twitter_%s_access_token_secret" % tweet.account),
+               )
+
+               # Update status
+               twitter.update_status(status=tweet.message)
index f4d8a5b8731300bba5a7d3b7dee80811eb07e84b..b5b7459863b84b51e6007bac0050acb32bbef28b 100644 (file)
@@ -12,3 +12,6 @@
 
 # Check mirrors once every 30 min
 */30 * * * *   nobody  ipfire.org check-mirrors
+
+# Tweet once a week
+0 8 * * *      nobody  sleep ${RANDOM} && ipfire.org tweet