небольшие улучшения парсинга описания/комментариев

This commit is contained in:
lost+skunk 2024-07-08 19:01:53 +03:00
parent 99fe9cf964
commit e07e1a25b2
6 changed files with 162 additions and 11 deletions

View File

@ -14,6 +14,7 @@ import (
"time" "time"
"git.macaw.me/skunky/devianter" "git.macaw.me/skunky/devianter"
"golang.org/x/net/html"
) )
// парсинг темплейтов // парсинг темплейтов
@ -95,18 +96,59 @@ func ParseDescription(dscr devianter.Text) string {
description[dl-1] == '}' { description[dl-1] == '}' {
var descr struct { var descr struct {
Blocks []struct { Blocks []struct {
Key, Text, Type string Text, Type string
InlineStyleRanges []struct { InlineStyleRanges []struct {
Offset, Length int Offset, Length int
Style string Style string
} }
EntityRanges []struct {
Offset, Length int
Key int
}
Data struct {
TextAlignment string
}
}
EntityMap map[string]struct {
Type string
Data struct {
Config struct {
Aligment string
Width int
}
Data devianter.Deviation
}
} }
} }
e := json.Unmarshal([]byte(description), &descr) e := json.Unmarshal([]byte(description), &descr)
err(e) err(e)
entities := make(map[int]devianter.Deviation)
for n, x := range descr.EntityMap {
num, _ := strconv.Atoi(n)
entities[num] = x.Data.Data
}
for _, x := range descr.Blocks { for _, x := range descr.Blocks {
ranges := make(map[int]text) ranges := make(map[int]text)
if len(x.InlineStyleRanges) == 0 {
switch x.Type {
case "atomic":
d := entities[x.EntityRanges[0].Key]
parseddescription.WriteString(`<img width="50%" src="`)
parseddescription.WriteString(ParseMedia(d.Media))
parseddescription.WriteString(`" title="`)
parseddescription.WriteString(d.Author.Username)
parseddescription.WriteString(" - ")
parseddescription.WriteString(d.Title)
parseddescription.WriteString(`">`)
case "unstyled":
parseddescription.WriteString(x.Text)
}
parseddescription.WriteString("<br>")
}
for i, rngs := range x.InlineStyleRanges { for i, rngs := range x.InlineStyleRanges {
var tag string var tag string
@ -140,7 +182,66 @@ func ParseDescription(dscr devianter.Text) string {
} }
} }
} else if dl != 0 { } else if dl != 0 {
parseddescription.WriteString(description) tagval := func(t *html.Tokenizer) string {
for {
tt := t.Next()
switch tt {
case html.ErrorToken:
return ""
case html.TextToken:
return string(t.Text())
}
}
}
tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup))
for {
t := tt.Next()
switch t {
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 := strings.ReplaceAll(a.Val, "https://www.deviantart.com/users/outgoing?", "")
if strings.Contains(url, "deviantart") {
url = strings.ReplaceAll(url, "https://www.deviantart.com/", "")
url = strings.ReplaceAll(url, url[0:strings.Index(url, "/")+1], "")
}
parseddescription.WriteString("<a target=\"_blank\" href=\"" + url + "\">" + tagval(tt) + "</a> ")
}
}
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("<img src=\"" + uri + "\" title=\"" + title + "\">")
}
}
}
case "br", "li", "ul", "p", "b":
parseddescription.WriteString(token.String())
case "div":
parseddescription.WriteString("<p> ")
}
case html.TextToken:
parseddescription.Write(tt.Text())
}
}
} }
return parseddescription.String() return parseddescription.String()
@ -234,7 +335,7 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s
} }
for _, data := range devs { for _, data := range devs {
if !(data.NSFW && !CFG.Nsfw) { if !(data.NSFW && !CFG.Nsfw) {
url := s.ParseMedia(data.Media) url := ParseMedia(data.Media)
if s.Atom { if s.Atom {
id := strconv.Itoa(data.ID) id := strconv.Itoa(data.ID)
list.WriteString(`<entry><author><name>`) list.WriteString(`<entry><author><name>`)
@ -307,7 +408,6 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s
return list.String() return list.String()
} }
// FIXME: первый комментарий не отображается.
func (s skunkyart) ParseComments(c devianter.Comments) string { func (s skunkyart) ParseComments(c devianter.Comments) string {
var cmmts strings.Builder var cmmts strings.Builder
replied := make(map[int]string) replied := make(map[int]string)
@ -354,7 +454,7 @@ func (s skunkyart) ParseComments(c devianter.Comments) string {
cmmts.WriteString(x.Posted.UTC().String()) cmmts.WriteString(x.Posted.UTC().String())
cmmts.WriteString("]<p>") cmmts.WriteString("]<p>")
cmmts.WriteString(x.Comment) cmmts.WriteString(ParseDescription(x.TextContent))
cmmts.WriteString("<p>👍: ") cmmts.WriteString("<p>👍: ")
cmmts.WriteString(strconv.Itoa(x.Likes)) cmmts.WriteString(strconv.Itoa(x.Likes))
cmmts.WriteString(" ⏩: ") cmmts.WriteString(" ⏩: ")
@ -369,7 +469,7 @@ func (s skunkyart) ParseComments(c devianter.Comments) string {
return cmmts.String() return cmmts.String()
} }
func (s skunkyart) ParseMedia(media devianter.Media) string { func ParseMedia(media devianter.Media) string {
url := devianter.UrlFromMedia(media) url := devianter.UrlFromMedia(media)
if len(url) != 0 { if len(url) != 0 {
url = url[21:] url = url[21:]

View File

@ -127,7 +127,7 @@ func (s skunkyart) GRUser() {
case "cover_deviation": case "cover_deviation":
group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
group.About.BGMeta.Url = s.ConvertDeviantArtUrlToSkunkyArt(group.About.BGMeta.Url) group.About.BGMeta.Url = s.ConvertDeviantArtUrlToSkunkyArt(group.About.BGMeta.Url)
group.About.BG = s.ParseMedia(group.About.BGMeta.Media) group.About.BG = ParseMedia(group.About.BGMeta.Media)
case "group_admins": case "group_admins":
var htm strings.Builder var htm strings.Builder
for _, z := range x.ModuleData.GroupAdmins.Results { for _, z := range x.ModuleData.GroupAdmins.Results {
@ -165,7 +165,7 @@ func (s skunkyart) GRUser() {
folders.WriteString(`<a href="`) folders.WriteString(`<a href="`)
folders.WriteString(s.ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url)) folders.WriteString(s.ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url))
folders.WriteString(`"><img loading="lazy" src="`) folders.WriteString(`"><img loading="lazy" src="`)
folders.WriteString(s.ParseMedia(x.Thumb.Media)) folders.WriteString(ParseMedia(x.Thumb.Media))
folders.WriteString(`" title="`) folders.WriteString(`" title="`)
folders.WriteString(x.Thumb.Title) folders.WriteString(x.Thumb.Title)
folders.WriteString(`"></a><br>`) folders.WriteString(`"></a><br>`)
@ -212,10 +212,14 @@ func (s skunkyart) Deviation(author, postname string) {
id := id_search[len(id_search)-1] id := id_search[len(id_search)-1]
post.Post = devianter.DeviationFunc(id, author) post.Post = devianter.DeviationFunc(id, author)
if post.Post.Deviation.TextContent.Excerpt != "" {
post.Post.Description = ParseDescription(post.Post.Deviation.TextContent) post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
} else {
post.Post.Description = ParseDescription(post.Post.Deviation.Extended.DescriptionText)
}
// время публикации // время публикации
post.StringTime = post.Post.Deviation.PublishedTime.UTC().String() post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
post.Post.IMG = s.ParseMedia(post.Post.Deviation.Media) post.Post.IMG = ParseMedia(post.Post.Deviation.Media)
for _, x := range post.Post.Deviation.Extended.RelatedContent { for _, x := range post.Post.Deviation.Extended.RelatedContent {
if len(x.Deviations) != 0 { if len(x.Deviations) != 0 {
post.Related = s.DeviationList(x.Deviations) post.Related = s.DeviationList(x.Deviations)

View File

@ -60,6 +60,7 @@ form input, button, select {
color: rgb(160, 0, 147); color: rgb(160, 0, 147);
} }
.content { .content {
align-items: center;
border-radius: 3px; border-radius: 3px;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@ -113,3 +114,30 @@ form input, button, select {
text-align: center; text-align: center;
width: 5%; width: 5%;
} }
@media screen and (orientation: portrait) {
header {
scale: 155%;
justify-content: center;
}
.content {
margin: auto;
display: inherit;
scale: 100%;
}
.block {
max-width: 60%;
}
}
@media screen and (max-width: 1462px) {
.block {
max-width: 30%;
}
}
@media screen and (min-width: 788px) and (max-width: 884px) {
.block {
max-width: 35%;
}
}

5
go.mod
View File

@ -4,4 +4,7 @@ go 1.22.3
replace git.macaw.me/skunky/devianter v0.1.0 => /home/skunk/projects/devianter replace git.macaw.me/skunky/devianter v0.1.0 => /home/skunk/projects/devianter
require git.macaw.me/skunky/devianter v0.1.0 require (
git.macaw.me/skunky/devianter v0.1.0
golang.org/x/net v0.27.0
)

2
go.sum
View File

@ -0,0 +1,2 @@
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=

14
instances.json Normal file
View File

@ -0,0 +1,14 @@
{
"instances": [{
"urls": [{
"i2p": "http://skunky.i2p/art",
"tor": "http://skunky0wjkf8j8ajofgh98aOZjhu8f.onion/art",
"ygg": "http://[324:71e:281a:9ed3::fa11]/skunkyart",
"clearnet": "https://skunky.net/art"
}],
"settings": {
"nsfw": true,
"proxy": true
}
}]
}