// #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include "common.h" // clang-format off /* { "comment": { "commentId": "36521ed0-662f-4613-9286-8399b93f0b54", "postedAtISO": "2023-02-09T17:29:38.142Z", "deleted": false, "body": "oh helllly eah", "children": [], "postId": 993357, "inReplyTo": null, "hasCohostPlus": true, "hidden": false }, "canInteract": "not-allowed", "canEdit": "not-allowed", "canHide": "not-allowed", "poster": { "projectId": 10798, "handle": "iximeow", "displayName": "iximeow", "dek": "", "description": "opinions of varying quality. fishcat with five hammers, not afraid to use them. made out of meat, but no nutritional value.", "avatarURL": "https://staging.cohostcdn.org/avatar/10798-d6f56884-4a04-4198-902c-586e267da23e-profile.png", "avatarPreviewURL": "https://staging.cohostcdn.org/avatar/10798-d6f56884-4a04-4198-902c-586e267da23e-profile.png", "headerURL": null, "headerPreviewURL": null, "privacy": "public", "url": "", "pronouns": "any of em are fine", "flags": [], "avatarShape": "circle", "loggedOutPostVisibility": "public", "frequentlyUsedTags": [], "askSettings": { "enabled": false, "allowAnon": false, "requireLoggedInAnon": true }, "contactCard": [] } } { "1002162": [ { "comment": { "commentId": "1ddc7010-bb00-48f0-905f-5eb373d0a861", "postedAtISO": "2023-02-12T16:44:42.744Z", "deleted": false, "body": "`wine mono`??? like, you have to run the .NET code not just under Mono but under the Windows Mono??? what the Fuck?", "children": [ { "comment": { "commentId": "a86df117-1143-4c23-b9c1-ed47eb0ce27e", "postedAtISO": "2023-02-12T17:40:39.773Z", "deleted": false, "body": "idk, when i first tried the exe it gave me \"wine mono not installed\" (or something to that effect) and early-exited, and i only overcame that after `msiexec /i`ing wine-mono-7.4.0-x86.msi (at which point it started enough to crash for fonts, and I haven't managed to overcome that). there may be problems with my procedure owing to the fact that im (a) stupid and (b) not a prolific wine user, so idk", "children": [ { "comment": { "commentId": "902cd3a7-77f0-44e8-aeed-1ea1f32ce9f1", "postedAtISO": "2023-02-12T18:19:04.649Z", "deleted": false, "body": "dunno that we'd place the stupidity on you here, because i thought the entire shitfucking point of mono is that it didn't have to run inside a win32 environment", */ // clang-format on struct comment_c; struct comment { std::string commentId; // "36521ed0-662f-4613-9286-8399b93f0b54", std::string postedAtISO; // "2023-02-09T17:29:38.142Z", // bool deleted; // false, always false in my dataset std::string body; // "oh helllly eah", std::vector children; // [], // unsigned postId; // 993357, using the root key std::optional inReplyTo; // null, just parent link // std::string hidden; // false always false in my dataset }; struct comment_c { struct comment comment; // [] struct poster poster; // {...} }; // forward decl expanded from NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE inline void to_json(nlohmann::json & nlohmann_json_j, const comment_c & nlohmann_json_t); inline void from_json(const nlohmann::json & nlohmann_json_j, comment_c & nlohmann_json_t); NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(comment, commentId, postedAtISO, body, children, inReplyTo) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(comment_c, comment, poster) void eject(unsigned p, struct comment_c & c, unsigned & c_count, int memfd, bool parent_excluded = false) { ++c_count; if(p) printf("

In reply to post %1$u:

\n", p); auto exclude = std::binary_search(std::begin(excluded_uids), std::end(excluded_uids), c.poster.projectId); if(!exclude) printf("
\n", c.comment.commentId.data()); else printf("
\n"); if(!exclude) { printf("
\n"); auto user = uid_maps.find(c.poster.projectId); if(user != std::end(uid_maps)) printf("
\"\" %s
\n", user->second, c.poster.avatarURL.data(), (c.poster.displayName.empty() ? c.poster.handle : c.poster.displayName).data()); else printf("
\"\" %s
\n", c.poster.handle.data(), c.poster.avatarURL.data(), (c.poster.displayName.empty() ? c.poster.handle : c.poster.displayName).data()); printf(" \n", c.comment.commentId.data(), c.comment.postedAtISO.data(), c.comment.postedAtISO.data(), c.comment.postedAtISO.data()); if(c.comment.inReplyTo) printf(" \n", !parent_excluded ? c.comment.inReplyTo->data() : c.comment.commentId.data()); printf("
\n"); } printf("
\n"); if(!exclude) markdownise(c.comment.body, parse_iso_like(c.comment.postedAtISO), memfd); else printf(" (unavailable in archive)\n"); printf("
\n"); for(auto && cc : c.comment.children) eject(0, cc, c_count, memfd, exclude); printf("
\n"); } int main() { // sendfile(1, open("generator.pre-frag", O_RDONLY), nullptr, 128 * 1024 * 1024); int memfd = memfd_create(__FILE__, 0); auto cs_s = json::parse(stdin).template get>>(); std::map, std::greater> cs; for(auto && [p_s, cc] : cs_s) { unsigned p = atol(p_s.data()); assert(p); cs.emplace(p, std::move(cc)); } unsigned p_count{}, c_count{}; for(auto && [p_r, cc] : cs) { if(cc.empty()) { std::fputc('!', stderr); continue; } std::fputc('.', stderr); ++p_count; auto p = p_r; for(auto && c : cc) { eject(p, c, c_count, memfd); p = 0; } } std::fputc('\n', stderr); std::fprintf(stderr, "%u posts; %u comments\n", p_count, c_count); }