cleanups
This commit is contained in:
124
import_events.py
Normal file
124
import_events.py
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import argparse
|
||||
import psycopg2
|
||||
import yaml
|
||||
from urllib.parse import urlparse
|
||||
|
||||
def get_config(config_path):
|
||||
with open(config_path, 'r') as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
def count_events(data):
|
||||
return data.count('BEGIN:VEVENT')
|
||||
|
||||
def import_events():
|
||||
parser = argparse.ArgumentParser(description='Import CalDAV events from files to database.')
|
||||
parser.add_argument('--config', default='config.yaml', help='Path to config.yaml')
|
||||
parser.add_argument('--input', default='export', help='Input directory or file')
|
||||
parser.add_argument('--user', help='Target user (filter or override)')
|
||||
parser.add_argument('--calendar', help='Target calendar (filter or override)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
cfg = get_config(args.config)
|
||||
db_url = cfg.get('database', {}).get('url')
|
||||
if not db_url:
|
||||
print("Error: Could not find database URL in config.")
|
||||
return
|
||||
|
||||
try:
|
||||
conn = psycopg2.connect(db_url)
|
||||
cur = conn.cursor()
|
||||
except Exception as e:
|
||||
print(f"Error connecting to database: {e}")
|
||||
return
|
||||
|
||||
def upload_file(file_path, user_name, cal_name):
|
||||
cur.execute("""
|
||||
SELECT c.id, c.path
|
||||
FROM calendars c
|
||||
JOIN users u ON c.owner_id = u.id
|
||||
WHERE u.name = %s AND c.name = %s
|
||||
""", (user_name, cal_name))
|
||||
res = cur.fetchone()
|
||||
if not res:
|
||||
print(f"Warning: Calendar '{cal_name}' for user '{user_name}' not found in DB. Skipping {file_path}")
|
||||
return False
|
||||
|
||||
cal_id, cal_base_path = res
|
||||
with open(file_path, 'r') as f:
|
||||
data = f.read()
|
||||
|
||||
filename = os.path.basename(file_path)
|
||||
obj_path = os.path.join(cal_base_path, filename)
|
||||
etag = f'"{count_events(data)}"'
|
||||
|
||||
cur.execute("""
|
||||
INSERT INTO calendar_objects (calendar_id, path, data, etag)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
ON CONFLICT (calendar_id, path) DO UPDATE
|
||||
SET data = EXCLUDED.data, etag = EXCLUDED.etag
|
||||
""", (cal_id, obj_path, data, etag))
|
||||
return True
|
||||
|
||||
# Gather all files
|
||||
files_to_process = []
|
||||
if os.path.isfile(args.input):
|
||||
files_to_process.append(args.input)
|
||||
elif os.path.isdir(args.input):
|
||||
for root, _, filenames in os.walk(args.input):
|
||||
for f in filenames:
|
||||
if f.endswith('.ics'):
|
||||
files_to_process.append(os.path.join(root, f))
|
||||
else:
|
||||
print(f"Error: Input '{args.input}' not found.")
|
||||
return
|
||||
|
||||
success_count = 0
|
||||
for f_path in files_to_process:
|
||||
# Determine source structure
|
||||
# If input is a dir, rel_path is relative to it. If file, it's just the filename.
|
||||
if os.path.isdir(args.input):
|
||||
rel_path = os.path.relpath(f_path, args.input)
|
||||
else:
|
||||
rel_path = os.path.basename(f_path)
|
||||
|
||||
parts = rel_path.split(os.sep)
|
||||
|
||||
source_user = None
|
||||
source_cal = None
|
||||
|
||||
# Structure: user/calendar/file.ics (len 3)
|
||||
if len(parts) >= 3:
|
||||
source_user = parts[-3]
|
||||
source_cal = parts[-2]
|
||||
# Structure: calendar/file.ics (len 2)
|
||||
elif len(parts) == 2:
|
||||
source_cal = parts[-2]
|
||||
|
||||
# 1. Apply Filtering: If flag is set and we have a source value, they must match.
|
||||
if args.user and source_user and args.user != source_user:
|
||||
continue
|
||||
if args.calendar and source_cal and args.calendar != source_cal:
|
||||
continue
|
||||
|
||||
# 2. Determine Target: Flag overrides source.
|
||||
target_user = args.user or source_user
|
||||
target_cal = args.calendar or source_cal
|
||||
|
||||
if not target_user or not target_cal:
|
||||
print(f"Skipping {f_path}: Cannot determine user/calendar. Use --user and --calendar flags.")
|
||||
continue
|
||||
|
||||
if upload_file(f_path, target_user, target_cal):
|
||||
print(f"Imported: {target_user}/{target_cal}/{os.path.basename(f_path)}")
|
||||
success_count += 1
|
||||
|
||||
conn.commit()
|
||||
cur.close()
|
||||
conn.close()
|
||||
print(f"Done. Successfully imported {success_count} events.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import_events()
|
||||
Reference in New Issue
Block a user