aboutsummaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-06-11 04:51:03 +0200
committerdec05eba <dec05eba@protonmail.com>2021-06-11 04:51:03 +0200
commit89383cff1ba5d8a928262fcb4c40382a981c78c8 (patch)
treeda8b6062cc6770fd37e7a6f7b8c09fb61f46f7b2 /plugins
parent5b3becc79461d4ecf015e33515871cc09e26e04e (diff)
Remove dependency on youtube-dl for streaming youtube, resulting in faster video startup
Diffstat (limited to 'plugins')
-rw-r--r--plugins/ImageBoard.hpp6
-rw-r--r--plugins/Matrix.hpp6
-rw-r--r--plugins/MediaGeneric.hpp6
-rw-r--r--plugins/Page.hpp18
-rw-r--r--plugins/Soundcloud.hpp7
-rw-r--r--plugins/Youtube.hpp39
-rw-r--r--plugins/youtube/Signature.hpp46
7 files changed, 102 insertions, 26 deletions
diff --git a/plugins/ImageBoard.hpp b/plugins/ImageBoard.hpp
index 6b287b6..651eabf 100644
--- a/plugins/ImageBoard.hpp
+++ b/plugins/ImageBoard.hpp
@@ -16,16 +16,15 @@ namespace QuickMedia {
class ImageBoardThreadPage : public VideoPage {
public:
- ImageBoardThreadPage(Program *program, std::string board_id, std::string thread_id) : VideoPage(program), board_id(std::move(board_id)), thread_id(std::move(thread_id)) {}
+ ImageBoardThreadPage(Program *program, std::string board_id, std::string thread_id) : VideoPage(program, ""), board_id(std::move(board_id)), thread_id(std::move(thread_id)) {}
const char* get_title() const override { return ""; }
PageTypez get_type() const override { return PageTypez::IMAGE_BOARD_THREAD; }
bool autoplay_next_item() override { return true; }
- std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program, const std::string &video_url, const std::string &video_title) override;
+ std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program) override;
std::unique_ptr<Page> create_channels_page(Program*, const std::string&) override {
return nullptr;
}
- std::string get_url() override { return video_url; }
virtual PluginResult login(const std::string &token, const std::string &pin, std::string &response_msg);
// If |filepath| is empty then no file is uploaded
virtual PostResult post_comment(const std::string &captcha_id, const std::string &comment, const std::string &filepath = "") = 0;
@@ -33,6 +32,5 @@ namespace QuickMedia {
const std::string board_id;
const std::string thread_id;
- std::string video_url;
};
} \ No newline at end of file
diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp
index ebaa166..568357a 100644
--- a/plugins/Matrix.hpp
+++ b/plugins/Matrix.hpp
@@ -410,16 +410,14 @@ namespace QuickMedia {
// Dummy, only play one video. TODO: Play all videos in room, as related videos?
class MatrixVideoPage : public VideoPage {
public:
- MatrixVideoPage(Program *program) : VideoPage(program) {}
+ MatrixVideoPage(Program *program) : VideoPage(program, "") {}
const char* get_title() const override { return ""; }
- std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program*, const std::string&, const std::string&) override {
+ std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program*) override {
return nullptr;
}
std::unique_ptr<Page> create_channels_page(Program*, const std::string&) override {
return nullptr;
}
- std::string get_url() override { return url; }
- std::string url;
};
class MatrixChatPage : public Page {
diff --git a/plugins/MediaGeneric.hpp b/plugins/MediaGeneric.hpp
index c7ce00b..102e315 100644
--- a/plugins/MediaGeneric.hpp
+++ b/plugins/MediaGeneric.hpp
@@ -80,17 +80,15 @@ namespace QuickMedia {
class MediaGenericVideoPage : public VideoPage {
public:
- MediaGenericVideoPage(Program *program, MediaGenericSearchPage *search_page, const std::string &url) : VideoPage(program), search_page(search_page), url(url) {}
+ MediaGenericVideoPage(Program *program, MediaGenericSearchPage *search_page, const std::string &url) : VideoPage(program, url), search_page(search_page) {}
const char* get_title() const override { return ""; }
BodyItems get_related_media(const std::string &url, std::string &channel_url) override;
std::unique_ptr<Page> create_search_page(Program *program, int &search_delay) override;
- std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program, const std::string &video_url, const std::string &video_title) override;
+ std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program) override;
std::unique_ptr<Page> create_channels_page(Program*, const std::string&) override {
return nullptr;
}
- std::string get_url() override { return url; }
private:
MediaGenericSearchPage *search_page;
- std::string url;
};
} \ No newline at end of file
diff --git a/plugins/Page.hpp b/plugins/Page.hpp
index 54d7d88..0c5b093 100644
--- a/plugins/Page.hpp
+++ b/plugins/Page.hpp
@@ -102,18 +102,30 @@ namespace QuickMedia {
class VideoPage : public Page {
public:
- VideoPage(Program *program) : Page(program) {}
+ VideoPage(Program *program, std::string url) : Page(program), url(std::move(url)) {}
virtual PageTypez get_type() const override { return PageTypez::VIDEO; }
virtual bool autoplay_next_item() { return false; }
virtual BodyItems get_related_media(const std::string &url, std::string &channel_url) { (void)url; (void)channel_url; return {}; }
virtual std::unique_ptr<Page> create_search_page(Program *program, int &search_delay) { (void)program; (void)search_delay; return nullptr; }
virtual std::unique_ptr<Page> create_comments_page(Program *program) { (void)program; return nullptr; }
// Return nullptr if the service doesn't support related videos page
- virtual std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program, const std::string &video_url, const std::string &video_title) = 0;
+ virtual std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program) = 0;
// Return nullptr if the service doesn't support channels page
virtual std::unique_ptr<Page> create_channels_page(Program *program, const std::string &channel_url) = 0;
- virtual std::string get_url() = 0;
+ void set_url(std::string new_url) { url = std::move(new_url); }
+ std::string get_url() { return url; }
+ // Falls back to |get_url| if this and |get_audio_url| returns empty strings
+ virtual std::string get_video_url(int max_height, bool &has_embedded_audio) {
+ (void)max_height;
+ has_embedded_audio = true;
+ return "";
+ }
+ // Only used if |get_video_url| sets |has_embedded_audio| to false
+ virtual std::string get_audio_url() { return ""; }
virtual std::string url_get_playable_url(const std::string &url) { return url; }
virtual bool video_should_be_skipped(const std::string &url) { (void)url; return false; }
+ virtual PluginResult load() { return PluginResult::OK; }
+ protected:
+ std::string url;
};
} \ No newline at end of file
diff --git a/plugins/Soundcloud.hpp b/plugins/Soundcloud.hpp
index 873de5a..c7883ba 100644
--- a/plugins/Soundcloud.hpp
+++ b/plugins/Soundcloud.hpp
@@ -57,15 +57,12 @@ namespace QuickMedia {
class SoundcloudAudioPage : public VideoPage {
public:
- SoundcloudAudioPage(Program *program, const std::string &url) : VideoPage(program), url(url) {}
+ SoundcloudAudioPage(Program *program, const std::string &url) : VideoPage(program, url) {}
const char* get_title() const override { return ""; }
bool autoplay_next_item() override { return true; }
- std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *, const std::string &, const std::string &) override { return nullptr; }
+ std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *) override { return nullptr; }
std::unique_ptr<Page> create_channels_page(Program *, const std::string &) override { return nullptr; }
- std::string get_url() override { return url; }
std::string url_get_playable_url(const std::string &url) override;
bool video_should_be_skipped(const std::string &url) override { return url == "track" || url.find("/stream/users/") != std::string::npos; }
- private:
- std::string url;
};
} \ No newline at end of file
diff --git a/plugins/Youtube.hpp b/plugins/Youtube.hpp
index 746619c..dea6cc2 100644
--- a/plugins/Youtube.hpp
+++ b/plugins/Youtube.hpp
@@ -5,14 +5,35 @@
#include <unordered_set>
namespace QuickMedia {
- class YoutubeSearchPage : public Page {
+ struct YoutubeFormat {
+ std::string url;
+ int bitrate = 0;
+ };
+
+ struct YoutubeVideoFormat {
+ YoutubeFormat base;
+ int width = 0;
+ int height = 0;
+ int fps = 0;
+ bool has_embedded_audio = false;
+ };
+
+ struct YoutubeAudioFormat {
+ YoutubeFormat base;
+ };
+
+ bool youtube_url_extract_id(const std::string &youtube_url, std::string &youtube_video_id);
+
+ class YoutubeSearchPage : public LazyFetchPage {
public:
- YoutubeSearchPage(Program *program) : Page(program) {}
+ YoutubeSearchPage(Program *program) : LazyFetchPage(program) {}
const char* get_title() const override { return "Search"; }
bool search_is_filter() override { return false; }
SearchResult search(const std::string &str, BodyItems &result_items) override;
PluginResult get_page(const std::string &str, int page, BodyItems &result_items) override;
PluginResult submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) override;
+ PluginResult lazy_fetch(BodyItems &result_items) override;
+ bool lazy_fetch_is_loader() override { return true; }
private:
PluginResult search_get_continuation(const std::string &url, const std::string &continuation_token, BodyItems &result_items);
private:
@@ -110,18 +131,24 @@ namespace QuickMedia {
class YoutubeVideoPage : public VideoPage {
public:
- YoutubeVideoPage(Program *program, const std::string &url) : VideoPage(program), url(url) {}
+ YoutubeVideoPage(Program *program, std::string url) : VideoPage(program, std::move(url)) {}
const char* get_title() const override { return ""; }
BodyItems get_related_media(const std::string &url, std::string &channel_url) override;
std::unique_ptr<Page> create_search_page(Program *program, int &search_delay) override;
std::unique_ptr<Page> create_comments_page(Program *program) override;
- std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program, const std::string &video_url, const std::string &video_title) override;
+ std::unique_ptr<RelatedVideosPage> create_related_videos_page(Program *program) override;
std::unique_ptr<Page> create_channels_page(Program *program, const std::string &channel_url) override;
- std::string get_url() override { return url; }
+ std::string get_video_url(int max_height, bool &has_embedded_audio) override;
+ std::string get_audio_url() override;
+ PluginResult load() override;
+ private:
+ void parse_format(const Json::Value &format_json, bool is_adaptive);
+ void parse_formats(const Json::Value &streaming_data_json);
private:
std::string xsrf_token;
std::string comments_continuation_token;
- std::string url;
+ std::vector<YoutubeVideoFormat> video_formats;
+ std::vector<YoutubeAudioFormat> audio_formats;
std::string playback_url;
std::string watchtime_url;
diff --git a/plugins/youtube/Signature.hpp b/plugins/youtube/Signature.hpp
new file mode 100644
index 0000000..7456615
--- /dev/null
+++ b/plugins/youtube/Signature.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include "../../include/AsyncTask.hpp"
+#include <string>
+#include <vector>
+#include <map>
+#include <mutex>
+#include <time.h>
+
+namespace QuickMedia {
+ // Thread safe
+ class YoutubeSignatureDecryptor {
+ public:
+ static YoutubeSignatureDecryptor& get_instance();
+ bool decrypt(const std::string &s, const std::string &sp, std::string &sig_key, std::string &sig_value);
+ private:
+ YoutubeSignatureDecryptor();
+ ~YoutubeSignatureDecryptor();
+ YoutubeSignatureDecryptor(const YoutubeSignatureDecryptor&) = delete;
+ YoutubeSignatureDecryptor& operator=(const YoutubeSignatureDecryptor&) = delete;
+
+ struct DecryptFuncCall {
+ std::string func_name;
+ long arg;
+ };
+
+ enum class DecryptFunction {
+ REVERSE,
+ SPLICE,
+ SWAP
+ };
+
+ bool js_code_to_operations(const std::string &function_body_str, const std::string &var_body_str, std::vector<DecryptFuncCall> &new_func_calls, std::map<std::string, DecryptFunction> &new_func_decls);
+ int update_decrypt_function();
+ private:
+ AsyncTask<void> poll_task;
+ std::mutex update_signature_mutex;
+ std::string decryption_function;
+ time_t decrypt_function_last_updated = 0;
+ bool running = false;
+ bool up_to_date = false;
+
+ std::vector<DecryptFuncCall> func_calls;
+ std::map<std::string, DecryptFunction> func_decls;
+ };
+} \ No newline at end of file