137 lines
4.2 KiB

# -*- 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
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')))
# Variables
headers = []
date_now = # 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 csv file does not exist
if( not isfile( csv_file ) ):
print("Couldn't find CSV file '{}'. Exiting.".format(template_file))
# Exit if template does not exist
if( not isfile( template_file ) ):
print("Couldn't find template file '{}'. Exiting.".format(template_file))
# Exit if lastseen path doesn't exist
if( not isdir( lastseen_path) ):
print( "Critical error: please create directory {}".format( lastseen_path) )
# Touch last seen file if not exists
if( isfile( last_updated_file ) ):
wrapper = open(last_updated_file, 'r',encoding="utf-8")
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 )
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')
# 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
last_updated_at = date_now