pixwhile/pixivmodels.cpp

229 lines
8.4 KiB
C++

#include <regex>
#include "blankie/murl.h"
#include "pixivmodels.h"
#include "numberhelper.h"
static inline std::optional<std::string> get_1920x960_cover_image(blankie::murl::Url url);
static inline std::optional<std::string> get_original_cover_image(blankie::murl::Url url, const nlohmann::json& cover_image);
static inline std::optional<std::string> get_original_profile_picture(blankie::murl::Url url);
static inline std::optional<std::string> get_360x360_illust_thumbnail(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(size_t back) const {
if (this->thumbnails.size() > back) {
return this->thumbnails[this->thumbnails.size() - back - 1];
}
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<const nlohmann::json::string_t&>());
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::string>();
std::optional<std::string> original = get_original_cover_image(c_720x360, cover_image);
std::optional<std::string> 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<std::string>();
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<std::string>();
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("translation")) {
tag.english = j["translation"].get<std::string>();
}
}
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.user_display_name);
illust.user_id = to_ull(author_details.at("user_id").get_ref<const nlohmann::json::string_t&>());
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<const nlohmann::json::string_t&>());
illust_details.at("title").get_to(illust.title);
illust.ai_generated = illust_details.at("ai_type").get<int>() == 2;
illust_details.at("upload_timestamp").get_to(illust.upload_time);
if (full_data) {
if (illust_details.contains("comment") && illust_details["comment"].is_string()) {
illust.comment = illust_details["comment"].get<std::string>();
}
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<std::string> 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<std::string> get_original_cover_image(blankie::murl::Url url, const nlohmann::json& cover_image) {
std::smatch sm;
if (!std::regex_match(url.path, sm, thumbnail_path_regex)) {
return std::nullopt;
}
url.path = sm.str(1);
if (cover_image.contains("profile_cover_ext") && cover_image["profile_cover_ext"].is_string()
&& !cover_image["profile_cover_ext"].get_ref<const nlohmann::json::string_t&>().empty()) {
url.path += '.';
url.path += cover_image["profile_cover_ext"].get<std::string>();
} else {
url.path += sm.str(2);
}
return url.to_string();
}
static std::regex profile_picture_thumbnail_path_regex("(/.+)_\\d{2,}(\\.\\w{3,4})");
static inline std::optional<std::string> 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<std::string>());
}
images.thumbnails.push_back(j.at("main").get<std::string>());
images.original = get_original_profile_picture(images.thumbnails.back());
return images;
}
static std::regex illust_360x360_thumbnail_path_regex(
"(?:/c/[^/]+?/img-master|/img-original)?"
"(/img/.*/\\d+_p\\d+)(?:_master1200|_square1200)?\\.\\w{3,4}"
);
static inline std::optional<std::string> get_360x360_illust_thumbnail(blankie::murl::Url url) {
using namespace std::string_literals;
std::smatch sm;
if (!std::regex_match(url.path, sm, illust_360x360_thumbnail_path_regex)) {
return std::nullopt;
}
url.path = "/c/360x360_10_webp/img-master"s + sm.str(1) + "_square1200.jpg";
return url.to_string();
}
static Images get_illust_image(const nlohmann::json& j) {
Images images;
ssize_t add_360x360_to = -1;
auto add_if_exists = [&](const char* key) {
if (j.contains(key) && j[key].is_string()) {
images.thumbnails.push_back(j[key].get<std::string>());
return true;
}
return false;
};
add_if_exists("url_ss");
add_if_exists("url_placeholder");
add_if_exists("url_small");
if (!add_if_exists("url_s")) {
add_360x360_to = static_cast<ssize_t>(images.thumbnails.size());
}
add_if_exists("url");
if (j.contains("url_big") && j["url_big"].is_string()) {
images.original = j["url_big"].get<std::string>();
}
if (add_360x360_to >= 0) {
std::optional<std::string> c_360x360 = get_360x360_illust_thumbnail(images.original_or_thumbnail());
if (c_360x360) {
images.thumbnails.insert(images.thumbnails.begin() + add_360x360_to, std::move(*c_360x360));
}
}
return images;
}