#include using json = nlohmann::json; // https://github.com/nlohmann/json/issues/760 namespace nlohmann { template struct adl_serializer> { static void to_json(json & j, const std::optional & opt) { if(opt == std::nullopt) { j = nullptr; } else { j = *opt; } } static void from_json(const json & j, std::optional & opt) { if(j.is_null()) { opt = std::nullopt; } else { opt = j.get(); } } }; } struct poster { unsigned projectId; std::string handle; std::string displayName; std::string avatarURL; }; NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(poster, projectId, handle, displayName, avatarURL) // cohost.org/exerian has no DM // cohost.org/bobbi has no DM static const std::map uid_maps = { {64525, "//101010.pl/@nabijaczleweli"}, {817, "//infosec.exchange/@atax1a"}, {31790, "//azabani.com"}, {10798, "//www.iximeow.net"}, }; static unsigned excluded_uids[] = { #include "excluded.h" }; void htmlencode(std::string & of, bool quotes = false) { for(std::size_t i{}; (i = of.find('&', i)) != std::string::npos;) { of.replace(i, 1, "&"); ++i; } for(std::size_t i; (i = of.find('<')) != std::string::npos;) of.replace(i, 1, "<"); if(quotes) { for(std::size_t i; (i = of.find('"')) != std::string::npos;) of.replace(i, 1, """); } } static regex_t autolink_regex = [] { regex_t ret; // 2 4 if(auto e = regcomp(&ret, "(^|[ ])(http(s?)://[^ ]*)(([.,:;!)] )|([.,:;!)]*([ ]|$))|$)", REG_EXTENDED | REG_NEWLINE)) { char err[1024]; regerror(e, &ret, err, 1024); fputs(err, stderr); fputc('\n', stderr); abort(); } assert(ret.re_nsub >= 4); return ret; }(); static regex_t videoify_regex = [] { regex_t ret; if(auto e = regcomp(&ret, "^http(s?)://[^ ]*.(mp4|webm)$", REG_EXTENDED | REG_NEWLINE | REG_ICASE)) { char err[1024]; regerror(e, &ret, err, 1024); fputs(err, stderr); fputc('\n', stderr); abort(); } return ret; }(); // https://cohost.org/staff/post/1477549-cohost-patch-notes-v // date -d '2023-05-10T15:00 EDT' -u +%s static constexpr time_t fixlines_after = 1683745200; void markdownise(std::string & m, time_t m_at, int memfd) { regmatch_t matches[10]; for(;;) { matches->rm_so = 0; matches->rm_eo = m.size(); if(regexec(&videoify_regex, m.data(), 10, matches, REG_STARTEND)) break; //