130 lines
4.9 KiB
C++
130 lines
4.9 KiB
C++
#include "routes.h"
|
|
#include "../servehelper.h"
|
|
#include "../client.h"
|
|
#include "../models.h"
|
|
|
|
static const char* sorting_method_names[3] = {"Posts", "Posts and replies", "Media"};
|
|
static const char* sorting_method_suffixes[3] = {"", "/with_replies", "/media"};
|
|
static inline PostSortingMethod get_sorting_method(const std::string& method);
|
|
|
|
static inline Element user_header(const Account& account, PostSortingMethod sorting_method);
|
|
static inline Element user_link_field(const AccountField& field);
|
|
static inline Element sorting_method_link(const Account& account, PostSortingMethod current_method, PostSortingMethod new_method);
|
|
|
|
|
|
void user_route(const httplib::Request& req, httplib::Response& res) {
|
|
std::string server = req.matches.str(1);
|
|
std::string username = req.matches.str(2);
|
|
PostSortingMethod sorting_method = get_sorting_method(req.matches.str(3));
|
|
|
|
std::optional<Account> account;
|
|
try {
|
|
account = mastodon_client.get_account_by_username(server, username);
|
|
} catch (const std::exception& e) {
|
|
res.status = 500;
|
|
serve_error(req, res, "500: Internal server error", "Failed to fetch user information", e.what());
|
|
return;
|
|
}
|
|
|
|
if (!account) {
|
|
res.status = 404;
|
|
serve_error(req, res, "404: User not found");
|
|
return;
|
|
}
|
|
|
|
Element body("body", {
|
|
user_header(*account, sorting_method),
|
|
});
|
|
serve(req, res, account->display_name + " (" + account->username + '@' + account->domain_name + ')', std::move(body));
|
|
}
|
|
|
|
|
|
static inline PostSortingMethod get_sorting_method(const std::string& method) {
|
|
for (size_t i = 0; i < sizeof(sorting_method_suffixes) / sizeof(sorting_method_suffixes[0]); i++) {
|
|
if (method == sorting_method_suffixes[i]) {
|
|
return static_cast<PostSortingMethod>(i);
|
|
}
|
|
}
|
|
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
|
|
static inline Element user_header(const Account& account, PostSortingMethod sorting_method) {
|
|
struct tm created_at;
|
|
char created_at_str[16];
|
|
gmtime_r(&account.created_at, &created_at);
|
|
strftime(created_at_str, 16, "%Y-%m-%d", &created_at);
|
|
|
|
Element user_links("table", {{"class", "user_page-user_links"}}, {});
|
|
user_links.nodes.reserve(account.fields.size());
|
|
for (const AccountField& i : account.fields) {
|
|
user_links.nodes.push_back(user_link_field(i));
|
|
}
|
|
|
|
Element header("header", {
|
|
Element("a", {{"href", account.header}}, {
|
|
Element("img", {{"class", "user_page-header"}, {"alt", "User header"}, {"src", account.header}}, {}),
|
|
}),
|
|
Element("div", {{"class", "user_page-user_pfp"}}, {
|
|
Element("a", {{"href", account.avatar}}, {
|
|
Element("img", {{"alt", "User profile picture"}, {"src", account.avatar}}, {}),
|
|
}),
|
|
Element("span", {
|
|
Element("b", {account.display_name}), " (", account.username, "@", account.domain_name, ")",
|
|
Element("br"),
|
|
Element("br"), Element("b", {"Joined: "}), std::string(created_at_str),
|
|
Element("br"),
|
|
Element("b", {std::to_string(account.statuses_count)}), " Posts", " / ",
|
|
Element("b", {std::to_string(account.following_count)}), " Following", " / ",
|
|
Element("b", {std::to_string(account.followers_count)}), " Followers",
|
|
}),
|
|
}),
|
|
|
|
Element("div", {{"class", "user_page-user_description"}}, {
|
|
Element("div", {{"class", "user_page-user_bio"}}, {account.note_html}),
|
|
|
|
std::move(user_links),
|
|
}),
|
|
|
|
Element("nav", {{"class", "user_page-user_posts_nav"}}, {
|
|
sorting_method_link(account, sorting_method, PostSortingMethod::Posts),
|
|
sorting_method_link(account, sorting_method, PostSortingMethod::PostsAndReplies),
|
|
sorting_method_link(account, sorting_method, PostSortingMethod::Media),
|
|
}),
|
|
});
|
|
return header;
|
|
}
|
|
|
|
static inline Element user_link_field(const AccountField& field) {
|
|
using namespace std::string_literals;
|
|
|
|
Element tr("tr", {
|
|
Element("th", {field.name}),
|
|
Element("td", {field.value_html}),
|
|
});
|
|
if (field.verified_at >= 0) {
|
|
struct tm verified_at;
|
|
char verified_at_str[32];
|
|
gmtime_r(&field.verified_at, &verified_at);
|
|
strftime(verified_at_str, 32, "%Y-%m-%d %H:%M:%S %Z", &verified_at);
|
|
|
|
tr.attributes = {{"class", "verified"}, {"title", "Verified at "s + verified_at_str}};
|
|
}
|
|
|
|
return tr;
|
|
}
|
|
|
|
static inline Element sorting_method_link(const Account& account, PostSortingMethod current_method, PostSortingMethod new_method) {
|
|
using namespace std::string_literals;
|
|
const char* method_name = sorting_method_names[new_method];
|
|
|
|
if (current_method == new_method) {
|
|
return Element("b", {method_name});
|
|
} else {
|
|
return Element("a", {{"href", "/"s + account.domain_name + "/@" + account.username + sorting_method_suffixes[new_method]}}, {
|
|
method_name,
|
|
});
|
|
}
|
|
}
|