My agentic slop goes here. Not intended for anyone else!
at main 3.8 kB view raw
1open Cmdliner 2open Owntracks_to_clickhouse 3 4let process_file input_file output_file = 5 try 6 let records = Owntracks_parser.parse_file input_file in 7 match output_file with 8 | Some out_path -> 9 Clickhouse_formatter.write_jsonl_file out_path records; 10 Printf.printf "Converted %d records from %s to %s\n" 11 (List.length records) input_file out_path 12 | None -> 13 Clickhouse_formatter.print_jsonl records 14 with 15 | Sys_error msg -> 16 Printf.eprintf "Error: %s\n" msg; 17 exit 1 18 | e -> 19 Printf.eprintf "Unexpected error: %s\n" (Printexc.to_string e); 20 exit 1 21 22let process_directory dir_path output_file recursive = 23 let rec find_rec_files dir = 24 let entries = Sys.readdir dir in 25 Array.fold_left (fun acc entry -> 26 let full_path = Filename.concat dir entry in 27 if Sys.is_directory full_path then 28 if recursive then 29 acc @ find_rec_files full_path 30 else 31 acc 32 else if Filename.check_suffix entry ".rec" then 33 full_path :: acc 34 else 35 acc 36 ) [] entries 37 in 38 39 let rec_files = find_rec_files dir_path in 40 let all_records = List.fold_left (fun acc file -> 41 try 42 let records = Owntracks_parser.parse_file file in 43 Printf.printf "Processed %s: %d records\n" file (List.length records); 44 acc @ records 45 with e -> 46 Printf.eprintf "Warning: Failed to process %s: %s\n" 47 file (Printexc.to_string e); 48 acc 49 ) [] rec_files in 50 51 match output_file with 52 | Some out_path -> 53 Clickhouse_formatter.write_jsonl_file out_path all_records; 54 Printf.printf "Total: Converted %d records from %d files to %s\n" 55 (List.length all_records) (List.length rec_files) out_path 56 | None -> 57 Clickhouse_formatter.print_jsonl all_records 58 59let main input output recursive = 60 if Sys.is_directory input then 61 process_directory input output recursive 62 else 63 process_file input output 64 65let input_arg = 66 let doc = "Input OwnTracks .rec file or directory containing .rec files" in 67 Arg.(required & pos 0 (some string) None & info [] ~docv:"INPUT" ~doc) 68 69let output_arg = 70 let doc = "Output JSON lines file (if not specified, outputs to stdout)" in 71 Arg.(value & opt (some string) None & info ["o"; "output"] ~docv:"OUTPUT" ~doc) 72 73let recursive_arg = 74 let doc = "Recursively process directories for .rec files" in 75 Arg.(value & flag & info ["r"; "recursive"] ~doc) 76 77let main_term = 78 Term.(const main $ input_arg $ output_arg $ recursive_arg) 79 80let info = 81 let doc = "Convert OwnTracks .rec files to ClickHouse JSON lines" in 82 let man = [ 83 `S Manpage.s_description; 84 `P "$(tname) converts OwnTracks recorder files (.rec) to JSON lines format suitable for importing into ClickHouse with geo data types."; 85 `P "Each location record is converted to a JSON object with the following fields:"; 86 `P "- timestamp: ISO 8601 formatted timestamp"; 87 `P "- timestamp_epoch: Unix timestamp"; 88 `P "- point: [longitude, latitude] array for ClickHouse Point type"; 89 `P "- latitude, longitude: Individual coordinate fields"; 90 `P "- altitude, accuracy, battery: Optional fields from OwnTracks"; 91 `P "- tracker_id: Device identifier from OwnTracks"; 92 `S Manpage.s_examples; 93 `P "Convert a single file to stdout:"; 94 `Pre " $(tname) path/to/file.rec"; 95 `P "Convert a single file to output file:"; 96 `Pre " $(tname) path/to/file.rec -o output.jsonl"; 97 `P "Process all .rec files in a directory:"; 98 `Pre " $(tname) path/to/directory -o output.jsonl"; 99 `P "Process directory recursively:"; 100 `Pre " $(tname) path/to/directory -r -o output.jsonl"; 101 ] in 102 Cmd.info "owntracks2clickhouse" ~version:"1.0.0" ~doc ~man 103 104let cmd = Cmd.v info main_term 105 106let () = exit (Cmd.eval cmd)