Improve performance

This commit is contained in:
Melroy van den Berg 2025-04-25 00:43:10 +02:00
parent b951b920ac
commit 1c8dad5500
No known key found for this signature in database
GPG key ID: 71D11FF23454B9D7

View file

@ -20,11 +20,8 @@ func Format(data map[string]interface{}) (string, error) {
return "", fmt.Errorf("error formatting JSON: %v", err) return "", fmt.Errorf("error formatting JSON: %v", err)
} }
// Convert to string for gjson parsing
jsonStr := string(jsonData)
// Create a summary based on the object type // Create a summary based on the object type
summary := createSummary(jsonStr) summary := createSummary(jsonData)
// Combine the full JSON first, followed by the summary at the bottom // Combine the full JSON first, followed by the summary at the bottom
result := fmt.Sprintf("%s\n\n%s", string(jsonData), summary) result := fmt.Sprintf("%s\n\n%s", string(jsonData), summary)
@ -32,13 +29,13 @@ func Format(data map[string]interface{}) (string, error) {
} }
// createSummary generates a human-readable summary of the ActivityPub object or nodeinfo // createSummary generates a human-readable summary of the ActivityPub object or nodeinfo
func createSummary(jsonStr string) string { func createSummary(jsonStr []byte) string {
// Try to detect nodeinfo // Try to detect nodeinfo
if gjson.Get(jsonStr, "software.name").Exists() && gjson.Get(jsonStr, "version").Exists() { if gjson.GetBytes(jsonStr, "software.name").Exists() && gjson.GetBytes(jsonStr, "version").Exists() {
return nodeInfoSummary(jsonStr) return nodeInfoSummary(jsonStr)
} }
objectType := gjson.Get(jsonStr, "type").String() objectType := gjson.GetBytes(jsonStr, "type").String()
// Build a header with the object type // Build a header with the object type
bold := color.New(color.Bold).SprintFunc() bold := color.New(color.Bold).SprintFunc()
@ -50,7 +47,7 @@ func createSummary(jsonStr string) string {
header := fmt.Sprintf("%s: %s\n", bold("Type"), cyan(objectType)) header := fmt.Sprintf("%s: %s\n", bold("Type"), cyan(objectType))
// Add sensitive content warning if present // Add sensitive content warning if present
if gjson.Get(jsonStr, "sensitive").Bool() { if gjson.GetBytes(jsonStr, "sensitive").Bool() {
header += fmt.Sprintf("%s: %s\n", red(bold("WARNING")), red("Sensitive Content!")) header += fmt.Sprintf("%s: %s\n", red(bold("WARNING")), red("Sensitive Content!"))
} }
@ -59,7 +56,7 @@ func createSummary(jsonStr string) string {
summaryParts = append(summaryParts, header) summaryParts = append(summaryParts, header)
// Add ID if available // Add ID if available
if id := gjson.Get(jsonStr, "id").String(); id != "" { if id := gjson.GetBytes(jsonStr, "id").String(); id != "" {
summaryParts = append(summaryParts, fmt.Sprintf("%s: %s", bold("Original URL"), green(id))) summaryParts = append(summaryParts, fmt.Sprintf("%s: %s", bold("Original URL"), green(id)))
} }
@ -85,7 +82,7 @@ func createSummary(jsonStr string) string {
} }
// nodeInfoSummary generates a summary for nodeinfo objects // nodeInfoSummary generates a summary for nodeinfo objects
func nodeInfoSummary(jsonStr string) string { func nodeInfoSummary(jsonStr []byte) string {
bold := color.New(color.Bold).SprintFunc() bold := color.New(color.Bold).SprintFunc()
cyan := color.New(color.FgCyan).SprintFunc() cyan := color.New(color.FgCyan).SprintFunc()
green := color.New(color.FgGreen).SprintFunc() green := color.New(color.FgGreen).SprintFunc()
@ -93,14 +90,14 @@ func nodeInfoSummary(jsonStr string) string {
red := color.New(color.FgRed).SprintFunc() red := color.New(color.FgRed).SprintFunc()
parts := []string{} parts := []string{}
parts = append(parts, fmt.Sprintf("%s: %s", bold("NodeInfo Version"), cyan(gjson.Get(jsonStr, "version").String()))) parts = append(parts, fmt.Sprintf("%s: %s", bold("NodeInfo Version"), cyan(gjson.GetBytes(jsonStr, "version").String())))
parts = append(parts, fmt.Sprintf("%s: %s %s", bold("Software"), green(gjson.Get(jsonStr, "software.name").String()), yellow(gjson.Get(jsonStr, "software.version").String()))) parts = append(parts, fmt.Sprintf("%s: %s %s", bold("Software"), green(gjson.GetBytes(jsonStr, "software.name").String()), yellow(gjson.GetBytes(jsonStr, "software.version").String())))
if repo := gjson.Get(jsonStr, "software.repository").String(); repo != "" { if repo := gjson.GetBytes(jsonStr, "software.repository").String(); repo != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Repository"), green(repo))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Repository"), green(repo)))
} }
// Color openRegistrations green if true, red if false // Color openRegistrations green if true, red if false
openReg := gjson.Get(jsonStr, "openRegistrations") openReg := gjson.GetBytes(jsonStr, "openRegistrations")
openRegStr := openReg.String() openRegStr := openReg.String()
var openRegColored string var openRegColored string
if openReg.Exists() { if openReg.Exists() {
@ -113,66 +110,66 @@ func nodeInfoSummary(jsonStr string) string {
openRegColored = openRegStr openRegColored = openRegStr
} }
parts = append(parts, fmt.Sprintf("%s: %s", bold("Open Registrations"), openRegColored)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Open Registrations"), openRegColored))
if protocols := gjson.Get(jsonStr, "protocols").Array(); len(protocols) > 0 { if protocols := gjson.GetBytes(jsonStr, "protocols").Array(); len(protocols) > 0 {
var plist []string var plist []string
for _, p := range protocols { for _, p := range protocols {
plist = append(plist, p.String()) plist = append(plist, p.String())
} }
parts = append(parts, fmt.Sprintf("%s: %s", bold("Protocols"), strings.Join(plist, ", "))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Protocols"), strings.Join(plist, ", ")))
} }
if users := gjson.Get(jsonStr, "usage.users.total").Int(); users > 0 { if users := gjson.GetBytes(jsonStr, "usage.users.total").Int(); users > 0 {
activeMonth := gjson.Get(jsonStr, "usage.users.activeMonth").Int() activeMonth := gjson.GetBytes(jsonStr, "usage.users.activeMonth").Int()
activeHalfyear := gjson.Get(jsonStr, "usage.users.activeHalfyear").Int() activeHalfyear := gjson.GetBytes(jsonStr, "usage.users.activeHalfyear").Int()
parts = append(parts, fmt.Sprintf("%s: %d (active month: %d, halfyear: %d)", bold("Users"), users, activeMonth, activeHalfyear)) parts = append(parts, fmt.Sprintf("%s: %d (active month: %d, halfyear: %d)", bold("Users"), users, activeMonth, activeHalfyear))
} }
if posts := gjson.Get(jsonStr, "usage.localPosts").Int(); posts > 0 { if posts := gjson.GetBytes(jsonStr, "usage.localPosts").Int(); posts > 0 {
parts = append(parts, fmt.Sprintf("%s: %d", bold("Local Posts"), posts)) parts = append(parts, fmt.Sprintf("%s: %d", bold("Local Posts"), posts))
} }
if comments := gjson.Get(jsonStr, "usage.localComments").Int(); comments > 0 { if comments := gjson.GetBytes(jsonStr, "usage.localComments").Int(); comments > 0 {
parts = append(parts, fmt.Sprintf("%s: %d", bold("Local Comments"), comments)) parts = append(parts, fmt.Sprintf("%s: %d", bold("Local Comments"), comments))
} }
if nodeName := gjson.Get(jsonStr, "metadata.nodeName").String(); nodeName != "" { if nodeName := gjson.GetBytes(jsonStr, "metadata.nodeName").String(); nodeName != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Node Name"), cyan(nodeName))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Node Name"), cyan(nodeName)))
} }
if nodeDesc := gjson.Get(jsonStr, "metadata.nodeDescription").String(); nodeDesc != "" { if nodeDesc := gjson.GetBytes(jsonStr, "metadata.nodeDescription").String(); nodeDesc != "" {
parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Node Description"), nodeDesc)) parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Node Description"), nodeDesc))
} }
return strings.Join(parts, "\n") return strings.Join(parts, "\n")
} }
// formatActor formats actor-type objects (Person, Service, etc.) // formatActor formats actor-type objects (Person, Service, etc.)
func formatActor(jsonStr string, parts []string, bold, cyan, green, red, yellow func(a ...interface{}) string) []string { func formatActor(jsonStr []byte, parts []string, bold, cyan, green, red, yellow func(a ...interface{}) string) []string {
if name := gjson.Get(jsonStr, "name").String(); name != "" { if name := gjson.GetBytes(jsonStr, "name").String(); name != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Name"), cyan(name))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Name"), cyan(name)))
} }
if preferredUsername := gjson.Get(jsonStr, "preferredUsername").String(); preferredUsername != "" { if preferredUsername := gjson.GetBytes(jsonStr, "preferredUsername").String(); preferredUsername != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Username"), red(preferredUsername))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Username"), red(preferredUsername)))
} }
if url := gjson.Get(jsonStr, "url").String(); url != "" { if url := gjson.GetBytes(jsonStr, "url").String(); url != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("URL"), green(url))) parts = append(parts, fmt.Sprintf("%s: %s", bold("URL"), green(url)))
} }
iconUrl := gjson.Get(jsonStr, "icon.url").String() iconUrl := gjson.GetBytes(jsonStr, "icon.url").String()
if iconUrl != "" { if iconUrl != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Avatar"), green(iconUrl))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Avatar"), green(iconUrl)))
} }
if summary := gjson.Get(jsonStr, "summary").String(); summary != "" { if summary := gjson.GetBytes(jsonStr, "summary").String(); summary != "" {
md := htmlToMarkdown(summary) md := htmlToMarkdown(summary)
parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Summary"), renderMarkdown(md))) parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Summary"), renderMarkdown(md)))
} }
if published := gjson.Get(jsonStr, "published").String(); published != "" { if published := gjson.GetBytes(jsonStr, "published").String(); published != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published))))
} }
if followers := gjson.Get(jsonStr, "followers").String(); followers != "" { if followers := gjson.GetBytes(jsonStr, "followers").String(); followers != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Followers"), green(followers))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Followers"), green(followers)))
} }
if following := gjson.Get(jsonStr, "following").String(); following != "" { if following := gjson.GetBytes(jsonStr, "following").String(); following != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Following"), green(following))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Following"), green(following)))
} }
@ -180,13 +177,13 @@ func formatActor(jsonStr string, parts []string, bold, cyan, green, red, yellow
} }
// formatContent formats content-type objects (Note, Article, Page, etc.) // formatContent formats content-type objects (Note, Article, Page, etc.)
func formatContent(jsonStr string, parts []string, bold, green, yellow func(a ...interface{}) string) []string { func formatContent(jsonStr []byte, parts []string, bold, green, yellow func(a ...interface{}) string) []string {
// Show the name/title if present (especially for Page/thread) // Show the name/title if present (especially for Page/thread)
if name := gjson.Get(jsonStr, "name").String(); name != "" { if name := gjson.GetBytes(jsonStr, "name").String(); name != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Title"), name)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Title"), name))
} }
if content := gjson.Get(jsonStr, "content").String(); content != "" { if content := gjson.GetBytes(jsonStr, "content").String(); content != "" {
md := htmlToMarkdown(content) md := htmlToMarkdown(content)
// Truncate the content if its too big. // Truncate the content if its too big.
if len(md) > 1200 { if len(md) > 1200 {
@ -196,7 +193,7 @@ func formatContent(jsonStr string, parts []string, bold, green, yellow func(a ..
} }
// Check for attachments (images, videos, etc.) // Check for attachments (images, videos, etc.)
attachments := gjson.Get(jsonStr, "attachment").Array() attachments := gjson.GetBytes(jsonStr, "attachment").Array()
if len(attachments) > 0 { if len(attachments) > 0 {
parts = append(parts, fmt.Sprintf("%s:", bold("Attachments"))) parts = append(parts, fmt.Sprintf("%s:", bold("Attachments")))
for i, attachment := range attachments { for i, attachment := range attachments {
@ -221,7 +218,7 @@ func formatContent(jsonStr string, parts []string, bold, green, yellow func(a ..
parts = append(parts, attachmentInfo) parts = append(parts, attachmentInfo)
// For type Page and attachment type Link, show href if present // For type Page and attachment type Link, show href if present
objectType := gjson.Get(jsonStr, "type").String() objectType := gjson.GetBytes(jsonStr, "type").String()
if objectType == "Page" && attachmentType == "Link" && href != "" { if objectType == "Page" && attachmentType == "Link" && href != "" {
parts = append(parts, fmt.Sprintf(" URL: %s", green(href))) parts = append(parts, fmt.Sprintf(" URL: %s", green(href)))
} else if url != "" { } else if url != "" {
@ -230,39 +227,39 @@ func formatContent(jsonStr string, parts []string, bold, green, yellow func(a ..
} }
} }
if published := gjson.Get(jsonStr, "published").String(); published != "" { if published := gjson.GetBytes(jsonStr, "published").String(); published != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published))))
} }
if updated := gjson.Get(jsonStr, "updated").String(); updated != "" { if updated := gjson.GetBytes(jsonStr, "updated").String(); updated != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Updated"), yellow(formatDate(updated)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Updated"), yellow(formatDate(updated))))
} }
if attributedTo := gjson.Get(jsonStr, "attributedTo").String(); attributedTo != "" { if attributedTo := gjson.GetBytes(jsonStr, "attributedTo").String(); attributedTo != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Author"), green(attributedTo))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Author"), green(attributedTo)))
} }
if to := gjson.Get(jsonStr, "to").Array(); len(to) > 0 { if to := gjson.GetBytes(jsonStr, "to").Array(); len(to) > 0 {
parts = append(parts, fmt.Sprintf("%s: %s", bold("To"), green(formatArray(to)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("To"), green(formatArray(to))))
} }
if cc := gjson.Get(jsonStr, "cc").Array(); len(cc) > 0 { if cc := gjson.GetBytes(jsonStr, "cc").Array(); len(cc) > 0 {
parts = append(parts, fmt.Sprintf("%s: %s", bold("CC"), green(formatArray(cc)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("CC"), green(formatArray(cc))))
} }
if inReplyTo := gjson.Get(jsonStr, "inReplyTo").String(); inReplyTo != "" { if inReplyTo := gjson.GetBytes(jsonStr, "inReplyTo").String(); inReplyTo != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("In Reply To"), green(inReplyTo))) parts = append(parts, fmt.Sprintf("%s: %s", bold("In Reply To"), green(inReplyTo)))
} }
// Include endTime for Question type // Include endTime for Question type
if endTime := gjson.Get(jsonStr, "endTime").String(); endTime != "" { if endTime := gjson.GetBytes(jsonStr, "endTime").String(); endTime != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("End Time"), yellow(formatDate(endTime)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("End Time"), yellow(formatDate(endTime))))
} }
// Include options (oneOf/anyOf) for Question type // Include options (oneOf/anyOf) for Question type
options := gjson.Get(jsonStr, "oneOf").Array() options := gjson.GetBytes(jsonStr, "oneOf").Array()
if len(options) == 0 { if len(options) == 0 {
options = gjson.Get(jsonStr, "anyOf").Array() options = gjson.GetBytes(jsonStr, "anyOf").Array()
} }
if len(options) > 0 { if len(options) > 0 {
parts = append(parts, fmt.Sprintf("%s:", bold("Poll Options"))) parts = append(parts, fmt.Sprintf("%s:", bold("Poll Options")))
@ -276,24 +273,24 @@ func formatContent(jsonStr string, parts []string, bold, green, yellow func(a ..
} }
// formatActivity formats activity-type objects (Create, Like, etc.) // formatActivity formats activity-type objects (Create, Like, etc.)
func formatActivity(jsonStr string, parts []string, bold, green, yellow func(a ...interface{}) string) []string { func formatActivity(jsonStr []byte, parts []string, bold, green, yellow func(a ...interface{}) string) []string {
if actor := gjson.Get(jsonStr, "actor").String(); actor != "" { if actor := gjson.GetBytes(jsonStr, "actor").String(); actor != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Actor"), actor)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Actor"), actor))
} }
if object := gjson.Get(jsonStr, "object").String(); object != "" { if object := gjson.GetBytes(jsonStr, "object").String(); object != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Object"), object)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Object"), object))
} else if gjson.Get(jsonStr, "object").IsObject() { } else if gjson.GetBytes(jsonStr, "object").IsObject() {
objectType := gjson.Get(jsonStr, "object.type").String() objectType := gjson.GetBytes(jsonStr, "object.type").String()
parts = append(parts, fmt.Sprintf("%s: %s", bold("Object Type"), yellow(objectType))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Object Type"), yellow(objectType)))
if content := gjson.Get(jsonStr, "object.content").String(); content != "" { if content := gjson.GetBytes(jsonStr, "object.content").String(); content != "" {
md := htmlToMarkdown(content) md := htmlToMarkdown(content)
parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Content"), renderMarkdown(md))) parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Content"), renderMarkdown(md)))
} }
// Check for attachments in the object // Check for attachments in the object
attachments := gjson.Get(jsonStr, "object.attachment").Array() attachments := gjson.GetBytes(jsonStr, "object.attachment").Array()
if len(attachments) > 0 { if len(attachments) > 0 {
parts = append(parts, fmt.Sprintf("%s:", bold("Attachments"))) parts = append(parts, fmt.Sprintf("%s:", bold("Attachments")))
for i, attachment := range attachments { for i, attachment := range attachments {
@ -323,11 +320,11 @@ func formatActivity(jsonStr string, parts []string, bold, green, yellow func(a .
} }
} }
if published := gjson.Get(jsonStr, "published").String(); published != "" { if published := gjson.GetBytes(jsonStr, "published").String(); published != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published))))
} }
if target := gjson.Get(jsonStr, "target").String(); target != "" { if target := gjson.GetBytes(jsonStr, "target").String(); target != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Target"), target)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Target"), target))
} }
@ -335,15 +332,15 @@ func formatActivity(jsonStr string, parts []string, bold, green, yellow func(a .
} }
// formatCollection formats collection-type objects // formatCollection formats collection-type objects
func formatCollection(jsonStr string, parts []string, bold, green, yellow func(a ...interface{}) string) []string { func formatCollection(jsonStr []byte, parts []string, bold, green, yellow func(a ...interface{}) string) []string {
if totalItems := gjson.Get(jsonStr, "totalItems").Int(); totalItems > 0 { if totalItems := gjson.GetBytes(jsonStr, "totalItems").Int(); totalItems > 0 {
parts = append(parts, fmt.Sprintf("%s: %d", bold("Total Items"), totalItems)) parts = append(parts, fmt.Sprintf("%s: %d", bold("Total Items"), totalItems))
} }
// Show first few items if available // Show first few items if available
items := gjson.Get(jsonStr, "items").Array() items := gjson.GetBytes(jsonStr, "items").Array()
if len(items) == 0 { if len(items) == 0 {
items = gjson.Get(jsonStr, "orderedItems").Array() items = gjson.GetBytes(jsonStr, "orderedItems").Array()
} }
if len(items) > 0 { if len(items) > 0 {
@ -366,7 +363,7 @@ func formatCollection(jsonStr string, parts []string, bold, green, yellow func(a
} }
} }
if published := gjson.Get(jsonStr, "published").String(); published != "" { if published := gjson.GetBytes(jsonStr, "published").String(); published != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published))))
} }
@ -374,24 +371,24 @@ func formatCollection(jsonStr string, parts []string, bold, green, yellow func(a
} }
// formatMedia formats media-type objects (Image, Video, etc.) // formatMedia formats media-type objects (Image, Video, etc.)
func formatMedia(jsonStr string, parts []string, bold, green, yellow func(a ...interface{}) string) []string { func formatMedia(jsonStr []byte, parts []string, bold, green, yellow func(a ...interface{}) string) []string {
if name := gjson.Get(jsonStr, "name").String(); name != "" { if name := gjson.GetBytes(jsonStr, "name").String(); name != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Title"), name)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Title"), name))
} }
if url := gjson.Get(jsonStr, "url").String(); url != "" { if url := gjson.GetBytes(jsonStr, "url").String(); url != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("URL"), green(url))) parts = append(parts, fmt.Sprintf("%s: %s", bold("URL"), green(url)))
} }
if duration := gjson.Get(jsonStr, "duration").String(); duration != "" { if duration := gjson.GetBytes(jsonStr, "duration").String(); duration != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Duration"), duration)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Duration"), duration))
} }
if published := gjson.Get(jsonStr, "published").String(); published != "" { if published := gjson.GetBytes(jsonStr, "published").String(); published != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Published"), yellow(formatDate(published))))
} }
if attributedTo := gjson.Get(jsonStr, "attributedTo").String(); attributedTo != "" { if attributedTo := gjson.GetBytes(jsonStr, "attributedTo").String(); attributedTo != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Author"), attributedTo)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Author"), attributedTo))
} }
@ -399,25 +396,25 @@ func formatMedia(jsonStr string, parts []string, bold, green, yellow func(a ...i
} }
// formatEvent formats event-type objects // formatEvent formats event-type objects
func formatEvent(jsonStr string, parts []string, bold, yellow func(a ...interface{}) string) []string { func formatEvent(jsonStr []byte, parts []string, bold, yellow func(a ...interface{}) string) []string {
if name := gjson.Get(jsonStr, "name").String(); name != "" { if name := gjson.GetBytes(jsonStr, "name").String(); name != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Title"), name)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Title"), name))
} }
if content := gjson.Get(jsonStr, "content").String(); content != "" { if content := gjson.GetBytes(jsonStr, "content").String(); content != "" {
md := htmlToMarkdown(content) md := htmlToMarkdown(content)
parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Description"), renderMarkdown(md))) parts = append(parts, fmt.Sprintf("%s:\n%s", bold("Description"), renderMarkdown(md)))
} }
if startTime := gjson.Get(jsonStr, "startTime").String(); startTime != "" { if startTime := gjson.GetBytes(jsonStr, "startTime").String(); startTime != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Start Time"), yellow(formatDate(startTime)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Start Time"), yellow(formatDate(startTime))))
} }
if endTime := gjson.Get(jsonStr, "endTime").String(); endTime != "" { if endTime := gjson.GetBytes(jsonStr, "endTime").String(); endTime != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("End Time"), yellow(formatDate(endTime)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("End Time"), yellow(formatDate(endTime))))
} }
if location := gjson.Get(jsonStr, "location").String(); location != "" { if location := gjson.GetBytes(jsonStr, "location").String(); location != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Location"), location)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Location"), location))
} }
@ -425,12 +422,12 @@ func formatEvent(jsonStr string, parts []string, bold, yellow func(a ...interfac
} }
// formatTombstone formats tombstone-type objects // formatTombstone formats tombstone-type objects
func formatTombstone(jsonStr string, parts []string, bold, green, yellow func(a ...interface{}) string) []string { func formatTombstone(jsonStr []byte, parts []string, bold, green, yellow func(a ...interface{}) string) []string {
if formerType := gjson.Get(jsonStr, "formerType").String(); formerType != "" { if formerType := gjson.GetBytes(jsonStr, "formerType").String(); formerType != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Former Type"), formerType)) parts = append(parts, fmt.Sprintf("%s: %s", bold("Former Type"), formerType))
} }
if deleted := gjson.Get(jsonStr, "deleted").String(); deleted != "" { if deleted := gjson.GetBytes(jsonStr, "deleted").String(); deleted != "" {
parts = append(parts, fmt.Sprintf("%s: %s", bold("Deleted"), yellow(formatDate(deleted)))) parts = append(parts, fmt.Sprintf("%s: %s", bold("Deleted"), yellow(formatDate(deleted))))
} }