package main import ( "html/template" "regexp" "strings" "github.com/FChannel0/FChannel-Server/activitypub" "github.com/FChannel0/FChannel-Server/config" "github.com/FChannel0/FChannel-Server/db" "github.com/FChannel0/FChannel-Server/util" "github.com/FChannel0/FChannel-Server/webfinger" _ "github.com/lib/pq" ) func MediaProxy(url string) string { re := regexp.MustCompile("(.+)?" + config.Domain + "(.+)?") if re.MatchString(url) { return url } re = regexp.MustCompile("(.+)?\\.onion(.+)?") if re.MatchString(url) { return url } MediaHashs[util.HashMedia(url)] = url return "/api/media?hash=" + util.HashMedia(url) } func ParseAttachment(obj activitypub.ObjectBase, catalog bool) template.HTML { // TODO: convert all of these to Sprintf statements, or use strings.Builder or something, anything but this really // string concatenation is highly inefficient _especially_ when being used like this if len(obj.Attachment) < 1 { return "" } var media string if regexp.MustCompile(`image\/`).MatchString(obj.Attachment[0].MediaType) { media = ", should also escape &, ", and ' nContent := strings.ReplaceAll(content, `<`, "<") nContent, err := ParseLinkComments(board, op, nContent, thread) if err != nil { return "", err } nContent = ParseCommentQuotes(nContent) nContent = strings.ReplaceAll(nContent, `/\<`, ">") return template.HTML(nContent), nil } func ParseLinkComments(board activitypub.Actor, op string, content string, thread activitypub.ObjectBase) (string, error) { 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 = ParseLinkTitle(board.Outbox, op, thread.Content) } else { for _, e := range thread.Replies.OrderedItems { if e.Id == parsedLink { quoteTitle = ParseLinkTitle(board.Outbox, op, e.Content) break } } if quoteTitle == "" { obj, err := activitypub.GetObjectFromDBFromID(parsedLink) if err != nil { return "", err } if len(obj.OrderedItems) > 0 { quoteTitle = ParseLinkTitle(board.Outbox, op, obj.OrderedItems[0].Content) } else { quoteTitle = ParseLinkTitle(board.Outbox, op, parsedLink) } } } if replyID, isReply, err := db.IsReplyToOP(op, parsedLink); err == nil || !isReply { id := util.ShortURL(board.Outbox, replyID) content = strings.Replace(content, match[i][0], ">>"+id+""+isOP+"", -1) } else { //this is a cross post parsedOP, err := db.GetReplyOP(parsedLink) if err == nil { link = parsedOP + "#" + util.ShortURL(parsedOP, parsedLink) } actor, err := webfinger.FingerActor(parsedLink) if err == nil && actor.Id != "" { content = strings.Replace(content, match[i][0], ">>"+util.ShortURL(board.Outbox, parsedLink)+isOP+" →", -1) } } } return content, nil } 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], ">>"+util.ShortURL(actorName, link)+isOP, 1) } // TODO: this drops more than we need to 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 }