Add OGP metadata for artworks
This commit is contained in:
		
							parent
							
								
									6aeba6acb6
								
							
						
					
					
						commit
						ee03ab01d8
					
				| 
						 | 
				
			
			@ -9,9 +9,11 @@
 | 
			
		|||
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_preview_images(const httplib::Request& req, const Config& config, const Illust& illust);
 | 
			
		||||
static inline std::vector<blankie::html::Node> parse_description_line(const httplib::Request& req, const Config& config, std::string str);
 | 
			
		||||
static inline Nodes parse_description_line(const httplib::Request& req, const Config& config, std::string str);
 | 
			
		||||
static inline Element generate_description(const httplib::Request& req, const Config& config, const std::string& description);
 | 
			
		||||
static inline Element generate_illust_tags(const httplib::Request& req, const Config& config, const Illust& illust);
 | 
			
		||||
static inline std::string generate_description_text(const httplib::Request& req, const Config& config, std::string description);
 | 
			
		||||
static inline Nodes generate_ogp_nodes(const httplib::Request& req, const Config& config, const Illust& illust);
 | 
			
		||||
 | 
			
		||||
static inline bool is_true(const std::string& str);
 | 
			
		||||
static inline std::string time_to_string(time_t time);
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +53,7 @@ void artworks_route(const httplib::Request& req, httplib::Response& res, const C
 | 
			
		|||
    }
 | 
			
		||||
    body.nodes.push_back(generate_illust_tags(req, config, illust));
 | 
			
		||||
    body.nodes.push_back(Element("p", {time_to_string(illust.upload_time)}));
 | 
			
		||||
    serve(req, res, config, std::move(illust.title), std::move(body));
 | 
			
		||||
    serve(req, res, config, illust.title, std::move(body), generate_ogp_nodes(req, config, illust));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline Element generate_user_link(const httplib::Request& req, const Config& config, const Illust& illust) {
 | 
			
		||||
| 
						 | 
				
			
			@ -120,8 +122,8 @@ static inline Element generate_preview_images(const httplib::Request& req, const
 | 
			
		|||
    return div;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline std::vector<blankie::html::Node> parse_description_line(const httplib::Request& req, const Config& config, std::string str) {
 | 
			
		||||
    std::vector<blankie::html::Node> nodes;
 | 
			
		||||
static inline Nodes parse_description_line(const httplib::Request& req, const Config& config, std::string str) {
 | 
			
		||||
    Nodes nodes;
 | 
			
		||||
    std::smatch sm;
 | 
			
		||||
 | 
			
		||||
    while (std::regex_search(str, sm, blankie::murl::full_url_regex)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -160,7 +162,7 @@ static inline Element generate_description(const httplib::Request& req, const Co
 | 
			
		|||
        if (!p.nodes.empty()) {
 | 
			
		||||
            p.nodes.push_back(Element("br"));
 | 
			
		||||
        }
 | 
			
		||||
        std::vector<blankie::html::Node> nodes = parse_description_line(req, config, std::move(str));
 | 
			
		||||
        Nodes nodes = parse_description_line(req, config, std::move(str));
 | 
			
		||||
        p.nodes.insert(p.nodes.end(), nodes.begin(), nodes.end());
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -196,6 +198,61 @@ static inline Element generate_illust_tags(const httplib::Request& req, const Co
 | 
			
		|||
    return div;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline std::string generate_description_text(const httplib::Request& req, const Config& config, std::string description) {
 | 
			
		||||
    std::string new_description;
 | 
			
		||||
    std::smatch sm;
 | 
			
		||||
 | 
			
		||||
    new_description.reserve(description.size());
 | 
			
		||||
    while (std::regex_search(description, sm, blankie::murl::full_url_regex)) {
 | 
			
		||||
        std::string prefix = sm.prefix();
 | 
			
		||||
        std::string url_str = sm.str(0);
 | 
			
		||||
        std::string suffix = sm.suffix();
 | 
			
		||||
 | 
			
		||||
        if (prefix.ends_with('(') && url_str.ends_with(')')) {
 | 
			
		||||
            url_str.pop_back();
 | 
			
		||||
            suffix.insert(0, 1, ')');
 | 
			
		||||
        }
 | 
			
		||||
        new_description += std::move(prefix);
 | 
			
		||||
 | 
			
		||||
        blankie::murl::Url url(std::move(url_str));
 | 
			
		||||
        url_str = url.is_host_equal("pixiv.net") || url.is_host_equal("www.pixiv.net")
 | 
			
		||||
            ? proxy_pixiv_url(req, config, std::move(url))
 | 
			
		||||
            : url.to_string();
 | 
			
		||||
        new_description += std::move(url_str);
 | 
			
		||||
 | 
			
		||||
        description = std::move(suffix);
 | 
			
		||||
    }
 | 
			
		||||
    new_description += std::move(description);
 | 
			
		||||
 | 
			
		||||
    return new_description;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline Nodes generate_ogp_nodes(const httplib::Request& req, const Config& config, const Illust& illust) {
 | 
			
		||||
    Nodes nodes({
 | 
			
		||||
        Element("meta", {{"property", "og:title"}, {"content", illust.title}}, {}),
 | 
			
		||||
        Element("meta", {{"property", "og:type"}, {"content", "photo"}}, {}),
 | 
			
		||||
        Element("meta", {{"property", "og:site_name"}, {"content", "Pixwhile"}}, {}),
 | 
			
		||||
        Element("meta", {{"property", "og:url"}, {"content", get_origin(req, config) + "/artworks/" + std::to_string(illust.illust_id)}}, {})
 | 
			
		||||
    });
 | 
			
		||||
    if (illust.comment) {
 | 
			
		||||
        nodes.push_back(Element("meta", {{"property", "og:description"}, {"content", generate_description_text(req, config, *illust.comment)}}, {}));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // i don't even know what multiple og:images do anymore
 | 
			
		||||
    // https://stackoverflow.com/questions/13424780/facebook-multiple-ogimage-tags-which-is-default
 | 
			
		||||
    nodes.reserve(nodes.size() + illust.images.size() * 3);
 | 
			
		||||
    for (const Images& images : illust.images) {
 | 
			
		||||
        const Image& image = images.thumbnail_or_original();
 | 
			
		||||
        nodes.push_back(Element("meta", {{"property", "og:image"}, {"content", proxy_image_url(config, image.url)}}, {}));
 | 
			
		||||
        if (image.size) {
 | 
			
		||||
            nodes.push_back(Element("meta", {{"property", "og:image:width"}, {"content", std::to_string(image.size->first)}}, {}));
 | 
			
		||||
            nodes.push_back(Element("meta", {{"property", "og:image:height"}, {"content", std::to_string(image.size->second)}}, {}));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool is_true(const std::string& str) {
 | 
			
		||||
    return !str.empty() && str != "0" && str != "false" && str != "no";
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,7 +99,7 @@ static inline Element generate_header(const httplib::Request& req, const Config&
 | 
			
		|||
 | 
			
		||||
static inline Element generate_search_suggestions(const httplib::Request& req, const Config& config,
 | 
			
		||||
        const std::vector<std::string>& tags, const std::vector<SearchSuggestion>& search_suggestions, bool open_by_default) {
 | 
			
		||||
    std::vector<blankie::html::Node> ul_nodes;
 | 
			
		||||
    Nodes ul_nodes;
 | 
			
		||||
    ul_nodes.reserve(search_suggestions.size());
 | 
			
		||||
    for (const SearchSuggestion& search_suggestion : search_suggestions) {
 | 
			
		||||
        std::string text = search_suggestion.tag;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,20 +11,23 @@ static inline Element generate_illusts_grid(const httplib::Request& req, const C
 | 
			
		|||
static inline Element generate_illusts_grid_item(const httplib::Request& req, const Config& config, const Illust& illust);
 | 
			
		||||
static inline Element generate_illust_badge(const Illust& illust, const std::string& illust_url);
 | 
			
		||||
 | 
			
		||||
void serve(const httplib::Request& req, httplib::Response& res, const Config& config, std::string title, Element element) {
 | 
			
		||||
void serve(const httplib::Request& req, httplib::Response& res, const Config& config, std::string title, Element element, Nodes extra_head) {
 | 
			
		||||
    using namespace std::string_literals;
 | 
			
		||||
 | 
			
		||||
    std::string css_url = get_origin(req, config) + "/style.css";
 | 
			
		||||
    res.set_header("Content-Security-Policy", "default-src 'none'; style-src "s + css_url
 | 
			
		||||
        + "; img-src https://s.pximg.net " + config.image_proxy_url.get_origin());
 | 
			
		||||
 | 
			
		||||
    Element head("head", {
 | 
			
		||||
        Element("meta", {{"charset", "utf-8"}}, {}),
 | 
			
		||||
        Element("title", {std::move(title)}),
 | 
			
		||||
        Element("link", {{"rel", "stylesheet"}, {"href", std::move(css_url) + "?v=" + std::to_string(css_hash)}}, {}),
 | 
			
		||||
        Element("meta", {{"name", "viewport"}, {"content", "width=device-width,initial-scale=1"}}, {})
 | 
			
		||||
    });
 | 
			
		||||
    head.nodes.reserve(head.nodes.size() + extra_head.size());
 | 
			
		||||
    head.nodes.insert(head.nodes.end(), extra_head.begin(), extra_head.end());
 | 
			
		||||
    std::string html = "<!DOCTYPE html>"s + Element("html", {
 | 
			
		||||
        Element("head", {
 | 
			
		||||
            Element("meta", {{"charset", "utf-8"}}, {}),
 | 
			
		||||
            Element("title", {std::move(title)}),
 | 
			
		||||
            Element("link", {{"rel", "stylesheet"}, {"href", std::move(css_url) + "?v=" + std::to_string(css_hash)}}, {}),
 | 
			
		||||
            Element("meta", {{"name", "viewport"}, {"content", "width=device-width,initial-scale=1"}}, {})
 | 
			
		||||
        }),
 | 
			
		||||
        std::move(head),
 | 
			
		||||
        std::move(element)
 | 
			
		||||
    }).serialize();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,8 +9,10 @@
 | 
			
		|||
struct Config; // forward declaration from config.h
 | 
			
		||||
struct Illusts; // forward declaration from pixivmodels.h
 | 
			
		||||
using Element = blankie::html::Element;
 | 
			
		||||
using Node = blankie::html::Node;
 | 
			
		||||
using Nodes = std::vector<Node>;
 | 
			
		||||
 | 
			
		||||
void serve(const httplib::Request& req, httplib::Response& res, const Config& config, std::string title, Element element);
 | 
			
		||||
void serve(const httplib::Request& req, httplib::Response& res, const Config& config, std::string title, Element element, Nodes extra_head = {});
 | 
			
		||||
void serve_error(const httplib::Request& req, httplib::Response& res, const Config& config,
 | 
			
		||||
        std::string title, std::optional<std::string> subtitle = std::nullopt, std::optional<std::string> info = std::nullopt);
 | 
			
		||||
void serve_redirect(const httplib::Request& req, httplib::Response& res, const Config& config, std::string url);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue