diff options
author | dec05eba <dec05eba@protonmail.com> | 2022-02-18 19:26:23 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2022-02-18 19:26:23 +0100 |
commit | de5fa7773f0393bfab917f8bf8606cb38ba3930e (patch) | |
tree | a0c5ec51f87948181797ccd2d3934b4a86c29a00 /src/plugins/WatchProgress.cpp | |
parent | 9301f1da5cf779516131f6bd5ddfc22991601128 (diff) |
Refactor watch progress (prepare for global watch progress)
Diffstat (limited to 'src/plugins/WatchProgress.cpp')
-rw-r--r-- | src/plugins/WatchProgress.cpp | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/plugins/WatchProgress.cpp b/src/plugins/WatchProgress.cpp new file mode 100644 index 0000000..c3e2fb7 --- /dev/null +++ b/src/plugins/WatchProgress.cpp @@ -0,0 +1,115 @@ +#include "../../plugins/WatchProgress.hpp" +#include "../../include/Storage.hpp" +#include "../../include/Notification.hpp" +#include <json/value.h> + +namespace QuickMedia { + double WatchProgress::get_watch_ratio() const { + if(duration_sec == 0) + return 0; + return (double)time_pos_sec / (double)duration_sec; + } + + // We consider having watched the video if the user stopped watching 90% in, because they might skip the ending theme/credits (especially in anime) + bool WatchProgress::has_finished_watching() const { + return get_watch_ratio() >= 0.9; + } + + bool set_watch_progress_for_plugin(const char *plugin_name, const std::string &id, int64_t time_pos_sec, int64_t duration_sec, const std::string &thumbnail_url) { + Path watch_progress_dir = get_storage_dir().join("watch-progress"); + if(create_directory_recursive(watch_progress_dir) != 0) { + show_notification("QuickMedia", "Failed to create " + watch_progress_dir.data + " to set watch progress for " + id, Urgency::CRITICAL); + return false; + } + + Path progress_path = watch_progress_dir; + progress_path.join(plugin_name); + + Json::Value json_root; + if(!read_file_as_json(progress_path, json_root) || !json_root.isObject()) + json_root = Json::Value(Json::objectValue); + + Json::Value watch_progress_json(Json::objectValue); + watch_progress_json["time"] = (int64_t)time_pos_sec; + watch_progress_json["duration"] = (int64_t)duration_sec; + watch_progress_json["thumbnail_url"] = thumbnail_url; + watch_progress_json["timestamp"] = (int64_t)time(nullptr); + json_root[id] = std::move(watch_progress_json); + + if(!save_json_to_file_atomic(progress_path, json_root)) { + show_notification("QuickMedia", "Failed to set watch progress for " + id, Urgency::CRITICAL); + return false; + } + + fprintf(stderr, "Set watch progress for \"%s\" to %d/%d\n", id.c_str(), (int)time_pos_sec, (int)duration_sec); + return true; + } + + std::unordered_map<std::string, WatchProgress> get_watch_progress_for_plugin(const char *plugin_name) { + std::unordered_map<std::string, WatchProgress> watch_progress_map; + Path progress_path = get_storage_dir().join("watch-progress").join(plugin_name); + + Json::Value json_root; + if(!read_file_as_json(progress_path, json_root) || !json_root.isObject()) + return watch_progress_map; + + for(Json::Value::const_iterator it = json_root.begin(); it != json_root.end(); ++it) { + Json::Value key = it.key(); + if(!key.isString()) + continue; + + const Json::Value &time_json = (*it)["time"]; + const Json::Value &duration_json = (*it)["duration"]; + const Json::Value ×tamp_json = (*it)["timestamp"]; + if(!time_json.isInt64() || !duration_json.isInt64() || !timestamp_json.isInt64()) + continue; + + WatchProgress watch_progress; + watch_progress.time_pos_sec = time_json.asInt64(); + watch_progress.duration_sec = duration_json.asInt64(); + watch_progress.timestamp = timestamp_json.asInt64(); + + const Json::Value &thumbnail_url_json = (*it)["thumbnail_url"]; + if(thumbnail_url_json.isString()) + watch_progress.thumbnail_url = thumbnail_url_json.asString(); + + watch_progress_map[key.asString()] = std::move(watch_progress); + } + + return watch_progress_map; + } + + bool toggle_watched_for_plugin_save_to_file(const char *plugin_name, const std::string &id, int64_t duration_sec, const std::string &thumbnail_url, WatchedStatus &watched_status) { + Path local_anime_progress_path = get_storage_dir().join("watch-progress").join(plugin_name); + + Json::Value json_root; + if(!read_file_as_json(local_anime_progress_path, json_root) || !json_root.isObject()) + json_root = Json::Value(Json::objectValue); + + bool watched = false; + Json::Value &watched_item = json_root[id]; + if(watched_item.isObject()) { + watched = true; + } else { + watched_item = Json::Value(Json::objectValue); + watched = false; + } + + if(watched) { + json_root.removeMember(id.c_str()); + } else { + watched_item["time"] = (int64_t)duration_sec; + watched_item["duration"] = (int64_t)duration_sec; + watched_item["thumbnail_url"] = thumbnail_url; + watched_item["timestamp"] = (int64_t)time(nullptr); + } + + if(!save_json_to_file_atomic(local_anime_progress_path, json_root)) { + show_notification("QuickMedia", "Failed to mark " + id + " as " + (watched ? "not watched" : "watched"), Urgency::CRITICAL); + return false; + } + + watched_status = watched ? WatchedStatus::NOT_WATCHED : WatchedStatus::WATCHED; + return true; + } +}
\ No newline at end of file |