Python command line used in a crontab to monitor toots using a specific tag and auto boosting them
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

statusUpdateByDatetime.py 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #!/usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. Updates a mastodon account based on a CSV file containing status
  5. Status are defined using
  6. - date
  7. - time
  8. - any number of fields usable in jinja2 templates as variables whose name
  9. is the column name
  10. """
  11. import codecs
  12. import csv
  13. from datetime import datetime, timezone
  14. import io
  15. import operator
  16. import os
  17. from os.path import isfile, isdir, dirname, join, realpath
  18. import sys
  19. # Templates
  20. import jinja2
  21. # Toot
  22. from toot.console import main
  23. # Command line Arguments
  24. from argparse import ArgumentParser
  25. parser = ArgumentParser()
  26. parser.add_argument("-f", "--csv-file", type=str, default="status.csv", help="Which file to use for future status")
  27. parser.add_argument("-a", "--account", type=str, default="default", help="Which name for your bot (if multiple)")
  28. parser.add_argument("-p", "--lastseen-path", type=str, default="/var/cache/newTopics", help="Which path to use for storing ")
  29. parser.add_argument("-pt", "--template-file", type=str, default="template.jinja", help="Which template file to use ")
  30. args = parser.parse_args()
  31. def sort_csv(csv_filename):
  32. """Read and return CSV data sorted by first two fields
  33. """
  34. data = []
  35. global headers
  36. with open(csv_filename, 'rb') as f:
  37. for row in csv.reader(codecs.iterdecode(f, 'utf-8'), delimiter=';'):
  38. if( row[0] == "Date"):
  39. headers = row
  40. else:
  41. data.append( row )
  42. data = sorted(data, key = operator.itemgetter(0,1))
  43. return data
  44. def recordUpdate():
  45. """ Helper for updating lastseen
  46. """
  47. handle = open(last_updated_file, 'w')
  48. handle.write(str(last_updated_at.strftime('%Y-%m-%d %H:%M:%S.%f%z')))
  49. handle.close()
  50. # Variables
  51. headers = []
  52. date_now = datetime.now(timezone.utc) # Now()
  53. account = args.account # The tag file lastseen path
  54. lastseen_path = args.lastseen_path # The tag file lastseen path
  55. csv_file = args.csv_file # The status file
  56. template_file = args.template_file # The status file
  57. last_updated_at = date_now # The last time we updated the status
  58. last_updated_file = join(lastseen_path, "{}.lastseen".format(account)) # lastseen file
  59. templateLoader = jinja2.FileSystemLoader(searchpath="./")
  60. templateEnv = jinja2.Environment(loader=templateLoader)
  61. # Exit if lastseen path doesn't exist
  62. if( not isdir( lastseen_path) ):
  63. print( "Critical error: please create directory {}".format( lastseen_path) )
  64. os._exit(2)
  65. # Touch last seen file if not exists
  66. if( isfile( last_updated_file ) ):
  67. wrapper = open(last_updated_file, 'r',encoding="utf-8")
  68. try:
  69. record = next(wrapper)
  70. except IOError as e:
  71. print("Couldn't open or write to file (%s)." % e)
  72. last_updated_at = datetime.strptime(record.rstrip(), '%Y-%m-%d %H:%M:%S.%f%z')
  73. print( last_updated_at )
  74. else:
  75. try:
  76. recordUpdate()
  77. except IOError as e:
  78. print("Couldn't open or write to file (%s)." % e)
  79. # Read CSV file
  80. statusList = sort_csv(csv_file)
  81. # Walk through records until a date is strictly superior to previous action and inferior to now
  82. for status in statusList:
  83. status_date = datetime.strptime("{} {}-+0000".format(status[0],status[1]), '%Y-%m-%d %H:%M:%S-%z')
  84. status_date.replace(tzinfo=timezone.utc)
  85. # Debug
  86. print( "status:{} last_updated_at:{} now:{}".format(status_date, last_updated_at, date_now) )
  87. # Status should be published
  88. if( status_date > last_updated_at and status_date < date_now ):
  89. template = templateEnv.get_template(template_file)
  90. template_vars = dict(zip(headers, status))
  91. outputText = template.render( template_vars )
  92. # Toot
  93. sim_args = [sys.argv[0], 'post' ]
  94. if ( account ) :
  95. sim_args.extend( ( '-u', account ))
  96. sim_args.append( outputText )
  97. sys.argv = sim_args
  98. main()
  99. last_updated_at = date_now
  100. # recordUpdate()
  101. os._exit(1)
  102. os._exit(0)