bugfix: nostr: links in titles/summaries

This commit is contained in:
Doug Hoyte
2024-12-19 19:59:57 -05:00
parent f130721d71
commit c4bb4b3f4c
3 changed files with 82 additions and 77 deletions

View File

@ -1,5 +1,4 @@
read
* nostr: links not replaced in feed titles
* support nprofile/nevent/etc links
example nevent: https://oddbean.com/e/note1qmye0at28we63aze93xjr92nzw725td0a5ncz3htwlc3wg78kp6q7802ad
example nprofile: https://oddbean.com/e/note1ykjalrpaj6jvxeuc434yd7ksrj8yd2vte478700ta8np250l3clsyjvh4q

View File

@ -264,11 +264,12 @@ struct Event {
// FIXME: Don't truncate UTF-8 mid-sequence
// FIXME: Don't put ellipsis if truncated text ends in punctuation
Summary summaryHtml() const {
Summary summaryHtml(lmdb::txn &txn, Decompressor &decomp, UserCache &userCache) const {
Summary output;
std::string content = json.at("content").get_string();
auto firstUrl = stripUrls(content);
preprocessEventContent(txn, decomp, userCache, content, false);
auto textAbbrev = [](std::string &str, size_t maxLen){
if (str.size() > maxLen) str = str.substr(0, maxLen-3) + "...";
@ -329,10 +330,8 @@ struct Event {
}
}
}
};
inline void preprocessEventContent(lmdb::txn &txn, Decompressor &decomp, const Event &ev, UserCache &userCache, std::string &content) {
void preprocessEventContent(lmdb::txn &txn, Decompressor &decomp, UserCache &userCache, std::string &content, bool withLinks = true) const {
static RE2 matcher(R"((?is)(.*?)(https?://\S+|#\[\d+\]|nostr:(?:note|npub)1\w+))");
std::string output;
@ -343,11 +342,15 @@ inline void preprocessEventContent(lmdb::txn &txn, Decompressor &decomp, const E
auto sv = [](re2::StringPiece s){ return std::string_view(s.data(), s.size()); };
auto appendLink = [&](std::string_view url, std::string_view text){
if (withLinks) {
output += "<a href=\"";
output += url;
output += "\">";
output += text;
output += "</a>";
} else {
output += text;
}
};
while (RE2::Consume(&input, matcher, &prefix, &match)) {
@ -375,7 +378,7 @@ inline void preprocessEventContent(lmdb::txn &txn, Decompressor &decomp, const E
bool didTransform = false;
auto offset = std::stoull(std::string(sv(match)).substr(2, match.size() - 3));
const auto &tags = ev.json.at("tags").get_array();
const auto &tags = json.at("tags").get_array();
try {
const auto &tag = tags.at(offset).get_array();
@ -401,6 +404,9 @@ inline void preprocessEventContent(lmdb::txn &txn, Decompressor &decomp, const E
std::swap(output, content);
}
}
};
inline std::string stripUrls(std::string &content) {
@ -530,14 +536,14 @@ struct EventThread {
}
std::string getThreadTitle() {
std::string getThreadTitle(lmdb::txn &txn, Decompressor &decomp, UserCache &userCache) {
if (!rootEventId.size()) return "";
auto p = eventCache.find(rootEventId);
if (p == eventCache.end()) return "";
const auto &elem = p->second;
return elem.summaryHtml().text;
return elem.summaryHtml(txn, decomp, userCache).text;
}
@ -564,10 +570,10 @@ struct EventThread {
ctx.abbrev = focusOnPubkey && *focusOnPubkey != pubkey;
if (ctx.abbrev) {
ctx.content = elem.summaryHtml().text;
ctx.content = elem.summaryHtml(txn, decomp, userCache).text;
} else {
ctx.content = templarInternal::htmlEscape(elem.json.at("content").get_string(), false);
preprocessEventContent(txn, decomp, elem, userCache, ctx.content);
elem.preprocessEventContent(txn, decomp, userCache, ctx.content);
}
ctx.ev = &elem;

View File

@ -104,7 +104,7 @@ TemplarResult renderFeed(lmdb::txn &txn, Decompressor &decomp, UserCache &userCa
auto ev = Event::fromLevId(txn, fe.levId);
ev.populateJson(txn, decomp);
auto summary = ev.summaryHtml();
auto summary = ev.summaryHtml(txn, decomp, userCache);
std::string url;
if (summary.url.size()) {
url = summary.url;
@ -208,7 +208,7 @@ HTTPResponse WebServer::generateReadResponse(lmdb::txn &txn, Decompressor &decom
if (u.path.size() == 2) {
EventThread et(txn, decomp, decodeBech32Simple(u.path[1]));
body = et.render(txn, decomp, userCache);
title = et.getThreadTitle();
title = et.getThreadTitle(txn, decomp, userCache);
} else if (u.path.size() == 3) {
if (u.path[2] == "reply") {
auto ev = Event::fromIdExternal(txn, u.path[1]);