From 89c41c1488854858e02ff6bd48a6518161fa05a5 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 22 Nov 2022 01:44:39 +0100 Subject: Allow launching directly into 4chan thread --- src/QuickMedia.cpp | 117 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 21 deletions(-) (limited to 'src/QuickMedia.cpp') diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 6f089be..2e7feff 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -317,9 +317,9 @@ namespace QuickMedia { } static void usage() { - fprintf(stderr, "usage: quickmedia [plugin] [--no-video] [--upscale-images] [--upscale-images-always] [--dir ] [--instance ] [-e ] [--video-max-height ] [youtube-url] [youtube-channel-url]\n"); + fprintf(stderr, "usage: quickmedia [plugin|url] [--no-video] [--upscale-images] [--upscale-images-always] [--dir ] [--instance ] [-e ] [--video-max-height ]\n"); fprintf(stderr, "OPTIONS:\n"); - fprintf(stderr, " plugin The plugin to use. Should be either launcher, 4chan, manga, manganelo, manganelos, mangatown, mangakatana, mangadex, readm, onimanga, local-manga, local-anime, youtube, peertube, lbry, soundcloud, nyaa.si, matrix, saucenao, hotexamples, anilist, dramacool, file-manager, stdin, pornhub, spankbang, xvideos or xhamster\n"); + fprintf(stderr, " plugin|url The plugin to use. Should be either launcher, 4chan, manga, manganelo, manganelos, mangatown, mangakatana, mangadex, readm, onimanga, local-manga, local-anime, youtube, peertube, lbry, soundcloud, nyaa.si, matrix, saucenao, hotexamples, anilist, dramacool, file-manager, stdin, pornhub, spankbang, xvideos or xhamster. This can also be a youtube url, youtube channel url or a 4chan thread url\n"); fprintf(stderr, " --no-video Only play audio when playing a video. Disabled by default\n"); fprintf(stderr, " --upscale-images Upscale low-resolution manga pages using waifu2x-ncnn-vulkan. Disabled by default\n"); fprintf(stderr, " --upscale-images-always Upscale manga pages using waifu2x-ncnn-vulkan, no matter what the original image resolution is. Disabled by default\n"); @@ -368,6 +368,44 @@ namespace QuickMedia { return true; } + // |comment_id| is optional + static bool fourchan_extract_url(const std::string &url, std::string &board_id, std::string &thread_id, std::string &comment_id) { + size_t len = 10; + size_t index = url.find("4chan.org/"); + if(index == std::string::npos) { + len = 13; + index = url.find("4channel.org/"); + } + + if(index == std::string::npos) + return false; + + index += len; + size_t board_end = url.find('/', index); + if(board_end == std::string::npos) + return false; + + board_id = url.substr(index, board_end - index); + index = board_end + 1; + + const std::string_view remaining(url.data() + index, url.size() - index); + if(remaining.size() <= 7 || remaining.substr(0, 7) != "thread/") + return false; + + index += 7; + size_t thread_id_end = url.find('#', index); + if(thread_id_end == std::string::npos) + thread_id_end = url.size(); + + thread_id = url.substr(index, thread_id_end - index); + if(thread_id.empty()) + return false; + + index = thread_id_end; + comment_id = url.substr(index); + return true; + } + int Program::run(int argc, char **argv) { mgl_init(); @@ -390,14 +428,22 @@ namespace QuickMedia { std::string youtube_url_converted = invidious_url_to_youtube_url(argv[i]); std::string youtube_channel_id; std::string youtube_video_id_dummy; + std::string fourchan_id_dummy; - if(youtube_url_extract_channel_id(youtube_url_converted, youtube_channel_id, youtube_channel_url)) { + if(youtube_url_extract_channel_id(youtube_url_converted, youtube_channel_id, launch_url)) { + launch_url_type = LaunchUrlType::YOUTUBE_CHANNEL; plugin_name = "youtube"; continue; } else if(youtube_url_extract_id(youtube_url_converted, youtube_video_id_dummy)) { - youtube_url = std::move(youtube_url_converted); + launch_url_type = LaunchUrlType::YOUTUBE_VIDEO; + launch_url = std::move(youtube_url_converted); plugin_name = "youtube"; continue; + } else if(fourchan_extract_url(argv[i], fourchan_id_dummy, fourchan_id_dummy, fourchan_id_dummy)) { + launch_url_type = LaunchUrlType::FOURCHAN_THREAD; + launch_url = argv[i]; + plugin_name = "4chan"; + continue; } for(const auto &valid_plugin : valid_plugins) { @@ -1283,20 +1329,32 @@ namespace QuickMedia { categories_sukebei_body->set_items(body_items); tabs.push_back(Tab{std::move(categories_sukebei_body), std::make_unique(this, true), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); } else if(strcmp(plugin_name, "4chan") == 0) { - auto boards_page = std::make_unique(this, resources_root); - FourchanBoardsPage *boards_page_ptr = boards_page.get(); + if(launch_url_type == LaunchUrlType::FOURCHAN_THREAD) { + // TODO: Use comment id + std::string board_id, thread_id, comment_id; + fourchan_extract_url(launch_url, board_id, thread_id, comment_id); + auto body = create_body(); + auto thread_page = std::make_unique(this, std::move(board_id), std::move(thread_id), ""); + page_stack.push(current_page); + current_page = PageType::IMAGE_BOARD_THREAD; + image_board_thread_page(thread_page.get(), body.get()); + exit(0); + } else { + auto boards_page = std::make_unique(this, resources_root); + FourchanBoardsPage *boards_page_ptr = boards_page.get(); - auto boards_body = create_body(); - BodyItems body_items; - boards_page->get_boards(body_items); - boards_body->set_items(std::move(body_items)); - tabs.push_back(Tab{std::move(boards_body), std::move(boards_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); + auto boards_body = create_body(); + BodyItems body_items; + boards_page->get_boards(body_items); + boards_body->set_items(std::move(body_items)); + tabs.push_back(Tab{std::move(boards_body), std::move(boards_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); - auto login_page = std::make_unique(this, "4chan pass login", boards_page_ptr, &tabs, 1); - FourchanLoginPage *login_page_ptr = login_page.get(); + auto login_page = std::make_unique(this, "4chan pass login", boards_page_ptr, &tabs, 1); + FourchanLoginPage *login_page_ptr = login_page.get(); - tabs.push_back(Tab{ create_body(), std::move(login_page), nullptr, {} }); - login_page_ptr->login_inputs = &tabs.back().login_inputs; + tabs.push_back(Tab{ create_body(), std::move(login_page), nullptr, {} }); + login_page_ptr->login_inputs = &tabs.back().login_inputs; + } } else if(strcmp(plugin_name, "hotexamples") == 0) { auto body = create_body(); BodyItems body_items; @@ -1322,11 +1380,11 @@ namespace QuickMedia { pipe_body->set_items(std::move(body_items)); tabs.push_back(Tab{std::move(pipe_body), std::make_unique(this), create_search_bar("Search...", SEARCH_DELAY_FILTER)}); } else if(strcmp(plugin_name, "youtube") == 0) { - if(!youtube_channel_url.empty()) { - YoutubeChannelPage::create_each_type(this, youtube_channel_url, "", "Channel", tabs); - } else if(!youtube_url.empty()) { + if(launch_url_type == LaunchUrlType::YOUTUBE_CHANNEL) { + YoutubeChannelPage::create_each_type(this, std::move(launch_url), "", "Channel", tabs); + } else if(launch_url_type == LaunchUrlType::YOUTUBE_VIDEO) { current_page = PageType::VIDEO_CONTENT; - auto youtube_video_page = std::make_unique(this, youtube_url, false); + auto youtube_video_page = std::make_unique(this, std::move(launch_url), false); video_content_page(nullptr, youtube_video_page.get(), "", false, nullptr, 0); } else { start_tab_index = 1; @@ -4479,6 +4537,22 @@ namespace QuickMedia { void Program::image_board_thread_page(ImageBoardThreadPage *thread_page, Body *thread_body) { AsyncImageLoader::get_instance().update(); + BodyItems result_items; + const TaskResult load_result = run_task_with_loading_screen([&]() { + return thread_page->lazy_fetch(result_items) == PluginResult::OK; + }); + + if(load_result == TaskResult::CANCEL) { + current_page = pop_page_stack(); + return; + } else if(load_result == TaskResult::FALSE) { + show_notification("QuickMedia", "Failed to load thread", Urgency::CRITICAL); + current_page = pop_page_stack(); + return; + } + + thread_body->set_items(std::move(result_items)); + // TODO: Instead of using stage here, use different pages for each stage enum class NavigationStage { VIEWING_COMMENTS, @@ -4697,9 +4771,10 @@ namespace QuickMedia { page_stack.push(PageType::IMAGE_BOARD_THREAD); current_page = PageType::VIDEO_CONTENT; watched_videos.clear(); - thread_page->set_url(selected_item->url); + ImageBoardVideoPage video_page(this); + video_page.set_url(selected_item->url); // TODO: Use real title - video_content_page(thread_page, thread_page, "", true, thread_body, thread_body->get_selected_item()); + video_content_page(thread_page, &video_page, "", true, thread_body, thread_body->get_selected_item()); redraw = true; idle_active_handler(); } else { -- cgit v1.2.3