137 lines
4.2 KiB
Python
137 lines
4.2 KiB
Python
#!/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 csv file does not exist
|
|
if( not isfile( csv_file ) ):
|
|
print("Couldn't find CSV file '{}'. Exiting.".format(template_file))
|
|
os._exit(2)
|
|
|
|
# Exit if template does not exist
|
|
if( not isfile( template_file ) ):
|
|
print("Couldn't find template file '{}'. Exiting.".format(template_file))
|
|
os._exit(2)
|
|
|
|
# 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)
|