about summary refs log tree commit diff stats
path: root/src/watch/events/playlist_handler.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/watch/events/playlist_handler.rs')
-rw-r--r--src/watch/events/playlist_handler.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/watch/events/playlist_handler.rs b/src/watch/events/playlist_handler.rs
new file mode 100644
index 0000000..8f2f322
--- /dev/null
+++ b/src/watch/events/playlist_handler.rs
@@ -0,0 +1,96 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use std::collections::HashMap;
+
+use anyhow::Result;
+use libmpv2::{events::PlaylistEntryId, mpv_node::MpvNode, Mpv};
+
+use crate::storage::video_database::extractor_hash::ExtractorHash;
+
+#[derive(Debug, Default)]
+pub struct PlaylistHandler {
+    /// A map of the original file paths to the videos extractor hashes.
+    /// Used to get the extractor hash from a video returned by mpv
+    playlist_cache: HashMap<String, ExtractorHash>,
+
+    /// A map of the playlist_entry_id field to their corresponding extractor hashes.
+    playlist_ids: HashMap<PlaylistEntryId, ExtractorHash>,
+}
+impl PlaylistHandler {
+    pub fn from_cache(cache: HashMap<String, ExtractorHash>) -> Self {
+        Self {
+            playlist_cache: cache,
+            playlist_ids: HashMap::new(),
+        }
+    }
+
+    pub fn reserve(&mut self, len: usize) {
+        self.playlist_cache.reserve(len)
+    }
+    pub fn add(&mut self, cache_path: String, extractor_hash: ExtractorHash) {
+        assert_eq!(
+            self.playlist_cache.insert(cache_path, extractor_hash),
+            None,
+            "Only new video should ever be added"
+        );
+    }
+
+    pub fn playlist_ids(&mut self, mpv: &Mpv) -> Result<&HashMap<PlaylistEntryId, ExtractorHash>> {
+        let mpv_playlist: Vec<(String, PlaylistEntryId)> = match mpv.get_property("playlist")? {
+            MpvNode::ArrayIter(array) => array
+                .map(|val| match val {
+                    MpvNode::MapIter(map) => {
+                        struct BuildPlaylistEntry {
+                            filename: Option<String>,
+                            id: Option<PlaylistEntryId>,
+                        }
+                        let mut entry = BuildPlaylistEntry {
+                            filename: None,
+                            id: None,
+                        };
+
+                        map.for_each(|(key, value)| match key.as_str() {
+                            "filename" => {
+                                entry.filename = Some(value.str().expect("work").to_owned())
+                            }
+                            "id" => {
+                                entry.id = Some(PlaylistEntryId::new(value.i64().expect("Works")))
+                            }
+                            _ => (),
+                        });
+                        (entry.filename.expect("is some"), entry.id.expect("is some"))
+                    }
+                    _ => unreachable!(),
+                })
+                .collect(),
+            _ => unreachable!(),
+        };
+
+        let mut playlist: HashMap<PlaylistEntryId, ExtractorHash> =
+            HashMap::with_capacity(mpv_playlist.len());
+        for (path, key) in mpv_playlist {
+            let hash = self
+                .playlist_cache
+                .get(&path)
+                .expect("All path should also be stored in the cache")
+                .to_owned();
+            playlist.insert(key, hash);
+        }
+
+        for (id, hash) in playlist {
+            if !self.playlist_ids.contains_key(&id) {
+                self.playlist_ids.insert(id, hash);
+            }
+        }
+
+        Ok(&self.playlist_ids)
+    }
+}