2023-04-09 13:31:50 +00:00
|
|
|
#include "routes.h"
|
|
|
|
#include "../servehelper.h"
|
|
|
|
#include "../numberhelper.h"
|
|
|
|
#include "../pixivclient.h"
|
|
|
|
|
|
|
|
static inline bool is_true(const std::string& str);
|
|
|
|
static inline Element generate_user_link(const httplib::Request& req, const Config& config, const Illust& illust);
|
|
|
|
static inline Element generate_images(const httplib::Request& req, const Config& config, const Illust& illust);
|
2023-04-09 13:50:44 +00:00
|
|
|
static inline Element generate_preview_images(const httplib::Request& req, const Config& config, const Illust& illust);
|
2023-04-09 13:31:50 +00:00
|
|
|
static inline Element generate_illust_metadata(const Illust& illust);
|
|
|
|
|
|
|
|
void artworks_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client) {
|
|
|
|
uint64_t illust_id = to_ull(req.matches.str(1));
|
2023-04-09 13:50:44 +00:00
|
|
|
bool preview = is_true(req.get_param_value("preview"));
|
2023-04-09 13:31:50 +00:00
|
|
|
Illust illust;
|
|
|
|
|
|
|
|
try {
|
|
|
|
illust = pixiv_client.get_illust(illust_id);
|
|
|
|
} catch (const PixivException& e) {
|
|
|
|
if (e.status == 404) {
|
|
|
|
res.status = 404;
|
|
|
|
serve_error(req, res, config, "404: Illust not found", e.what());
|
|
|
|
} else {
|
|
|
|
res.status = 500;
|
|
|
|
serve_error(req, res, config, "500: Internal server error", "Failed to fetch illust information", e.what());
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
} catch (const std::exception& e) {
|
|
|
|
res.status = 500;
|
|
|
|
serve_error(req, res, config, "500: Internal server error", "Failed to fetch illust information", e.what());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Element body("body", {
|
|
|
|
Element("h2", {illust.title}),
|
|
|
|
generate_user_link(req, config, illust),
|
2023-04-09 13:50:44 +00:00
|
|
|
!preview ? generate_images(req, config, illust) : generate_preview_images(req, config, illust),
|
2023-04-09 13:31:50 +00:00
|
|
|
Element("br"),
|
|
|
|
generate_illust_metadata(illust)
|
|
|
|
});
|
|
|
|
serve(req, res, config, std::move(illust.title), std::move(body));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Element generate_user_link(const httplib::Request& req, const Config& config, const Illust& illust) {
|
|
|
|
std::string profile_picture = proxy_image_url(config, illust.user_profile_pictures.thumbnail_or_original());
|
|
|
|
std::string user_link = get_origin(req, config) + "/users/" + std::to_string(illust.user_id);
|
|
|
|
|
|
|
|
return Element("a", {{"class", "usermetadata"}, {"href", std::move(user_link)}}, {
|
|
|
|
Element("img", {{"class", "smallprofilepicture"}, {"loading", "lazy"}, {"src", std::move(profile_picture)}}, {}),
|
|
|
|
Element("b", {illust.user_display_name})
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Element generate_images(const httplib::Request& req, const Config& config, const Illust& illust) {
|
|
|
|
using namespace std::string_literals;
|
|
|
|
|
|
|
|
Element div("div", {{"class", "illust"}}, {});
|
|
|
|
bool show_pages = illust.images.size() > 1;
|
|
|
|
|
2023-04-09 14:10:51 +00:00
|
|
|
if (show_pages) {
|
|
|
|
div.nodes.push_back(Element("a", {{"href", "?preview=1"}}, {"Preview Images"}));
|
|
|
|
}
|
|
|
|
div.nodes.reserve(div.nodes.size() + (show_pages ? illust.images.size() * 2 : illust.images.size()));
|
2023-04-09 13:31:50 +00:00
|
|
|
for (size_t i = 0; i < illust.images.size(); i++) {
|
|
|
|
const Images& images = illust.images[i];
|
|
|
|
std::string thumbnail = proxy_image_url(config, images.thumbnail_or_original());
|
|
|
|
std::string original = proxy_image_url(config, images.original_or_thumbnail());
|
|
|
|
|
|
|
|
if (show_pages) {
|
|
|
|
std::string id = std::to_string(i + 1);
|
|
|
|
div.nodes.push_back(Element("a", {{"class", "landmark"}, {"id", id}, {"href", "#"s + id}}, {id, "/", std::to_string(illust.images.size())}));
|
|
|
|
}
|
|
|
|
div.nodes.push_back(Element("a", {{"href", std::move(original)}}, {
|
|
|
|
Element("img", {{"loading", "lazy"}, {"src", std::move(thumbnail)}}, {})
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
return div;
|
|
|
|
}
|
|
|
|
|
2023-04-09 13:50:44 +00:00
|
|
|
static inline Element generate_preview_images(const httplib::Request& req, const Config& config, const Illust& illust) {
|
2023-04-09 14:10:51 +00:00
|
|
|
std::string no_preview_link = get_origin(req, config) + "/artworks/" + std::to_string(illust.illust_id);
|
|
|
|
Element div("div", {
|
|
|
|
Element("a", {{"class", "center"}, {"href", no_preview_link}}, {"Go back"}),
|
|
|
|
Element("br")
|
|
|
|
});
|
|
|
|
Element grid("div", {{"class", "grid"}}, {});
|
2023-04-09 13:50:44 +00:00
|
|
|
|
2023-04-09 14:10:51 +00:00
|
|
|
grid.nodes.reserve(illust.images.size());
|
2023-04-09 13:50:44 +00:00
|
|
|
for (size_t i = 0; i < illust.images.size(); i++) {
|
|
|
|
const Images& images = illust.images[i];
|
|
|
|
std::string thumbnail = proxy_image_url(config, images.thumbnail_or_original(1));
|
2023-04-09 14:10:51 +00:00
|
|
|
std::string link = no_preview_link + '#' + std::to_string(i + 1);
|
2023-04-09 13:50:44 +00:00
|
|
|
|
2023-04-09 14:10:51 +00:00
|
|
|
grid.nodes.push_back(Element("a", {{"href", std::move(link)}}, {
|
2023-04-09 13:50:44 +00:00
|
|
|
Element("img", {{"loading", "lazy"}, {"src", std::move(thumbnail)}}, {})
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2023-04-09 14:10:51 +00:00
|
|
|
div.nodes.push_back(std::move(grid));
|
2023-04-09 13:50:44 +00:00
|
|
|
return div;
|
|
|
|
}
|
|
|
|
|
2023-04-09 13:31:50 +00:00
|
|
|
static inline Element generate_illust_metadata(const Illust& illust) {
|
|
|
|
Element div("div", {{"class", "illustmetadata"}}, {});
|
|
|
|
|
|
|
|
if (illust.ai_generated) {
|
|
|
|
div.nodes.push_back(Element("b", {"AI-Generated "}));
|
|
|
|
}
|
|
|
|
div.nodes.reserve(div.nodes.size() + illust.tags.size());
|
|
|
|
for (const Tag& i : illust.tags) {
|
|
|
|
std::string tag = [&]() {
|
|
|
|
if (i.english) return *i.english;
|
|
|
|
if (i.romaji) return *i.romaji;
|
|
|
|
return i.japanese;
|
|
|
|
}();
|
|
|
|
|
|
|
|
div.nodes.push_back(Element("span", {"#", std::move(tag)}));
|
|
|
|
}
|
|
|
|
|
|
|
|
return div;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool is_true(const std::string& str) {
|
|
|
|
return !str.empty() && str != "0" && str != "false" && str != "no";
|
|
|
|
}
|