auto-archiver/auto_archive.py

141 wiersze
5.4 KiB
Python
Czysty Zwykły widok Historia

2022-05-10 21:09:33 +00:00
import sys
2022-02-21 13:19:09 +00:00
import datetime
2022-02-23 15:43:42 +00:00
import shutil
from loguru import logger
2022-02-21 13:19:09 +00:00
from dotenv import load_dotenv
2022-05-09 16:19:38 +00:00
import traceback
2022-02-21 13:19:09 +00:00
2022-05-03 18:34:04 +00:00
from archivers import TelethonArchiver, TelegramArchiver, TiktokArchiver, YoutubeDLArchiver, TwitterArchiver, WaybackArchiver, ArchiveResult
2022-05-09 16:19:38 +00:00
from utils import GWorksheet, mkdir_if_not_exists, expand_url
2022-05-03 18:34:04 +00:00
from configs import Config
2022-05-09 10:55:10 +00:00
logger.add("logs/1trace.log", level="TRACE")
logger.add("logs/2info.log", level="INFO")
logger.add("logs/3success.log", level="SUCCESS")
logger.add("logs/4warning.log", level="WARNING")
logger.add("logs/5error.log", level="ERROR")
load_dotenv()
2021-05-03 12:16:09 +00:00
2022-05-03 18:34:04 +00:00
def update_sheet(gw, row, result: ArchiveResult):
cell_updates = []
row_values = gw.get_row(row)
2021-05-03 12:16:09 +00:00
2022-02-23 08:54:03 +00:00
def batch_if_valid(col, val, final_value=None):
final_value = final_value or val
if val and gw.col_exists(col) and gw.get_cell(row_values, col) == '':
cell_updates.append((row, col, final_value))
2021-03-18 10:03:13 +00:00
cell_updates.append((row, 'status', result.status))
2021-03-15 09:08:02 +00:00
2022-02-23 08:54:03 +00:00
batch_if_valid('archive', result.cdn_url)
batch_if_valid('date', True, datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat())
2022-02-25 15:09:35 +00:00
batch_if_valid('thumbnail', result.thumbnail,
f'=IMAGE("{result.thumbnail}")')
2022-02-23 08:54:03 +00:00
batch_if_valid('thumbnail_index', result.thumbnail_index)
batch_if_valid('title', result.title)
batch_if_valid('duration', result.duration, str(result.duration))
2022-02-25 15:09:35 +00:00
batch_if_valid('screenshot', result.screenshot)
batch_if_valid('hash', result.hash)
if result.timestamp is not None:
if type(result.timestamp) == int:
timestamp_string = datetime.datetime.fromtimestamp(result.timestamp).replace(tzinfo=datetime.timezone.utc).isoformat()
elif type(result.timestamp) == str:
timestamp_string = result.timestamp
else:
timestamp_string = result.timestamp.isoformat()
batch_if_valid('timestamp', timestamp_string)
2021-03-15 09:08:02 +00:00
gw.batch_set_cell(cell_updates)
2022-05-03 18:34:04 +00:00
def process_sheet(c: Config, sheet, header=1, columns=GWorksheet.COLUMN_NAMES):
sh = c.gsheets_client.open(sheet)
# loop through worksheets to check
for ii, wks in enumerate(sh.worksheets()):
2022-05-09 14:59:35 +00:00
logger.info(f'Opening worksheet {ii=}: {wks.title=} {header=}')
gw = GWorksheet(wks, header_row=header, columns=columns)
2021-03-15 09:08:02 +00:00
2022-02-23 08:57:04 +00:00
if not gw.col_exists('url'):
2022-02-25 15:09:35 +00:00
logger.warning(
2022-05-03 18:34:04 +00:00
f'No "{c.column_names["url"]}" column found, skipping worksheet {wks.title}')
2021-03-25 12:42:42 +00:00
continue
2022-02-23 08:57:04 +00:00
if not gw.col_exists('status'):
2022-02-25 15:09:35 +00:00
logger.warning(
2022-05-03 18:34:04 +00:00
f'No "{c.column_names["status"]}" column found, skipping worksheet {wks.title}')
2021-03-25 12:42:42 +00:00
continue
# archives will be in a folder 'doc_name/worksheet_name'
2022-05-09 12:54:48 +00:00
c.set_folder(f'{sheet.replace(" ", "_")}/{wks.title.replace(" ", "_")}/')
storage = c.get_storage()
# loop through rows in worksheet
2022-02-25 15:09:35 +00:00
for row in range(1 + header, gw.count_rows() + 1):
url = gw.get_cell(row, 'url')
original_status = gw.get_cell(row, 'status')
2022-03-14 10:10:51 +00:00
status = gw.get_cell(row, 'status', fresh=original_status in ['', None] and url != '')
2022-02-23 08:54:03 +00:00
if url != '' and status in ['', None]:
2022-03-09 10:46:14 +00:00
gw.set_cell(row, 'status', 'Archive in progress')
url = expand_url(url)
# make a new driver so each spreadsheet row is idempotent
2022-05-10 21:09:33 +00:00
c.recreate_webdriver()
# order matters, first to succeed excludes remaining
active_archivers = [
TelethonArchiver(storage, c.webdriver, c.telegram_config),
TelegramArchiver(storage, c.webdriver),
TiktokArchiver(storage, c.webdriver),
YoutubeDLArchiver(storage, c.webdriver, c.facebook_cookie),
TwitterArchiver(storage, c.webdriver),
WaybackArchiver(storage, c.webdriver)
]
2022-03-09 10:46:14 +00:00
for archiver in active_archivers:
logger.debug(f'Trying {archiver} on row {row}')
try:
result = archiver.download(url, check_if_exists=True)
except Exception as e:
result = False
logger.error(f'Got unexpected error in row {row} with archiver {archiver} for url {url}: {e}\n{traceback.format_exc()}')
if result:
2022-03-09 10:46:14 +00:00
if result.status in ['success', 'already archived']:
2022-05-10 21:09:33 +00:00
result.status = f"{archiver.name}: {result.status}"
logger.success(f'{archiver} succeeded on row {row}')
2022-03-09 10:46:14 +00:00
break
2022-05-10 21:09:33 +00:00
logger.warning(f'{archiver} did not succeed on row {row}, final status: {result.status}')
result.status = f"{archiver.name}: {result.status}"
2022-03-09 10:46:14 +00:00
if result:
update_sheet(gw, row, result)
else:
gw.set_cell(row, 'status', 'failed: no archiver')
logger.success(f'Finshed worksheet {wks.title}')
2021-03-15 09:08:02 +00:00
2022-05-10 21:09:33 +00:00
2022-05-09 10:55:10 +00:00
@logger.catch
2021-03-25 12:42:42 +00:00
def main():
2022-05-09 10:55:10 +00:00
logger.debug(f'Passed args:{sys.argv}')
2022-05-03 18:34:04 +00:00
c = Config()
c.parse()
2022-03-18 08:53:21 +00:00
2022-05-03 18:34:04 +00:00
logger.info(f'Opening document {c.sheet} for header {c.header}')
2022-05-03 18:34:04 +00:00
mkdir_if_not_exists(c.tmp_folder)
process_sheet(c, c.sheet, header=c.header, columns=c.column_names)
shutil.rmtree(c.tmp_folder)
c.webdriver.quit()
2021-06-01 09:00:40 +00:00
2022-02-25 15:09:35 +00:00
2022-02-23 08:57:04 +00:00
if __name__ == '__main__':
main()