package app
import (
"encoding/json"
"strconv"
"strings"
"git.macaw.me/skunky/devianter"
"golang.org/x/net/html"
)
func (s skunkyart) ParseComments(c devianter.Comments) string {
var cmmts strings.Builder
replied := make(map[int]string)
cmmts.WriteString("Comments: ")
cmmts.WriteString(strconv.Itoa(c.Total))
cmmts.WriteString("
")
for _, x := range c.Thread {
replied[x.ID] = x.User.Username
cmmts.WriteString(`\n")
}
cmmts.WriteString(s.NavBase(DeviationList{
Pages: 0,
More: c.HasMore,
}))
cmmts.WriteString(" ")
return cmmts.String()
}
func (s skunkyart) DeviationList(devs []devianter.Deviation, allowAtom bool, content ...DeviationList) string {
if s.Atom && s.Page > 1 {
s.ReturnHTTPError(400)
return ""
}
var list, listContent strings.Builder
for i, l := 0, len(devs); i < l; i++ {
data := &devs[i]
if preview, fullview := ParseMedia(data.Media, 320), ParseMedia(data.Media); !(data.NSFW && !CFG.Nsfw) {
if allowAtom && s.Atom {
id := strconv.Itoa(data.ID)
listContent.WriteString(``)
listContent.WriteString(data.Author.Username)
listContent.WriteString(``)
listContent.WriteString(data.Title)
listContent.WriteString(``)
listContent.WriteString(id)
listContent.WriteString(``)
listContent.WriteString(data.PublishedTime.UTC().Format("Mon, 02 Jan 2006 15:04:05 -0700"))
listContent.WriteString(``)
listContent.WriteString(``)
listContent.WriteString(data.Title)
listContent.WriteString(``)
listContent.WriteString(ParseDescription(data.TextContent))
listContent.WriteString(`
`)
} else {
listContent.WriteString(`
")
}
}
}
if allowAtom && s.Atom {
list.WriteString(``)
list.WriteString(``)
if s.Type == 0 {
list.WriteString("Daily Deviations")
} else if s.Type == 'g' && len(devs) != 0 {
list.WriteString(devs[0].Author.Username)
} else {
list.WriteString("SkunkyArt")
}
list.WriteString(``)
list.WriteString(``)
list.WriteString(listContent.String())
list.WriteString("")
wr(s.Writer, list.String())
} else {
list.WriteString(``)
list.WriteString(listContent.String())
list.WriteString("
")
if content != nil {
list.WriteString(s.NavBase(content[0]))
}
}
return list.String()
}
/* DESCRIPTION/COMMENT PARSER */
type text struct {
TXT string
TXT_RAW string
From int
To int
}
func ParseDescription(dscr devianter.Text) string {
var parsedDescription strings.Builder
TagBuilder := func(content string, tags ...string) string {
l := len(tags)
for x := 0; x < l; x++ {
var htm strings.Builder
htm.WriteString("<")
htm.WriteString(tags[x])
htm.WriteString(">")
htm.WriteString(content)
htm.WriteString("")
htm.WriteString(tags[x])
htm.WriteString(">")
content = htm.String()
}
return content
}
DeleteTrackingFromUrl := func(url string) string {
if len(url) > 42 && url[:42] == "https://www.deviantart.com/users/outgoing?" {
url = url[42:]
}
return url
}
if description, dl := dscr.Html.Markup, len(dscr.Html.Markup); dl != 0 &&
description[0] == '{' &&
description[dl-1] == '}' {
var descr struct {
Blocks []struct {
Text, Type string
InlineStyleRanges []struct {
Offset, Length int
Style string
}
EntityRanges []struct {
Offset, Length int
Key int
}
Data struct {
TextAlignment string
}
}
EntityMap map[string]struct {
Type string
Data struct {
Url string
Config struct {
Aligment string
Width int
}
Data devianter.Deviation
}
}
}
e := json.Unmarshal([]byte(description), &descr)
try(e)
entities := make(map[int]devianter.Deviation)
urls := make(map[int]string)
for n, x := range descr.EntityMap {
num, _ := strconv.Atoi(n)
if x.Data.Url != "" {
urls[num] = DeleteTrackingFromUrl(x.Data.Url)
}
entities[num] = x.Data.Data
}
for _, x := range descr.Blocks {
Styles := make([]text, len(x.InlineStyleRanges))
if len(x.InlineStyleRanges) != 0 {
var tags = make(map[int][]string)
for n, rngs := range x.InlineStyleRanges {
Styles := &Styles[n]
switch rngs.Style {
case "BOLD":
rngs.Style = "b"
case "UNDERLINE":
rngs.Style = "u"
case "ITALIC":
rngs.Style = "i"
}
Styles.From = rngs.Offset
Styles.To = rngs.Offset + rngs.Length
FT := Styles.From * Styles.To
tags[FT] = append(tags[FT], rngs.Style)
}
for n := 0; n < len(Styles); n++ {
Styles := &Styles[n]
Styles.TXT_RAW = x.Text[Styles.From:Styles.To]
Styles.TXT = TagBuilder(Styles.TXT_RAW, tags[Styles.From*Styles.To]...)
}
}
switch x.Type {
case "atomic":
if len(x.EntityRanges) != 0 {
d := entities[x.EntityRanges[0].Key]
parsedDescription.WriteString(``)
}
case "unstyled":
if l := len(Styles); l != 0 {
for n, r := range Styles {
var tag string
if x.Type == "header-two" {
tag = "h2"
}
parsedDescription.WriteString(x.Text[:r.From])
if len(urls) != 0 && len(x.EntityRanges) != 0 {
ra := &x.EntityRanges[0]
parsedDescription.WriteString(``)
parsedDescription.WriteString(r.TXT)
parsedDescription.WriteString(``)
} else if l > n+1 {
parsedDescription.WriteString(r.TXT)
}
parsedDescription.WriteString(TagBuilder(tag, x.Text[r.To:]))
}
} else {
parsedDescription.WriteString(x.Text)
}
}
parsedDescription.WriteString("
")
}
} else if dl != 0 {
for tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup)); ; {
switch tt.Next() {
case html.ErrorToken:
return parsedDescription.String()
case html.StartTagToken, html.EndTagToken, html.SelfClosingTagToken:
token := tt.Token()
switch token.Data {
case "a":
for _, a := range token.Attr {
if a.Key == "href" {
url := DeleteTrackingFromUrl(a.Val)
parsedDescription.WriteString(``)
parsedDescription.WriteString(GetValueOfTag(tt))
parsedDescription.WriteString(" ")
}
}
case "img":
var uri, title string
for b, a := range token.Attr {
switch a.Key {
case "src":
if len(a.Val) > 9 && a.Val[8:9] == "e" {
uri = UrlBuilder("media", "emojitar", a.Val[37:len(a.Val)-4], "?type=e")
}
case "title":
title = a.Val
}
if title != "" {
for x := -1; x < b; x++ {
parsedDescription.WriteString(``)
}
}
}
case "br", "li", "ul", "p", "b":
parsedDescription.WriteString(token.String())
case "div":
parsedDescription.WriteString(" ")
}
case html.TextToken:
parsedDescription.Write(tt.Text())
}
}
}
return parsedDescription.String()
}