небольшие улучшения парсинга описания/комментариев
This commit is contained in:
parent
99fe9cf964
commit
e07e1a25b2
112
app/util.go
112
app/util.go
@ -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:]
|
||||||
|
@ -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)
|
||||||
|
|
||||||
post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
|
if post.Post.Deviation.TextContent.Excerpt != "" {
|
||||||
|
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)
|
||||||
|
@ -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
5
go.mod
@ -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
2
go.sum
@ -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
14
instances.json
Normal 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
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user