Add illustrations route
This commit is contained in:
parent
eb71b8c1ba
commit
8674a9195d
|
@ -25,7 +25,7 @@ add_link_options(${FLAGS})
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} main.cpp misc.cpp config.cpp servehelper.cpp numberhelper.cpp pixivclient.cpp pixivmodels.cpp
|
add_executable(${PROJECT_NAME} main.cpp misc.cpp config.cpp servehelper.cpp numberhelper.cpp pixivclient.cpp pixivmodels.cpp
|
||||||
blankie/serializer.cpp blankie/escape.cpp blankie/murl.cpp
|
blankie/serializer.cpp blankie/escape.cpp blankie/murl.cpp
|
||||||
routes/home.cpp routes/css.cpp routes/users/common.cpp routes/users/users.cpp routes/users/illustrations.cpp)
|
routes/home.cpp routes/css.cpp routes/artworks.cpp routes/users/common.cpp routes/users/users.cpp routes/users/illustrations.cpp)
|
||||||
set_target_properties(${PROJECT_NAME}
|
set_target_properties(${PROJECT_NAME}
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
CXX_STANDARD 20
|
CXX_STANDARD 20
|
||||||
|
|
3
main.cpp
3
main.cpp
|
@ -34,6 +34,9 @@ int main(int argc, char** argv) {
|
||||||
server.Get("/users/(\\d+)/illustrations", [&](const httplib::Request& req, httplib::Response& res) {
|
server.Get("/users/(\\d+)/illustrations", [&](const httplib::Request& req, httplib::Response& res) {
|
||||||
user_illustrations_route(req, res, config, pixiv_client);
|
user_illustrations_route(req, res, config, pixiv_client);
|
||||||
});
|
});
|
||||||
|
server.Get("/artworks/(\\d+)", [&](const httplib::Request& req, httplib::Response& res) {
|
||||||
|
artworks_route(req, res, config, pixiv_client);
|
||||||
|
});
|
||||||
|
|
||||||
server.Get("/member\\.php", [&](const httplib::Request& req, httplib::Response& res) {
|
server.Get("/member\\.php", [&](const httplib::Request& req, httplib::Response& res) {
|
||||||
std::string id = req.get_param_value("id");
|
std::string id = req.get_param_value("id");
|
||||||
|
|
|
@ -91,7 +91,7 @@ void from_json(const nlohmann::json& j, Illust& illust) {
|
||||||
const nlohmann::json& illust_details = full_data ? j.at("illust_details") : j;
|
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_account").get_to(illust.username);
|
||||||
author_details.at("user_name").get_to(illust.display_name);
|
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&>());
|
illust.user_id = to_ull(author_details.at("user_id").get_ref<const nlohmann::json::string_t&>());
|
||||||
if (full_data) {
|
if (full_data) {
|
||||||
illust.user_profile_pictures = get_profile_pictures(author_details.at("profile_img"));
|
illust.user_profile_pictures = get_profile_pictures(author_details.at("profile_img"));
|
||||||
|
@ -99,7 +99,7 @@ void from_json(const nlohmann::json& j, Illust& illust) {
|
||||||
|
|
||||||
illust.illust_id = to_ull(illust_details.at("id").get_ref<const nlohmann::json::string_t&>());
|
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_details.at("title").get_to(illust.title);
|
||||||
illust.ai_generated = illust_details.at("ai_type").get<int>() != 0;
|
illust.ai_generated = illust_details.at("ai_type").get<int>() == 2;
|
||||||
illust_details.at("upload_timestamp").get_to(illust.upload_time);
|
illust_details.at("upload_timestamp").get_to(illust.upload_time);
|
||||||
|
|
||||||
if (full_data) {
|
if (full_data) {
|
||||||
|
@ -193,12 +193,7 @@ static Images get_illust_image(const nlohmann::json& j) {
|
||||||
add_if_exists("url_s");
|
add_if_exists("url_s");
|
||||||
add_if_exists("url");
|
add_if_exists("url");
|
||||||
if (j.contains("url_big") && j["url_big"].is_string()) {
|
if (j.contains("url_big") && j["url_big"].is_string()) {
|
||||||
std::string url_big = j["url_big"].get<std::string>();
|
images.original = j["url_big"].get<std::string>();
|
||||||
if (url_big.starts_with("/img-original/")) {
|
|
||||||
images.original = std::move(url_big);
|
|
||||||
} else {
|
|
||||||
images.thumbnails.push_back(std::move(url_big));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return images;
|
return images;
|
||||||
|
|
|
@ -33,7 +33,7 @@ struct Tag {
|
||||||
|
|
||||||
struct Illust {
|
struct Illust {
|
||||||
std::string username;
|
std::string username;
|
||||||
std::string display_name;
|
std::string user_display_name;
|
||||||
uint64_t user_id;
|
uint64_t user_id;
|
||||||
Images user_profile_pictures;
|
Images user_profile_pictures;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
#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);
|
||||||
|
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));
|
||||||
|
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),
|
||||||
|
generate_images(req, config, illust),
|
||||||
|
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;
|
||||||
|
|
||||||
|
div.nodes.reserve(show_pages ? illust.images.size() * 2 : illust.images.size());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
void css_route(const httplib::Request& req, httplib::Response& res) {
|
void css_route(const httplib::Request& req, httplib::Response& res) {
|
||||||
res.set_content(R"EOF(
|
res.set_content(R"EOF(
|
||||||
|
|
||||||
|
/* GENERAL */
|
||||||
:root {
|
:root {
|
||||||
--background-color: black;
|
--background-color: black;
|
||||||
--text-color: white;
|
--text-color: white;
|
||||||
|
@ -35,15 +36,22 @@ void css_route(const httplib::Request& req, httplib::Response& res) {
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* USER PAGE (and a tiny bit for illustrations page) */
|
||||||
.cover {
|
.cover {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 50vh;
|
height: 50vh;
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
.profilepicture, .smallprofilepicture {
|
||||||
|
margin-right: .5em;
|
||||||
|
}
|
||||||
.profilepicture {
|
.profilepicture {
|
||||||
width: 5em;
|
width: 5em;
|
||||||
height: 5em;
|
height: 5em;
|
||||||
margin-right: .5em;
|
}
|
||||||
|
.smallprofilepicture {
|
||||||
|
width: 2.5em;
|
||||||
|
height: 2.5em;
|
||||||
}
|
}
|
||||||
.usermetadata {
|
.usermetadata {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -51,6 +59,7 @@ void css_route(const httplib::Request& req, httplib::Response& res) {
|
||||||
margin-left: .5em;
|
margin-left: .5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* USER ILLUSTRATIONS PAGE */
|
||||||
.center {
|
.center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +77,22 @@ void css_route(const httplib::Request& req, httplib::Response& res) {
|
||||||
width: 15em;
|
width: 15em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ILLUSTRATIONS PAGE */
|
||||||
|
.illustmetadata {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
.illust {
|
||||||
|
display: grid;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.illust .landmark {
|
||||||
|
padding-top: 1em;
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ERROR PAGE */
|
||||||
.error {
|
.error {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background-color: var(--error-background-color);
|
background-color: var(--error-background-color);
|
||||||
|
|
|
@ -9,3 +9,4 @@ void home_route(const httplib::Request& req, httplib::Response& res, const Confi
|
||||||
void css_route(const httplib::Request& req, httplib::Response& res);
|
void css_route(const httplib::Request& req, httplib::Response& res);
|
||||||
void users_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client);
|
void users_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client);
|
||||||
void user_illustrations_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client);
|
void user_illustrations_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client);
|
||||||
|
void artworks_route(const httplib::Request& req, httplib::Response& res, const Config& config, PixivClient& pixiv_client);
|
||||||
|
|
Loading…
Reference in New Issue