#!../venv/bin/python3 import telebot import sys import os import atexit import signal from time import sleep from socket import getaddrinfo from requests import get from subprocess import check_output import logging as log from json import loads as ljson from datetime import datetime import pytz sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import api.tfm_api as tfm_api # set logger log.basicConfig( level=log.INFO, filename="/var/log/tfm/tfm-tb.log", filemode="a", format="%(asctime)s | %(threadName)s | %(levelname)s | %(message)s" ) # actions to do on exit exit_actions = [] defer = exit_actions.append def finalize(*args): exec('\n'.join(exit_actions)) os._exit(0) atexit.register(finalize) signal.signal(signal.SIGTERM, finalize) signal.signal(signal.SIGINT, finalize) # initialize TFM API try: tfm_api.Initialize() tfm = tfm_api.TSession("af6dde9b-7be1-46f2-872e-9a06ce3d3358") except Exception as e: log.critical(f"failed to initialize TFM API: {str(e)}") exit(1) # initialize bot tfm_tb = telebot.TeleBot(tfm_api.conf["Telebot"]["Token"]) TZ = pytz.timezone("Europe/Moscow") # check if user is authorized and if chat exists in db def check_chat(message): return message.from_user.id == 924090228 # file handler @tfm_tb.message_handler(content_types=['document', 'photo', 'audio', 'video', 'voice', 'animation']) def file_handler(message): if not check_chat(message): return notes = None orig_name = None if message.forward_from_chat: notes = f"Telegram origin: \"{message.forward_from_chat.title}\" ({message.forward_from_chat.username})" if message.photo: fname = f"{message.photo[-1].file_unique_id}" log.info(f"got photo '{fname}'") file_info = tfm_tb.get_file(message.photo[-1].file_id) file_path = os.path.join(tfm_api.conf["Telebot"]["SaveFolder"], fname) with open(file_path, 'wb') as f: f.write(tfm_tb.download_file(file_info.file_path)) elif message.video: fname = f"{message.video.file_unique_id}" log.info(f"got video '{fname}'") file_info = tfm_tb.get_file(message.video.file_id) file_path = os.path.join(tfm_api.conf["Telebot"]["SaveFolder"], fname) with open(file_path, 'wb') as f: f.write(tfm_tb.download_file(file_info.file_path)) else: file = None if message.document: file = message.document elif message.animation: file = message.animation else: tfm_tb.reply_to(message, "Unsupported file type.") return log.info(f"got file '{file.file_name}'") orig_name = file.file_name file_info = tfm_tb.get_file(file.file_id) file_path = os.path.join(tfm_api.conf["Telebot"]["SaveFolder"], f"{file.file_unique_id}") try: with open(file_path, 'wb') as f: f.write(tfm_tb.download_file(file_info.file_path)) log.info(f"downloaded file '{file_path}'") exif = ljson(os.popen(f"exiftool -json \"{file_path}\"").read())[0] dt = exif["FileModifyDate"] if "SubSecCreateDate" in exif.keys(): dt = exif["SubSecCreateDate"] if '.' in dt: dt = datetime.strptime(dt, "%Y:%m:%d %H:%M:%S.%f%z") else: dt = datetime.strptime(dt, "%Y:%m:%d %H:%M:%S%z") file_id, ext = tfm.add_file(file_path, dt, notes, orig_name=orig_name) tfm.add_file_to_tag(file_id, "d6d8129a-984d-4451-8c83-d04523ced8a8") except Exception as e: tfm_tb.reply_to(message, "Error: %s" % str(e).split('\n')[0]) log.info(f"Error: %s" % str(e).split('\n')[0]) os.remove(file_path) log.info(f"removed file '{file_path}'") else: tfm_tb.reply_to(message, "File saved.") log.info(f"imported file '{file_path}'") # folder scanner @tfm_tb.message_handler(commands=['scan']) def scan(message): tfm_tb.reply_to(message, "Scanning...") log.info("Scanning...") scan_dir = "/srv/share/hfs/misc/tfm_temp/scan" files = [] for file in os.listdir(scan_dir): new_file = {"name": file} file = os.path.join(scan_dir, file) if not os.path.isfile(file): continue new_file["path"] = file try: exif = ljson(os.popen(f"exiftool -json \"{file}\"").read())[0] except Exception as e: log.error("Error while parsing EXIF for file '%s': %s" % (file, e)) continue dt = exif["FileModifyDate"] if "SubSecDateTimeOriginal" in exif.keys(): dt = exif["SubSecDateTimeOriginal"] elif "DateTimeOriginal" in exif.keys(): dt = exif["DateTimeOriginal"] if '.' in dt: try: dt = datetime.strptime(dt, "%Y:%m:%d %H:%M:%S.%f%z") except: dt = TZ.localize(datetime.strptime(dt, "%Y:%m:%d %H:%M:%S.%f")) else: try: try: dt = datetime.strptime(dt, "%Y:%m:%d %H:%M:%S%z") except: dt = TZ.localize(datetime.strptime(dt[:19], "%Y:%m:%d %H:%M:%S")) except: log.error("Broken date: %s\t%s" % (new_file, dt)) continue new_file["datetime"] = dt files.append(new_file) tfm_tb.reply_to(message, f"{len(files)} files found.") log.info(f"{len(files)} files found.") files.sort(key=lambda f: f["datetime"]) for file in files: try: file_id, ext = tfm.add_file(file["path"], file["datetime"]) tfm.add_file_to_tag(file_id, "d6d8129a-984d-4451-8c83-d04523ced8a8") except Exception as e: tfm_tb.reply_to(message, f"Error adding file '{file['name']}': {str(e)}") log.error(f"Error adding file '{file['name']}': {str(e)}") tfm_tb.reply_to(message, "Files added.") log.info("Files added.") if __name__ == '__main__': log.info("tfm-tb started") defer("log.info(\"tfm-tb stopped\")") while True: try: tfm_tb.polling(none_stop=True) except Exception as e: log.exception("exception on polling") sleep(1)