From 3b2c8a4c78ade9e819b61aa055039ae00e517a3e Mon Sep 17 00:00:00 2001 From: FChannel <> Date: Thu, 22 Jul 2021 13:50:11 -0700 Subject: fixed quote bug and moved comment parsing server side without javascript --- client.go | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 114 insertions(+), 12 deletions(-) (limited to 'client.go') diff --git a/client.go b/client.go index af83a28..12e6147 100644 --- a/client.go +++ b/client.go @@ -1,14 +1,17 @@ package main -import "net/http" -import "html/template" -import "database/sql" -import _ "github.com/lib/pq" -import "strings" -import "strconv" -import "sort" -import "regexp" -import "time" +import ( + "net/http" + "html/template" + "database/sql" + _ "github.com/lib/pq" + "strings" + "strconv" + "sort" + "regexp" + "time" + "fmt" +) var Key *string = new(string) @@ -116,6 +119,7 @@ func IndexGet(w http.ResponseWriter, r *http.Request, db *sql.DB) { if(len(data.BoardRemainer) == 3){ data.BoardRemainer = make([]int, 0) } + data.InstanceIndex = GetCollectionFromReq("https://fchan.xyz/followers").Items data.NewsItems = getNewsFromDB(db, 3) @@ -184,6 +188,9 @@ func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Co "proxy": func(url string) string { return MediaProxy(url) }, + "short": func(actorName string, url string) string { + return shortURL(actorName, url) + }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/nposts.html", "./static/top.html", "./static/bottom.html", "./static/posts.html")) @@ -219,6 +226,14 @@ func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Co returnData.Boards = Boards returnData.Posts = collection.OrderedItems + for i, e := range returnData.Posts { + returnData.Posts[i].ContentHTML = ParseContent(db, returnData.Board.Actor, e.Id, e.Content, e) + + for j, k := range e.Replies.OrderedItems { + returnData.Posts[i].Replies.OrderedItems[j].ContentHTML = ParseContent(db, returnData.Board.Actor, e.Id, k.Content, e) + } + } + var offset = 8 var pages []int pageLimit := (float64(collection.TotalItems) / float64(offset)) @@ -236,7 +251,10 @@ func CatalogGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection C t := template.Must(template.New("").Funcs(template.FuncMap{ "proxy": func(url string) string { return MediaProxy(url) - }, + }, + "short": func(actorName string, url string) string { + return shortURL(actorName, url) + }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/ncatalog.html", "./static/top.html")) actor := collection.Actor @@ -273,7 +291,10 @@ func PostGet(w http.ResponseWriter, r *http.Request, db *sql.DB){ t := template.Must(template.New("").Funcs(template.FuncMap{ "proxy": func(url string) string { return MediaProxy(url) - }, + }, + "short": func(actorName string, url string) string { + return shortURL(actorName, url) + }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/npost.html", "./static/top.html", "./static/bottom.html", "./static/posts.html")) path := r.URL.Path @@ -333,6 +354,14 @@ func PostGet(w http.ResponseWriter, r *http.Request, db *sql.DB){ if len(returnData.Posts) > 0 { returnData.PostId = shortURL(returnData.Board.To, returnData.Posts[0].Id) + + for i, e := range returnData.Posts { + returnData.Posts[i].ContentHTML = ParseContent(db, returnData.Board.Actor, e.Id, e.Content, e) + + for j, k := range e.Replies.OrderedItems { + returnData.Posts[i].Replies.OrderedItems[j].ContentHTML = ParseContent(db, returnData.Board.Actor, e.Id, k.Content, e) + } + } } t.ExecuteTemplate(w, "layout", returnData) @@ -596,7 +625,80 @@ func MediaProxy(url string) string { if re.MatchString(url) { return url } - + + fmt.Println("") MediaHashs[HashMedia(url)] = url return "/api/media?hash=" + HashMedia(url) } + +func ParseContent(db *sql.DB, board Actor, op string, content string, thread ObjectBase) template.HTML { + var nContent = content + + re := regexp.MustCompile(`(>>https?:\/\/[A-Za-z0-9_.-~]+\/[A-Za-z0-9_.-~]+\/\w+)`) + match := re.FindAllStringSubmatch(nContent, -1) + + //add url to each matched reply + for i, _ := range match { + link := strings.Replace(match[i][0], ">>", "", 1) + isOP := "" + + if link == op { + isOP = " (OP)" + } + + //formate the hover title text + var quoteTitle string + + // if the quoted content is local get it + // else get it from the database + if thread.Id == link { + quoteTitle = thread.Content + } else { + for _, e := range thread.Replies.OrderedItems { + if e.Id == link { + quoteTitle = e.Content + break + } + } + + if quoteTitle == "" { + obj := GetObjectFromDBFromID(db, link) + if len(obj.OrderedItems) > 0 { + quoteTitle = obj.OrderedItems[0].Content + } + } + } + + quoteTitle = strings.ReplaceAll(quoteTitle, ">", `/\<`) + quoteTitle = strings.ReplaceAll(quoteTitle, "\"", "") + quoteTitle = strings.ReplaceAll(quoteTitle, "'", "") + + + var style string + if board.Restricted { + style = "color: #af0a0f;" + } + + //replace link with quote format + nContent = strings.Replace(nContent, match[i][0], " >>" + shortURL(board.Outbox, link) + isOP + "", -1) + } + + // replace quotes + re = regexp.MustCompile(`((\r\n|^)>(.+)?[^\r\n])`) + match = re.FindAllStringSubmatch(nContent, -1) + + for i, _ := range match { + quote := strings.Replace(match[i][0], ">", ">", 1) + line := re.ReplaceAllString(match[i][0], "" + quote + "") + nContent = strings.Replace(nContent, match[i][0], line, 1) + } + + //replace isolated greater than symboles + re = regexp.MustCompile(`(\r\n)>`) + + nContent = re.ReplaceAllString(nContent, "\r\n>") + + nContent = strings.ReplaceAll(nContent, `/\<`, ">") + + return template.HTML(nContent) +} -- cgit v1.2.3 From fa895350a8bdf2eb93495dbf569fa3fe0680d2af Mon Sep 17 00:00:00 2001 From: FChannel <> Date: Thu, 22 Jul 2021 15:14:14 -0700 Subject: removed media javascript parsing it on server --- client.go | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) (limited to 'client.go') diff --git a/client.go b/client.go index 12e6147..5d824bf 100644 --- a/client.go +++ b/client.go @@ -190,7 +190,10 @@ func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Co }, "short": func(actorName string, url string) string { return shortURL(actorName, url) - }, + }, + "parseAttachment": func(obj ObjectBase, catalog bool) template.HTML { + return ParseAttachment(obj, catalog) + }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/nposts.html", "./static/top.html", "./static/bottom.html", "./static/posts.html")) @@ -254,6 +257,9 @@ func CatalogGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection C }, "short": func(actorName string, url string) string { return shortURL(actorName, url) + }, + "parseAttachment": func(obj ObjectBase, catalog bool) template.HTML { + return ParseAttachment(obj, catalog) }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/ncatalog.html", "./static/top.html")) actor := collection.Actor @@ -294,6 +300,9 @@ func PostGet(w http.ResponseWriter, r *http.Request, db *sql.DB){ }, "short": func(actorName string, url string) string { return shortURL(actorName, url) + }, + "parseAttachment": func(obj ObjectBase, catalog bool) template.HTML { + return ParseAttachment(obj, catalog) }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/npost.html", "./static/top.html", "./static/bottom.html", "./static/posts.html")) @@ -702,3 +711,78 @@ func ParseContent(db *sql.DB, board Actor, op string, content string, thread Obj return template.HTML(nContent) } + +func ParseAttachment(obj ObjectBase, catalog bool) template.HTML { + + if len(obj.Attachment) < 1 { + return "" + } + + var media string + if(regexp.MustCompile(`image\/`).MatchString(obj.Attachment[0].MediaType)){ + media = " Date: Thu, 22 Jul 2021 16:08:51 -0700 Subject: regex escape hyphens in regex for quote and replies --- client.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'client.go') diff --git a/client.go b/client.go index 5d824bf..f47ca52 100644 --- a/client.go +++ b/client.go @@ -10,7 +10,6 @@ import ( "sort" "regexp" "time" - "fmt" ) var Key *string = new(string) @@ -635,7 +634,6 @@ func MediaProxy(url string) string { return url } - fmt.Println("") MediaHashs[HashMedia(url)] = url return "/api/media?hash=" + HashMedia(url) } @@ -643,7 +641,7 @@ func MediaProxy(url string) string { func ParseContent(db *sql.DB, board Actor, op string, content string, thread ObjectBase) template.HTML { var nContent = content - re := regexp.MustCompile(`(>>https?:\/\/[A-Za-z0-9_.-~]+\/[A-Za-z0-9_.-~]+\/\w+)`) + re := regexp.MustCompile(`(>>https?://[A-Za-z0-9_.\-~]+\/[A-Za-z0-9_.\-~]+\/\w+)`) match := re.FindAllStringSubmatch(nContent, -1) //add url to each matched reply -- cgit v1.2.3 From 16b4165e5102fc9b4766e1bd1204ca9cf23199aa Mon Sep 17 00:00:00 2001 From: FChannel <> Date: Thu, 22 Jul 2021 19:03:28 -0700 Subject: added banning media by saving hash in database --- client.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'client.go') diff --git a/client.go b/client.go index f47ca52..002fc40 100644 --- a/client.go +++ b/client.go @@ -641,7 +641,7 @@ func MediaProxy(url string) string { func ParseContent(db *sql.DB, board Actor, op string, content string, thread ObjectBase) template.HTML { var nContent = content - re := regexp.MustCompile(`(>>https?://[A-Za-z0-9_.\-~]+\/[A-Za-z0-9_.\-~]+\/\w+)`) + re := regexp.MustCompile(`(>>https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/\w+)`) match := re.FindAllStringSubmatch(nContent, -1) //add url to each matched reply -- cgit v1.2.3 From 8f7386f2906716d40099fb50f029d48796dd1bbd Mon Sep 17 00:00:00 2001 From: FChannel <> Date: Fri, 23 Jul 2021 22:45:44 -0700 Subject: added cross post support. could blow up if referencing a link that is not local to the database or cache. --- client.go | 209 ++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 137 insertions(+), 72 deletions(-) (limited to 'client.go') diff --git a/client.go b/client.go index 002fc40..4f2fd70 100644 --- a/client.go +++ b/client.go @@ -638,78 +638,6 @@ func MediaProxy(url string) string { return "/api/media?hash=" + HashMedia(url) } -func ParseContent(db *sql.DB, board Actor, op string, content string, thread ObjectBase) template.HTML { - var nContent = content - - re := regexp.MustCompile(`(>>https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/\w+)`) - match := re.FindAllStringSubmatch(nContent, -1) - - //add url to each matched reply - for i, _ := range match { - link := strings.Replace(match[i][0], ">>", "", 1) - isOP := "" - - if link == op { - isOP = " (OP)" - } - - //formate the hover title text - var quoteTitle string - - // if the quoted content is local get it - // else get it from the database - if thread.Id == link { - quoteTitle = thread.Content - } else { - for _, e := range thread.Replies.OrderedItems { - if e.Id == link { - quoteTitle = e.Content - break - } - } - - if quoteTitle == "" { - obj := GetObjectFromDBFromID(db, link) - if len(obj.OrderedItems) > 0 { - quoteTitle = obj.OrderedItems[0].Content - } - } - } - - quoteTitle = strings.ReplaceAll(quoteTitle, ">", `/\<`) - quoteTitle = strings.ReplaceAll(quoteTitle, "\"", "") - quoteTitle = strings.ReplaceAll(quoteTitle, "'", "") - - - var style string - if board.Restricted { - style = "color: #af0a0f;" - } - - //replace link with quote format - nContent = strings.Replace(nContent, match[i][0], " >>" + shortURL(board.Outbox, link) + isOP + "", -1) - } - - // replace quotes - re = regexp.MustCompile(`((\r\n|^)>(.+)?[^\r\n])`) - match = re.FindAllStringSubmatch(nContent, -1) - - for i, _ := range match { - quote := strings.Replace(match[i][0], ">", ">", 1) - line := re.ReplaceAllString(match[i][0], "" + quote + "") - nContent = strings.Replace(nContent, match[i][0], line, 1) - } - - //replace isolated greater than symboles - re = regexp.MustCompile(`(\r\n)>`) - - nContent = re.ReplaceAllString(nContent, "\r\n>") - - nContent = strings.ReplaceAll(nContent, `/\<`, ">") - - return template.HTML(nContent) -} - func ParseAttachment(obj ObjectBase, catalog bool) template.HTML { if len(obj.Attachment) < 1 { @@ -784,3 +712,140 @@ func ParseAttachment(obj ObjectBase, catalog bool) template.HTML { return template.HTML(media) } + +func ParseContent(db *sql.DB, board Actor, op string, content string, thread ObjectBase) template.HTML { + + nContent := ParseLinkComments(db, board, op, content, thread) + + nContent = ParseCommentQuotes(nContent) + + nContent = strings.ReplaceAll(nContent, `/\<`, ">") + + return template.HTML(nContent) +}; + +func ParseLinkComments(db *sql.DB, board Actor, op string, content string, thread ObjectBase) string { + re := regexp.MustCompile(`(>>(https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/)(f[A-Za-z0-9_.\-~]+-)?([A-Za-z0-9_.\-~]+)?#?([A-Za-z0-9_.\-~]+)?)`) + match := re.FindAllStringSubmatch(content, -1) + + //add url to each matched reply + for i, _ := range match { + link := strings.Replace(match[i][0], ">>", "", 1) + isOP := "" + + domain := match[i][2] + + if link == op { + isOP = " (OP)" + } + + parsedLink := ConvertHashLink(domain, link) + + //formate the hover title text + var quoteTitle string + + // if the quoted content is local get it + // else get it from the database + if thread.Id == link { + quoteTitle = thread.Content + } else { + for _, e := range thread.Replies.OrderedItems { + if e.Id == parsedLink { + quoteTitle = ParseLinkTitle(board.Outbox, op, e.Content) + break + } + } + + if quoteTitle == "" { + obj := GetObjectFromDBFromID(db, parsedLink) + if len(obj.OrderedItems) > 0 { + quoteTitle = ParseLinkTitle(board.Outbox, op, obj.OrderedItems[0].Content) + } else { + quoteTitle = ParseLinkTitle(board.Outbox, op, parsedLink) + } + } + } + + var style string + if board.Restricted { + style = "color: #af0a0f;" + } + + //replace link with quote format + replyID, isReply := IsReplyToOP(db, op, parsedLink) + if isReply { + id := shortURL(board.Outbox, replyID) + + content = strings.Replace(content, match[i][0], ">>" + id + "" + isOP + "", -1) + + } else { + + //this is a cross post + parsedOP := GetReplyOP(db, parsedLink) + + if parsedOP != "" { + link = parsedOP + "#" + shortURL(parsedOP, parsedLink) + } + + content = strings.Replace(content, match[i][0], ">>" + shortURL(board.Outbox, parsedLink) + isOP + " →", -1) + } + } + + return content +} + +func ParseLinkTitle(actorName string, op string, content string) string { + re := regexp.MustCompile(`(>>(https?://[A-Za-z0-9_.:\-~]+\/[A-Za-z0-9_.\-~]+\/)\w+(#.+)?)`) + match := re.FindAllStringSubmatch(content, -1) + + for i, _ := range match { + link := strings.Replace(match[i][0], ">>", "", 1) + isOP := "" + + domain := match[i][2] + + if link == op { + isOP = " (OP)" + } + + link = ConvertHashLink(domain, link) + content = strings.Replace(content, match[i][0], ">>" + shortURL(actorName, link) + isOP , 1) + } + + content = strings.ReplaceAll(content, "'", "") + content = strings.ReplaceAll(content, "\"", "") + content = strings.ReplaceAll(content, ">", `/\<`) + + return content +} + +func ParseCommentQuotes(content string) string { + // replace quotes + re := regexp.MustCompile(`((\r\n|\r|\n|^)>(.+)?[^\r\n])`) + match := re.FindAllStringSubmatch(content, -1) + + for i, _ := range match { + quote := strings.Replace(match[i][0], ">", ">", 1) + line := re.ReplaceAllString(match[i][0], "" + quote + "") + content = strings.Replace(content, match[i][0], line, 1) + } + + //replace isolated greater than symboles + re = regexp.MustCompile(`(\r\n|\n|\r)>`) + + return re.ReplaceAllString(content, "\r\n>") +} + +func ConvertHashLink(domain string, link string) string { + re := regexp.MustCompile(`(#.+)`) + parsedLink := re.FindString(link) + + if parsedLink != "" { + parsedLink = domain + "" + strings.Replace(parsedLink, "#", "", 1) + parsedLink = strings.Replace(parsedLink, "\r", "", -1) + } else { + parsedLink = link + } + + return parsedLink +} -- cgit v1.2.3 From 6c3de825cb50ebcf4c464a742b5480414b8173c4 Mon Sep 17 00:00:00 2001 From: FChannel <> Date: Sun, 25 Jul 2021 14:24:02 -0700 Subject: fixed quote parsing bug --- client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'client.go') diff --git a/client.go b/client.go index 4f2fd70..03f54fa 100644 --- a/client.go +++ b/client.go @@ -747,7 +747,7 @@ func ParseLinkComments(db *sql.DB, board Actor, op string, content string, threa // if the quoted content is local get it // else get it from the database if thread.Id == link { - quoteTitle = thread.Content + quoteTitle = ParseLinkTitle(board.Outbox, op, thread.Content) } else { for _, e := range thread.Replies.OrderedItems { if e.Id == parsedLink { @@ -765,7 +765,7 @@ func ParseLinkComments(db *sql.DB, board Actor, op string, content string, threa } } } - + var style string if board.Restricted { style = "color: #af0a0f;" -- cgit v1.2.3 From 6846150cb48d080112981633d6dddabef5ce4439 Mon Sep 17 00:00:00 2001 From: FChannel <> Date: Sun, 25 Jul 2021 16:00:25 -0700 Subject: fixed bug with escaping html less than symbol for parsing content --- client.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'client.go') diff --git a/client.go b/client.go index 03f54fa..930cd6f 100644 --- a/client.go +++ b/client.go @@ -714,8 +714,10 @@ func ParseAttachment(obj ObjectBase, catalog bool) template.HTML { } func ParseContent(db *sql.DB, board Actor, op string, content string, thread ObjectBase) template.HTML { + + nContent := strings.ReplaceAll(content, `<`, "<") - nContent := ParseLinkComments(db, board, op, content, thread) + nContent = ParseLinkComments(db, board, op, nContent, thread) nContent = ParseCommentQuotes(nContent) -- cgit v1.2.3 From 87fc54c9d41bdbe7eaa8769386776a3723580b34 Mon Sep 17 00:00:00 2001 From: FChannel <> Date: Sun, 25 Jul 2021 17:35:41 -0700 Subject: showing post replies bug fix --- client.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'client.go') diff --git a/client.go b/client.go index 930cd6f..80ec75b 100644 --- a/client.go +++ b/client.go @@ -183,6 +183,7 @@ func AllNewsGet(w http.ResponseWriter, r *http.Request, db *sql.DB) { } func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Collection){ + t := template.Must(template.New("").Funcs(template.FuncMap{ "proxy": func(url string) string { return MediaProxy(url) @@ -192,7 +193,13 @@ func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Co }, "parseAttachment": func(obj ObjectBase, catalog bool) template.HTML { return ParseAttachment(obj, catalog) - }, + }, + "parseReplyLink": func(actorId string, op string, id string, content string) template.HTML { + actor := FingerActor(actorId) + title := strings.ReplaceAll(ParseLinkTitle(actor.Id, op, content), `/\<`, ">") + link := ">>" + shortURL(actor.Outbox, id) + "" + return template.HTML(link) + }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/nposts.html", "./static/top.html", "./static/bottom.html", "./static/posts.html")) @@ -300,9 +307,16 @@ func PostGet(w http.ResponseWriter, r *http.Request, db *sql.DB){ "short": func(actorName string, url string) string { return shortURL(actorName, url) }, + "parseAttachment": func(obj ObjectBase, catalog bool) template.HTML { return ParseAttachment(obj, catalog) - }, + }, + "parseReplyLink": func(actorId string, op string, id string, content string) template.HTML { + actor := FingerActor(actorId) + title := strings.ReplaceAll(ParseLinkTitle(actor.Id, op, content), `/\<`, ">") + link := ">>" + shortURL(actor.Outbox, id) + "" + return template.HTML(link) + }, "sub": func (i, j int) int { return i - j }}).ParseFiles("./static/main.html", "./static/npost.html", "./static/top.html", "./static/bottom.html", "./static/posts.html")) path := r.URL.Path -- cgit v1.2.3