From 6668f5f719a2e799100bb73a9eb5259adcef827d Mon Sep 17 00:00:00 2001 From: alban Date: Sun, 4 Aug 2019 18:38:41 +0200 Subject: [PATCH] [enh] Adds a status update script --- .gitignore | 2 + statusUpdateByDatetime.py | 127 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 .gitignore create mode 100644 statusUpdateByDatetime.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..df82bda --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +status.csv +template.jinja diff --git a/statusUpdateByDatetime.py b/statusUpdateByDatetime.py new file mode 100644 index 0000000..c4e5669 --- /dev/null +++ b/statusUpdateByDatetime.py @@ -0,0 +1,127 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +""" +Updates a mastodon account based on a CSV file containing status + +Status are defined using + - date + - time + - any number of fields usable in jinja2 templates as variables whose name + is the column name + +""" + +import codecs +import csv +from datetime import datetime, timezone +import io +import operator +import os +from os.path import isfile, isdir, dirname, join, realpath +import sys + +# Templates +import jinja2 + +# Toot +from toot.console import main + +# Command line Arguments +from argparse import ArgumentParser +parser = ArgumentParser() +parser.add_argument("-f", "--csv-file", type=str, default="status.csv", help="Which file to use for future status") +parser.add_argument("-a", "--account", type=str, default="default", help="Which name for your bot (if multiple)") +parser.add_argument("-p", "--lastseen-path", type=str, default="/var/cache/newTopics", help="Which path to use for storing ") +parser.add_argument("-pt", "--template-file", type=str, default="template.jinja", help="Which template file to use ") +args = parser.parse_args() + + +def sort_csv(csv_filename): + """Read and return CSV data sorted by first two fields + """ + data = [] + global headers + with open(csv_filename, 'rb') as f: + for row in csv.reader(codecs.iterdecode(f, 'utf-8'), delimiter=';'): + if( row[0] == "Date"): + headers = row + else: + data.append( row ) + data = sorted(data, key = operator.itemgetter(0,1)) + return data + +def recordUpdate(): + """ Helper for updating lastseen + """ + handle = open(last_updated_file, 'w') + handle.write(str(last_updated_at.strftime('%Y-%m-%d %H:%M:%S.%f%z'))) + handle.close() + +# Variables +headers = [] +date_now = datetime.now(timezone.utc) # Now() +account = args.account # The tag file lastseen path +lastseen_path = args.lastseen_path # The tag file lastseen path +csv_file = args.csv_file # The status file +template_file = args.template_file # The status file +last_updated_at = date_now # The last time we updated the status +last_updated_file = join(lastseen_path, "{}.lastseen".format(account)) # lastseen file + + +templateLoader = jinja2.FileSystemLoader(searchpath="./") +templateEnv = jinja2.Environment(loader=templateLoader) + + +# Exit if lastseen path doesn't exist +if( not isdir( lastseen_path) ): + print( "Critical error: please create directory {}".format( lastseen_path) ) + os._exit(2) + +# Touch last seen file if not exists +if( isfile( last_updated_file ) ): + wrapper = open(last_updated_file, 'r',encoding="utf-8") + try: + record = next(wrapper) + except IOError as e: + print("Couldn't open or write to file (%s)." % e) + last_updated_at = datetime.strptime(record.rstrip(), '%Y-%m-%d %H:%M:%S.%f%z') + print( last_updated_at ) + +else: + try: + recordUpdate() + except IOError as e: + print("Couldn't open or write to file (%s)." % e) + +# Read CSV file +statusList = sort_csv(csv_file) + +# Walk through records until a date is strictly superior to previous action and inferior to now +for status in statusList: + status_date = datetime.strptime("{} {}-+0000".format(status[0],status[1]), '%Y-%m-%d %H:%M:%S-%z') + status_date.replace(tzinfo=timezone.utc) + + # Debug + print( "status:{} last_updated_at:{} now:{}".format(status_date, last_updated_at, date_now) ) + + # Status should be published + if( status_date > last_updated_at and status_date < date_now ): + template = templateEnv.get_template(template_file) + template_vars = dict(zip(headers, status)) + outputText = template.render( template_vars ) + + # Toot + sim_args = [sys.argv[0], 'post' ] + + if ( account ) : + sim_args.extend( ( '-u', account )) + + sim_args.append( outputText ) + sys.argv = sim_args + main() + + last_updated_at = date_now + # recordUpdate() + os._exit(1) + +os._exit(0)