use a video player for uploaded videos
optimise the parser
This commit is contained in:
parent
b915131ab4
commit
c32498d543
127
common/parser.go
127
common/parser.go
|
@ -28,19 +28,26 @@ var URLOpen = []byte("<a href='")
|
||||||
var URLOpenUser = []byte("<a rel='ugc'href='")
|
var URLOpenUser = []byte("<a rel='ugc'href='")
|
||||||
var URLOpen2 = []byte("'>")
|
var URLOpen2 = []byte("'>")
|
||||||
var bytesSinglequote = []byte("'")
|
var bytesSinglequote = []byte("'")
|
||||||
var bytesGreaterthan = []byte(">")
|
var bytesGreaterThan = []byte(">")
|
||||||
var urlMention = []byte("'class='mention'")
|
var urlMention = []byte("'class='mention'")
|
||||||
var URLClose = []byte("</a>")
|
var URLClose = []byte("</a>")
|
||||||
|
var videoOpen = []byte("<video controls src=\"")
|
||||||
|
var videoOpen2 = []byte("\"><a class='attach'href=\"")
|
||||||
|
var videoClose = []byte("\"download>Attachment</a></video>")
|
||||||
var imageOpen = []byte("<a href=\"")
|
var imageOpen = []byte("<a href=\"")
|
||||||
var imageOpen2 = []byte("\"><img src='")
|
var imageOpen2 = []byte("\"><img src='")
|
||||||
var imageClose = []byte("'class='postImage'></a>")
|
var imageClose = []byte("'class='postImage'></a>")
|
||||||
var attachOpen = []byte("<a download class='attach'href=\"")
|
var attachOpen = []byte("<a class='attach'href=\"")
|
||||||
var attachClose = []byte("\">Attachment</a>")
|
var attachClose = []byte("\"download>Attachment</a>")
|
||||||
var sidParam = []byte("?sid=")
|
var sidParam = []byte("?sid=")
|
||||||
var stypeParam = []byte("&stype=")
|
var stypeParam = []byte("&stype=")
|
||||||
var urlPattern = `(?s)([ {1}])((http|https|ftp|mailto)*)(:{??)\/\/([\.a-zA-Z\/]+)([ {1}])`
|
var urlPattern = `(?s)([ {1}])((http|https|ftp|mailto)*)(:{??)\/\/([\.a-zA-Z\/]+)([ {1}])`
|
||||||
var urlReg *regexp.Regexp
|
var urlReg *regexp.Regexp
|
||||||
|
|
||||||
|
const imageSizeHint = len("<a href=\"") + len("\"><img src='") + len("'class='postImage'></a>")
|
||||||
|
const videoSizeHint = len("<video controls src=\"") + len("\"><a class='attach'href=\"") + len("\"download>Attachment</a></video>") + len("?sid=") + len("&stype=") + 8
|
||||||
|
const mentionSizeHint = len("<a href='") + len("'class='mention'") + len(">@") + len("</a>")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
urlReg = regexp.MustCompile(urlPattern)
|
urlReg = regexp.MustCompile(urlPattern)
|
||||||
}
|
}
|
||||||
|
@ -492,8 +499,14 @@ func ParseMessage(msg string, sectionID int, sectionType string, settings *Parse
|
||||||
LogError(err)
|
LogError(err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
for _, filter := range wordFilters {
|
for _, f := range wordFilters {
|
||||||
msg = strings.Replace(msg, filter.Find, filter.Replace, -1)
|
msg = strings.Replace(msg, f.Find, f.Replace, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(msg) < 2 {
|
||||||
|
msg = strings.Replace(msg, "\n", "<br>", -1)
|
||||||
|
msg = GetHookTable().Sshook("parse_assign", msg)
|
||||||
|
return msg
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for URLs, mentions and hashlinks in the messages...
|
// Search for URLs, mentions and hashlinks in the messages...
|
||||||
|
@ -513,7 +526,9 @@ func ParseMessage(msg string, sectionID int, sectionType string, settings *Parse
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
//fmt.Println("s2")
|
//fmt.Println("s2")
|
||||||
if msg[i] == '#' {
|
ch := msg[i]
|
||||||
|
switch ch {
|
||||||
|
case '#':
|
||||||
//fmt.Println("msg[i+1]:", msg[i+1])
|
//fmt.Println("msg[i+1]:", msg[i+1])
|
||||||
//fmt.Println("string(msg[i+1]):", string(msg[i+1]))
|
//fmt.Println("string(msg[i+1]):", string(msg[i+1]))
|
||||||
hashType := hashLinkTypes[msg[i+1]]
|
hashType := hashLinkTypes[msg[i+1]]
|
||||||
|
@ -540,31 +555,37 @@ func ParseMessage(msg string, sectionID int, sectionType string, settings *Parse
|
||||||
hashLinkMap[hashType](&sb, msg, &i)
|
hashLinkMap[hashType](&sb, msg, &i)
|
||||||
lastItem = i
|
lastItem = i
|
||||||
i--
|
i--
|
||||||
} else if msg[i] == '@' {
|
case '@':
|
||||||
sb.WriteString(msg[lastItem:i])
|
sb.WriteString(msg[lastItem:i])
|
||||||
i++
|
i++
|
||||||
start := i
|
start := i
|
||||||
uid, intLen := CoerceIntString(msg[start:])
|
uid, intLen := CoerceIntString(msg[start:])
|
||||||
i += intLen
|
i += intLen
|
||||||
|
|
||||||
menUser, err := Users.Get(uid)
|
var menUser *User
|
||||||
if err != nil {
|
if uid != 0 && user.ID == uid {
|
||||||
sb.Write(InvalidProfile)
|
menUser = user
|
||||||
lastItem = i
|
} else {
|
||||||
i--
|
menUser = Users.Getn(uid)
|
||||||
continue
|
if menUser == nil {
|
||||||
|
sb.Write(InvalidProfile)
|
||||||
|
lastItem = i
|
||||||
|
i--
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sb.Grow(mentionSizeHint + len(menUser.Link) + len(menUser.Name))
|
||||||
sb.Write(URLOpen)
|
sb.Write(URLOpen)
|
||||||
sb.WriteString(menUser.Link)
|
sb.WriteString(menUser.Link)
|
||||||
sb.Write(urlMention)
|
sb.Write(urlMention)
|
||||||
sb.Write(bytesGreaterthan)
|
sb.Write(bytesGreaterThan)
|
||||||
sb.WriteByte('@')
|
sb.WriteByte('@')
|
||||||
sb.WriteString(menUser.Name)
|
sb.WriteString(menUser.Name)
|
||||||
sb.Write(URLClose)
|
sb.Write(URLClose)
|
||||||
lastItem = i
|
lastItem = i
|
||||||
i--
|
i--
|
||||||
} else if msg[i] == 'h' || msg[i] == 'f' || msg[i] == 'g' || msg[i] == '/' {
|
case 'h', 'f', 'g', '/':
|
||||||
//fmt.Println("s3")
|
//fmt.Println("s3")
|
||||||
if len(msg) > i+5 && msg[i+1] == 't' && msg[i+2] == 't' && msg[i+3] == 'p' {
|
if len(msg) > i+5 && msg[i+1] == 't' && msg[i+2] == 't' && msg[i+3] == 'p' {
|
||||||
if len(msg) > i+6 && msg[i+4] == 's' && msg[i+5] == ':' && msg[i+6] == '/' {
|
if len(msg) > i+6 && msg[i+4] == 's' && msg[i+5] == ':' && msg[i+6] == '/' {
|
||||||
|
@ -574,10 +595,17 @@ func ParseMessage(msg string, sectionID int, sectionType string, settings *Parse
|
||||||
} else {
|
} else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if len(msg) > i+4 && msg[i+1] == 't' && msg[i+2] == 'p' && msg[i+3] == ':' && msg[i+4] == '/' {
|
} else if len(msg) > i+4 {
|
||||||
// Do nothing
|
fch := msg[i+1]
|
||||||
} else if len(msg) > i+4 && msg[i+1] == 'i' && msg[i+2] == 't' && msg[i+3] == ':' && msg[i+4] == '/' {
|
if fch == 't' && msg[i+2] == 'p' && msg[i+3] == ':' && msg[i+4] == '/' {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
|
} else if fch == 'i' && msg[i+2] == 't' && msg[i+3] == ':' && msg[i+4] == '/' {
|
||||||
|
// Do nothing
|
||||||
|
} else if fch == '/' {
|
||||||
|
// Do nothing
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
} else if msg[i+1] == '/' {
|
} else if msg[i+1] == '/' {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} else {
|
} else {
|
||||||
|
@ -626,7 +654,7 @@ func ParseMessage(msg string, sectionID int, sectionType string, settings *Parse
|
||||||
//fmt.Println("p2")
|
//fmt.Println("p2")
|
||||||
|
|
||||||
addImage := func(url string) {
|
addImage := func(url string) {
|
||||||
sb.Grow(len(imageOpen) + len(url) + len(url) + len(imageOpen2) + len(imageClose))
|
sb.Grow(imageSizeHint + len(url) + len(url))
|
||||||
sb.Write(imageOpen)
|
sb.Write(imageOpen)
|
||||||
sb.WriteString(url)
|
sb.WriteString(url)
|
||||||
sb.Write(imageOpen2)
|
sb.Write(imageOpen2)
|
||||||
|
@ -638,13 +666,32 @@ func ParseMessage(msg string, sectionID int, sectionType string, settings *Parse
|
||||||
|
|
||||||
// TODO: Reduce the amount of code duplication
|
// TODO: Reduce the amount of code duplication
|
||||||
// TODO: Avoid allocating a string for media.Type?
|
// TODO: Avoid allocating a string for media.Type?
|
||||||
if media.Type == "attach" {
|
switch media.Type {
|
||||||
|
case AImage:
|
||||||
addImage(media.URL + "?sid=" + strconv.Itoa(sectionID) + "&stype=" + sectionType)
|
addImage(media.URL + "?sid=" + strconv.Itoa(sectionID) + "&stype=" + sectionType)
|
||||||
continue
|
continue
|
||||||
} else if media.Type == "image" {
|
case AVideo:
|
||||||
|
sb.Grow(videoSizeHint + (len(media.URL) + len(sectionType)*2))
|
||||||
|
sb.Write(videoOpen)
|
||||||
|
sb.WriteString(media.URL)
|
||||||
|
sb.Write(sidParam)
|
||||||
|
sb.WriteString(strconv.Itoa(sectionID))
|
||||||
|
sb.Write(stypeParam)
|
||||||
|
sb.WriteString(sectionType)
|
||||||
|
sb.Write(videoOpen2)
|
||||||
|
sb.WriteString(media.URL)
|
||||||
|
sb.Write(sidParam)
|
||||||
|
sb.WriteString(strconv.Itoa(sectionID))
|
||||||
|
sb.Write(stypeParam)
|
||||||
|
sb.WriteString(sectionType)
|
||||||
|
sb.Write(videoClose)
|
||||||
|
i += urlLen
|
||||||
|
lastItem = i
|
||||||
|
continue
|
||||||
|
case EImage:
|
||||||
addImage(media.URL)
|
addImage(media.URL)
|
||||||
continue
|
continue
|
||||||
} else if media.Type == "aother" {
|
case AOther:
|
||||||
sb.Write(attachOpen)
|
sb.Write(attachOpen)
|
||||||
sb.WriteString(media.URL)
|
sb.WriteString(media.URL)
|
||||||
sb.Write(sidParam)
|
sb.Write(sidParam)
|
||||||
|
@ -655,12 +702,15 @@ func ParseMessage(msg string, sectionID int, sectionType string, settings *Parse
|
||||||
i += urlLen
|
i += urlLen
|
||||||
lastItem = i
|
lastItem = i
|
||||||
continue
|
continue
|
||||||
} else if media.Type == "raw" {
|
case ERaw:
|
||||||
sb.WriteString(media.Body)
|
sb.WriteString(media.Body)
|
||||||
i += urlLen
|
i += urlLen
|
||||||
lastItem = i
|
lastItem = i
|
||||||
continue
|
continue
|
||||||
} else if media.Type != "" {
|
case ENone:
|
||||||
|
// Do nothing
|
||||||
|
// TODO: Add support for media plugins
|
||||||
|
default:
|
||||||
sb.Write(unknownMedia)
|
sb.Write(unknownMedia)
|
||||||
i += urlLen
|
i += urlLen
|
||||||
continue
|
continue
|
||||||
|
@ -863,7 +913,8 @@ func PartialURLStringLen2(data string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaEmbed struct {
|
type MediaEmbed struct {
|
||||||
Type string //image
|
//Type string //image
|
||||||
|
Type int
|
||||||
URL string
|
URL string
|
||||||
FURL string
|
FURL string
|
||||||
Body string
|
Body string
|
||||||
|
@ -871,6 +922,17 @@ type MediaEmbed struct {
|
||||||
Trusted bool // samesite urls
|
Trusted bool // samesite urls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ENone = iota
|
||||||
|
ERaw
|
||||||
|
EImage
|
||||||
|
AImage
|
||||||
|
AVideo
|
||||||
|
AOther
|
||||||
|
)
|
||||||
|
|
||||||
|
var LastEmbedID = AOther
|
||||||
|
|
||||||
// TODO: Write a test for this
|
// TODO: Write a test for this
|
||||||
func parseMediaString(data string, settings *ParseSettings) (media MediaEmbed, ok bool) {
|
func parseMediaString(data string, settings *ParseSettings) (media MediaEmbed, ok bool) {
|
||||||
if !validateURLString(data) {
|
if !validateURLString(data) {
|
||||||
|
@ -920,9 +982,11 @@ func parseMediaString(data string, settings *ParseSettings) (media MediaEmbed, o
|
||||||
return media, false
|
return media, false
|
||||||
}
|
}
|
||||||
if ImageFileExts.Contains(ext) {
|
if ImageFileExts.Contains(ext) {
|
||||||
media.Type = "attach"
|
media.Type = AImage
|
||||||
|
} else if WebVideoFileExts.Contains(ext) {
|
||||||
|
media.Type = AVideo
|
||||||
} else {
|
} else {
|
||||||
media.Type = "aother"
|
media.Type = AOther
|
||||||
}
|
}
|
||||||
return media, true
|
return media, true
|
||||||
}
|
}
|
||||||
|
@ -934,7 +998,7 @@ func parseMediaString(data string, settings *ParseSettings) (media MediaEmbed, o
|
||||||
if strings.HasSuffix(host, ".youtube.com") && path == "/watch" {
|
if strings.HasSuffix(host, ".youtube.com") && path == "/watch" {
|
||||||
video, ok := query["v"]
|
video, ok := query["v"]
|
||||||
if ok && len(video) >= 1 && video[0] != "" {
|
if ok && len(video) >= 1 && video[0] != "" {
|
||||||
media.Type = "raw"
|
media.Type = ERaw
|
||||||
// TODO: Filter the URL to make sure no nasties end up in there
|
// TODO: Filter the URL to make sure no nasties end up in there
|
||||||
media.Body = "<iframe class='postIframe'src='https://www.youtube-nocookie.com/embed/" + video[0] + "'frameborder=0 allowfullscreen></iframe>"
|
media.Body = "<iframe class='postIframe'src='https://www.youtube-nocookie.com/embed/" + video[0] + "'frameborder=0 allowfullscreen></iframe>"
|
||||||
return media, true
|
return media, true
|
||||||
|
@ -943,10 +1007,10 @@ func parseMediaString(data string, settings *ParseSettings) (media MediaEmbed, o
|
||||||
|
|
||||||
if lastFrag := pathFrags[len(pathFrags)-1]; lastFrag != "" {
|
if lastFrag := pathFrags[len(pathFrags)-1]; lastFrag != "" {
|
||||||
// TODO: Write a function for getting the file extension of a string
|
// TODO: Write a function for getting the file extension of a string
|
||||||
ext := strings.TrimPrefix(filepath.Ext(lastFrag),".")
|
ext := strings.TrimPrefix(filepath.Ext(lastFrag), ".")
|
||||||
if len(ext) != 0 {
|
if len(ext) != 0 {
|
||||||
if ImageFileExts.Contains(ext) {
|
if ImageFileExts.Contains(ext) {
|
||||||
media.Type = "image"
|
media.Type = EImage
|
||||||
var sport string
|
var sport string
|
||||||
if port != "443" && port != "80" && port != "" {
|
if port != "443" && port != "80" && port != "" {
|
||||||
sport = ":" + port
|
sport = ":" + port
|
||||||
|
@ -954,6 +1018,7 @@ func parseMediaString(data string, settings *ParseSettings) (media MediaEmbed, o
|
||||||
media.URL = scheme + "//" + host + sport + path
|
media.URL = scheme + "//" + host + sport + path
|
||||||
return media, true
|
return media, true
|
||||||
}
|
}
|
||||||
|
// TODO: Support external videos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,11 @@ func TestParser(t *testing.T) {
|
||||||
l.Add("http://"+u, "<a href='"+fs+"'>"+c.Site.URL+"</a>")
|
l.Add("http://"+u, "<a href='"+fs+"'>"+c.Site.URL+"</a>")
|
||||||
l.Add("https://"+u, "<a href='"+fs+"'>"+c.Site.URL+"</a>")
|
l.Add("https://"+u, "<a href='"+fs+"'>"+c.Site.URL+"</a>")
|
||||||
|
|
||||||
|
l.Add("//"+u+"/attachs/sha256hash.webm?sid=1&stype=forums", "<video controls src=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"><a class='attach'href=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"download>Attachment</a></video>")
|
||||||
|
l.Add("//"+u+"/attachs/sha256hash.webm", "<video controls src=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"><a class='attach'href=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"download>Attachment</a></video>")
|
||||||
|
l.Add("//"+u+"/attachs/sha256hash.webm?sid=1", "<video controls src=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"><a class='attach'href=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"download>Attachment</a></video>")
|
||||||
|
l.Add("//"+u+"/attachs/sha256hash.webm?stype=forums", "<video controls src=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"><a class='attach'href=\""+fs+"/attachs/sha256hash.webm?sid=1&stype=forums\"download>Attachment</a></video>")
|
||||||
|
|
||||||
l.Add("//"+u+"/attachs/sha256hash.png?sid=1&stype=forums", "<a href=\""+fs+"/attachs/sha256hash.png?sid=1&stype=forums\"><img src='"+fs+"/attachs/sha256hash.png?sid=1&stype=forums'class='postImage'></a>")
|
l.Add("//"+u+"/attachs/sha256hash.png?sid=1&stype=forums", "<a href=\""+fs+"/attachs/sha256hash.png?sid=1&stype=forums\"><img src='"+fs+"/attachs/sha256hash.png?sid=1&stype=forums'class='postImage'></a>")
|
||||||
l.Add("//"+u+"/attachs/sha256hash?sid=1&stype=forums", "<red>[Invalid URL]</red>")
|
l.Add("//"+u+"/attachs/sha256hash?sid=1&stype=forums", "<red>[Invalid URL]</red>")
|
||||||
l.Add("//"+u+"/attachs/s?sid=1&stype=forums", "<red>[Invalid URL]</red>")
|
l.Add("//"+u+"/attachs/s?sid=1&stype=forums", "<red>[Invalid URL]</red>")
|
||||||
|
@ -242,7 +247,7 @@ func TestParser(t *testing.T) {
|
||||||
l.Add("//"+u+"/attachs/sha256hash.png?sid=1", "<a href=\""+fs+"/attachs/sha256hash.png?sid=1&stype=forums\"><img src='"+fs+"/attachs/sha256hash.png?sid=1&stype=forums'class='postImage'></a>")
|
l.Add("//"+u+"/attachs/sha256hash.png?sid=1", "<a href=\""+fs+"/attachs/sha256hash.png?sid=1&stype=forums\"><img src='"+fs+"/attachs/sha256hash.png?sid=1&stype=forums'class='postImage'></a>")
|
||||||
l.Add("//"+u+"/attachs/sha256hash.png?stype=forums", "<a href=\""+fs+"/attachs/sha256hash.png?sid=1&stype=forums\"><img src='"+fs+"/attachs/sha256hash.png?sid=1&stype=forums'class='postImage'></a>")
|
l.Add("//"+u+"/attachs/sha256hash.png?stype=forums", "<a href=\""+fs+"/attachs/sha256hash.png?sid=1&stype=forums\"><img src='"+fs+"/attachs/sha256hash.png?sid=1&stype=forums'class='postImage'></a>")
|
||||||
|
|
||||||
l.Add("//"+u+"/attachs/sha256hash.txt?sid=1&stype=forums", "<a download class='attach'href=\""+fs+"/attachs/sha256hash.txt?sid=1&stype=forums\">Attachment</a>")
|
l.Add("//"+u+"/attachs/sha256hash.txt?sid=1&stype=forums", "<a class='attach'href=\""+fs+"/attachs/sha256hash.txt?sid=1&stype=forums\"download>Attachment</a>")
|
||||||
|
|
||||||
l.Add("//example.com/image.png", "<a href=\"//example.com/image.png\"><img src='//example.com/image.png'class='postImage'></a>")
|
l.Add("//example.com/image.png", "<a href=\"//example.com/image.png\"><img src='//example.com/image.png'class='postImage'></a>")
|
||||||
l.Add("https://example.com/image.png", "<a href=\"https://example.com/image.png\"><img src='https://example.com/image.png'class='postImage'></a>")
|
l.Add("https://example.com/image.png", "<a href=\"https://example.com/image.png\"><img src='https://example.com/image.png'class='postImage'></a>")
|
||||||
|
|
Loading…
Reference in New Issue