#include #include "blankie/murl.h" #include "pixivmodels.h" #include "numberhelper.h" static inline std::optional get_1920x960_cover_image(blankie::murl::Url url); static inline std::optional get_original_cover_image(blankie::murl::Url url); static inline std::optional get_original_profile_picture(blankie::murl::Url url); static Images get_profile_pictures(const nlohmann::json& j); static Images get_illust_image(const nlohmann::json& j); const std::string& Images::original_or_thumbnail() const { if (this->original) { return *this->original; } if (!this->thumbnails.empty()) { return this->thumbnails.back(); } throw std::runtime_error("Images does not contain any images"); } const std::string& Images::thumbnail_or_original() const { if (!this->thumbnails.empty()) { return this->thumbnails.back(); } if (this->original) { return *this->original; } throw std::runtime_error("Images does not contain any images"); } void from_json(const nlohmann::json& j, User& user) { j.at("user_account").get_to(user.username); j.at("user_name").get_to(user.display_name); user.user_id = to_ull(j.at("user_id").get_ref()); if (j.contains("cover_image") && j["cover_image"].is_object()) { nlohmann::json cover_image = j["cover_image"]; std::string c_720x360 = cover_image.at("profile_cover_image").at("720x360").get(); std::optional original = get_original_cover_image(c_720x360); std::optional c_1920x960 = get_1920x960_cover_image(c_720x360); user.cover_images = {std::move(original), {std::move(c_720x360)}}; if (c_1920x960) { user.cover_images->thumbnails.push_back(std::move(*c_1920x960)); } } user.profile_pictures = get_profile_pictures(j.at("profile_img")); if (j.contains("user_webpage")) { std::string user_webpage = j.at("user_webpage").get(); if (!user_webpage.empty()) { user.links.push_back({"Webpage", std::move(user_webpage)}); } } auto add_social_as_needed = [&](const char* key, const char* public_name) { nlohmann::json social = j["social"]; if (!social.contains(key)) { return; } std::string url = social[key].at("url").get(); user.links.push_back({public_name, std::move(url)}); }; if (j.contains("social") && j["social"].is_object()) { add_social_as_needed("twitter", "Twitter"); add_social_as_needed("instagram", "Instagram"); add_social_as_needed("tumblr", "Tumblr"); add_social_as_needed("facebook", "Facebook"); add_social_as_needed("circlems", "Circle.ms"); add_social_as_needed("pawoo", "Pawoo"); } } void from_json(const nlohmann::json& j, Tag& tag) { j.at("tag").get_to(tag.japanese); if (j.contains("romaji")) { tag.romaji = j["romaji"].get(); } if (j.contains("translation")) { tag.english = j["translation"].get(); } } void from_json(const nlohmann::json& j, Illust& illust) { bool full_data = j.contains("illust_details"); const nlohmann::json& author_details = j.at("author_details"); const nlohmann::json& illust_details = full_data ? j.at("illust_details") : j; author_details.at("user_account").get_to(illust.username); author_details.at("user_name").get_to(illust.display_name); illust.user_id = to_ull(author_details.at("user_id").get_ref()); if (full_data) { illust.user_profile_pictures = get_profile_pictures(author_details.at("profile_img")); } illust.illust_id = to_ull(illust_details.at("id").get_ref()); illust_details.at("title").get_to(illust.title); illust.ai_generated = illust_details.at("ai_type").get() != 0; illust_details.at("upload_timestamp").get_to(illust.upload_time); if (full_data) { std::string comment_html = illust_details.at("comment_html").get(); if (!comment_html.empty()) { illust.comment_html = std::move(comment_html); } illust_details.at("display_tags").get_to(illust.tags); } if (illust_details.contains("manga_a")) { const nlohmann::json& manga_a = illust_details["manga_a"]; illust.images.reserve(manga_a.size()); for (auto &[_, i] : manga_a.items()) { illust.images.push_back(get_illust_image(i)); } } else { illust.images = {get_illust_image(illust_details)}; } } void from_json(const nlohmann::json& j, Illusts& illusts) { j.at("illusts").get_to(illusts.illusts); j.at("total").get_to(illusts.total_illusts); j.at("lastPage").get_to(illusts.total_pages); } static std::regex resolution_path_regex("/c/(\\d+x\\d+)(.+)"); static inline std::optional get_1920x960_cover_image(blankie::murl::Url url) { std::smatch sm; if (!std::regex_match(url.path, sm, resolution_path_regex)) { return std::nullopt; } if (sm[1] == "1920x960") { return std::nullopt; } url.path = "/c/1920x960" + sm.str(2); return url.to_string(); } static std::regex thumbnail_path_regex("/c/[^/]+/(.+)_master\\d+(\\.\\w{3,4})?"); static inline std::optional get_original_cover_image(blankie::murl::Url url) { std::smatch sm; if (!std::regex_match(url.path, sm, thumbnail_path_regex)) { return std::nullopt; } url.path = sm.str(1) + sm.str(2); return url.to_string(); } static std::regex profile_picture_thumbnail_path_regex("(/.+)_\\d{2,}(\\.\\w{3,4})"); static inline std::optional get_original_profile_picture(blankie::murl::Url url) { std::smatch sm; if (!std::regex_match(url.path, sm, profile_picture_thumbnail_path_regex)) { return std::nullopt; } url.path = sm.str(1) + sm.str(2); return url.to_string(); } static Images get_profile_pictures(const nlohmann::json& j) { Images images; if (j.contains("main_s")) { images.thumbnails.push_back(j["main_s"].get()); } images.thumbnails.push_back(j.at("main").get()); images.original = get_original_profile_picture(images.thumbnails.back()); return images; } static Images get_illust_image(const nlohmann::json& j) { Images images; auto add_if_exists = [&](const char* key) { if (j.contains(key) && j[key].is_string()) { images.thumbnails.push_back(j[key].get()); } }; add_if_exists("url_ss"); add_if_exists("url_placeholder"); add_if_exists("url_s"); add_if_exists("url"); if (j.contains("url_big") && j["url_big"].is_string()) { std::string url_big = j["url_big"].get(); if (url_big.starts_with("/img-original/")) { images.original = std::move(url_big); } else { images.thumbnails.push_back(std::move(url_big)); } } return images; }