| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- #!/bin/bash
- set -euo pipefail
- if [ $# -eq 0 ]; then
- echo "Usage: $0 <export-file1.json> [export-file2.json] ..." >&2
- exit 1
- fi
- jq -n --slurpfile files <(
- for file in "$@"; do
- basename=$(basename "$file")
- date_prefix=$(echo "$basename" | grep -oE '^[0-9]{4}-[0-9]{2}-[0-9]{2}' || echo "0000-00-00")
- jq --arg file "$file" --arg date "$date_prefix" '. + {sourceFile: $file, fileDate: $date}' "$file"
- done | jq -s '.'
- ) '
- # Sort files by date (later dates have priority for tie-breaking)
- ($files[0] | sort_by(.fileDate)) as $sorted_files |
- # Merge playlists
- ($sorted_files | map(.playlists // {} | to_entries) | flatten | group_by(.key) | map({
- key: .[0].key,
- value: (
- # Get the playlist name
- .[0].key as $playlist_name |
- # Collect all videos from all versions with metadata
- (map(.value) | flatten | unique_by(.url)) as $all_videos |
- # For each video, find its earliest position
- $all_videos | map(. as $video |
- # Find earliest position across all files
- ([$sorted_files[] |
- select(.playlists[$playlist_name]) |
- .playlists[$playlist_name] |
- to_entries[] |
- select(.value.url == $video.url) |
- {index: .key, date: .}
- ] |
- if length > 0 then
- min_by(.date)
- else
- {index: 999999, date: {fileDate: "9999-99-99"}}
- end) as $earliest |
- # Get latest video data
- ([$sorted_files[] |
- select(.playlists[$playlist_name]) |
- .playlists[$playlist_name][] |
- select(.url == $video.url)
- ] | last) as $latest_video |
- $latest_video + {
- _sort_date: ($sorted_files | map(select(.playlists[$playlist_name] and (.playlists[$playlist_name] | map(.url) | contains([$video.url])))) | .[0].fileDate),
- _sort_index: $earliest.index
- }
- ) |
- # Sort by earliest appearance
- sort_by([._sort_date, ._sort_index]) |
- # Remove sort keys
- map(del(._sort_date, ._sort_index))
- )
- }) | from_entries) as $merged_playlists |
- # Merge playback history
- ($sorted_files | map(.playbackHistory // {} | to_entries) | flatten | group_by(.key) | map({
- key: .[0].key,
- value: (
- # For each video in history, merge all events and metadata
- map(.value) |
- {
- url: (map(.url) | last),
- title: (map(.title) | last),
- tags: (map(.tags // []) | flatten | unique),
- history: (map(.history // []) | flatten | unique_by(.timestamp) | sort_by(.timestamp))
- }
- )
- }) | from_entries) as $merged_history |
- # Collect all open tabs (unique by URL, keep latest title)
- ($sorted_files | map(.openTabs // []) | flatten | group_by(.url) | map(last)) as $merged_tabs |
- # Output merged result
- {
- playlists: $merged_playlists,
- playbackHistory: $merged_history,
- openTabs: $merged_tabs,
- exportDate: (now | todate),
- mergedFrom: ($sorted_files | map({file: .sourceFile, date: .fileDate}))
- }
- '
|