Fix opengraph

This commit is contained in:
Kieran 2024-03-07 11:37:16 +00:00
parent 9ba3fc118d
commit 4e1c62ac90

View File

@ -14,17 +14,8 @@ namespace NostrServices.Controllers;
/// Add OpenGraph tags to html documents /// Add OpenGraph tags to html documents
/// </summary> /// </summary>
[Route("/api/v1/opengraph")] [Route("/api/v1/opengraph")]
public class OpenGraphController : Controller public class OpenGraphController(ILogger<OpenGraphController> logger, RedisStore redisStore) : Controller
{ {
private readonly ILogger<OpenGraphController> _logger;
private readonly RedisStore _redisStore;
public OpenGraphController(ILogger<OpenGraphController> logger, RedisStore redisStore)
{
_logger = logger;
_redisStore = redisStore;
}
/// <summary> /// <summary>
/// Inject opengraph tags into provided html /// Inject opengraph tags into provided html
/// </summary> /// </summary>
@ -63,7 +54,7 @@ public class OpenGraphController : Controller
{ {
if (nid.Hrp is "nevent" or "note" or "naddr") if (nid.Hrp is "nevent" or "note" or "naddr")
{ {
var ev = await _redisStore.GetEvent(nid); var ev = await redisStore.GetEvent(nid);
if (ev != default) if (ev != default)
{ {
var tags = MetaTagsToElements(await GetEventTags(ev)); var tags = MetaTagsToElements(await GetEventTags(ev));
@ -75,7 +66,7 @@ public class OpenGraphController : Controller
} }
else if (nid.Hrp is "nprofile" or "npub") else if (nid.Hrp is "nprofile" or "npub")
{ {
var profile = await _redisStore.GetProfile(nid.Special); var profile = await redisStore.GetProfile(nid.Special);
var meta = await GetProfileMeta(profile); var meta = await GetProfileMeta(profile);
var tags = MetaTagsToElements([ var tags = MetaTagsToElements([
@ -98,7 +89,7 @@ public class OpenGraphController : Controller
} }
catch (Exception ex) when (ex is not TaskCanceledException) catch (Exception ex) when (ex is not TaskCanceledException)
{ {
_logger.LogWarning("Failed to inject event tags: {Message}", ex.ToString()); logger.LogWarning("Failed to inject event tags: {Message}", ex.ToString());
} }
} }
@ -109,17 +100,20 @@ public class OpenGraphController : Controller
{ {
var ret = new List<KeyValuePair<string, string>>(); var ret = new List<KeyValuePair<string, string>>();
var profile = await _redisStore.GetProfile(ev.PubKey.ToHex()); var profile = await redisStore.GetProfile(ev.PubKey.ToHex());
var name = profile?.Name ?? "Nostrich"; var name = profile?.Name ?? "Nostrich";
switch (ev.Kind) switch (ev.Kind)
{ {
case (long)NostrKind.LiveEvent: case (long)NostrKind.LiveEvent:
{ {
var host = ev.Tags.FirstOrDefault(a => a.Key == "p" && a.Values[1] == "host")?.Values[0] ?? ev.PubKey.ToHex(); var host = ev.Tags.FirstOrDefault(a => a.Key == "p" && a.Values[^1] == "host")
var hostProfile = await _redisStore.GetProfile(host); ?.Values[0] ??
ev.PubKey.ToHex();
var hostProfile = await redisStore.GetProfile(host);
var hostName = hostProfile?.Name ?? profile?.Name ?? "Nostrich"; var hostName = hostProfile?.Name ?? profile?.Name ?? "Nostrich";
var stream = ev.GetFirstTagValue("streaming") ?? ev.GetFirstTagValue("recording") ?? ""; var stream = ev.GetFirstTagValue("streaming") ?? ev.GetFirstTagValue("recording") ?? "";
var image = ev.GetFirstTagValue("image") ?? hostProfile?.Picture ?? $"https://robohash.v0l.io/{ev.PubKey.ToHex()}.png"; var image = ev.GetFirstTagValue("image") ??
hostProfile?.Picture ?? $"https://robohash.v0l.io/{ev.PubKey.ToHex()}.png";
ret.AddRange(new KeyValuePair<string, string>[] ret.AddRange(new KeyValuePair<string, string>[]
{ {
new("og:type", "video.other"), new("og:type", "video.other"),
@ -145,7 +139,8 @@ public class OpenGraphController : Controller
case 1_313: // stream clip case 1_313: // stream clip
{ {
var stream = ev.GetFirstTagValue("r")!; var stream = ev.GetFirstTagValue("r")!;
var image = ev.GetFirstTagValue("image") ?? profile?.Picture ?? $"https://robohash.v0l.io/{ev.PubKey.ToHex()}.png"; var image = ev.GetFirstTagValue("image") ??
profile?.Picture ?? $"https://robohash.v0l.io/{ev.PubKey.ToHex()}.png";
ret.AddRange(new KeyValuePair<string, string>[] ret.AddRange(new KeyValuePair<string, string>[]
{ {
new("og:type", "video.other"), new("og:type", "video.other"),
@ -212,15 +207,24 @@ public class OpenGraphController : Controller
foreach (var ex in tags) foreach (var ex in tags)
{ {
var tag = doc.CreateElement(ex.Element); IElement tag = doc.Head?.Children.FirstOrDefault(a =>
{
if (ex.Element == "meta")
{
var metaPropertyA = a.Attributes.FirstOrDefault(b => b.Name == "property");
var metaPropertyB = ex.Attributes.FirstOrDefault(b => b is { Key: "property" });
return metaPropertyA?.Value == metaPropertyB.Value;
}
return false;
}) ?? AddNewTag(ex);
foreach (var attr in ex.Attributes) foreach (var attr in ex.Attributes)
{ {
tag.SetAttribute(attr.Key, attr.Value); tag.SetAttribute(attr.Key, attr.Value);
} }
doc.Head?.AppendChild(tag); var isOgTitle = ex.Attributes.Any(a => a is { Key: "property", Value: "og:title" });
var isOgTitle = ex.Attributes.Any(a => a is {Key: "property", Value: "og:title"});
if (isOgTitle && doc.Head != default) if (isOgTitle && doc.Head != default)
{ {
var titleTag = doc.Head.QuerySelector("title"); var titleTag = doc.Head.QuerySelector("title");
@ -238,7 +242,7 @@ public class OpenGraphController : Controller
} }
} }
var isOgDesc = ex.Attributes.Any(a => a is {Key: "property", Value: "og:description"}); var isOgDesc = ex.Attributes.Any(a => a is { Key: "property", Value: "og:description" });
if (isOgDesc && doc.Head != default) if (isOgDesc && doc.Head != default)
{ {
var ogDesc = ex.Attributes.FirstOrDefault(a => a.Key is "content"); var ogDesc = ex.Attributes.FirstOrDefault(a => a.Key is "content");
@ -256,6 +260,15 @@ public class OpenGraphController : Controller
descriptionTag.SetAttribute("content", ogDesc.Value); descriptionTag.SetAttribute("content", ogDesc.Value);
} }
} }
continue;
IElement AddNewTag(HeadElement he)
{
var tx = doc!.CreateElement(he.Element);
doc.Head?.AppendChild(tx);
return tx;
}
} }
return doc; return doc;
@ -295,4 +308,4 @@ class CachedMeta
[ProtoMember(5)] [ProtoMember(5)]
public CompactEvent? Event { get; init; } public CompactEvent? Event { get; init; }
} }