небольшие улучшения парсинга описания/комментариев
This commit is contained in:
parent
99fe9cf964
commit
e07e1a25b2
112
app/util.go
112
app/util.go
@ -14,6 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.macaw.me/skunky/devianter"
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
// парсинг темплейтов
|
||||
@ -95,18 +96,59 @@ func ParseDescription(dscr devianter.Text) string {
|
||||
description[dl-1] == '}' {
|
||||
var descr struct {
|
||||
Blocks []struct {
|
||||
Key, Text, Type string
|
||||
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 {
|
||||
Config struct {
|
||||
Aligment string
|
||||
Width int
|
||||
}
|
||||
Data devianter.Deviation
|
||||
}
|
||||
}
|
||||
}
|
||||
e := json.Unmarshal([]byte(description), &descr)
|
||||
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 {
|
||||
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 {
|
||||
var tag string
|
||||
|
||||
@ -140,7 +182,66 @@ func ParseDescription(dscr devianter.Text) string {
|
||||
}
|
||||
}
|
||||
} 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()
|
||||
@ -234,7 +335,7 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s
|
||||
}
|
||||
for _, data := range devs {
|
||||
if !(data.NSFW && !CFG.Nsfw) {
|
||||
url := s.ParseMedia(data.Media)
|
||||
url := ParseMedia(data.Media)
|
||||
if s.Atom {
|
||||
id := strconv.Itoa(data.ID)
|
||||
list.WriteString(`<entry><author><name>`)
|
||||
@ -307,7 +408,6 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s
|
||||
return list.String()
|
||||
}
|
||||
|
||||
// FIXME: первый комментарий не отображается.
|
||||
func (s skunkyart) ParseComments(c devianter.Comments) string {
|
||||
var cmmts strings.Builder
|
||||
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("]<p>")
|
||||
|
||||
cmmts.WriteString(x.Comment)
|
||||
cmmts.WriteString(ParseDescription(x.TextContent))
|
||||
cmmts.WriteString("<p>👍: ")
|
||||
cmmts.WriteString(strconv.Itoa(x.Likes))
|
||||
cmmts.WriteString(" ⏩: ")
|
||||
@ -369,7 +469,7 @@ func (s skunkyart) ParseComments(c devianter.Comments) string {
|
||||
return cmmts.String()
|
||||
}
|
||||
|
||||
func (s skunkyart) ParseMedia(media devianter.Media) string {
|
||||
func ParseMedia(media devianter.Media) string {
|
||||
url := devianter.UrlFromMedia(media)
|
||||
if len(url) != 0 {
|
||||
url = url[21:]
|
||||
|
@ -127,7 +127,7 @@ func (s skunkyart) GRUser() {
|
||||
case "cover_deviation":
|
||||
group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
|
||||
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":
|
||||
var htm strings.Builder
|
||||
for _, z := range x.ModuleData.GroupAdmins.Results {
|
||||
@ -165,7 +165,7 @@ func (s skunkyart) GRUser() {
|
||||
folders.WriteString(`<a href="`)
|
||||
folders.WriteString(s.ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url))
|
||||
folders.WriteString(`"><img loading="lazy" src="`)
|
||||
folders.WriteString(s.ParseMedia(x.Thumb.Media))
|
||||
folders.WriteString(ParseMedia(x.Thumb.Media))
|
||||
folders.WriteString(`" title="`)
|
||||
folders.WriteString(x.Thumb.Title)
|
||||
folders.WriteString(`"></a><br>`)
|
||||
@ -212,10 +212,14 @@ func (s skunkyart) Deviation(author, postname string) {
|
||||
id := id_search[len(id_search)-1]
|
||||
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.Post.IMG = s.ParseMedia(post.Post.Deviation.Media)
|
||||
post.Post.IMG = ParseMedia(post.Post.Deviation.Media)
|
||||
for _, x := range post.Post.Deviation.Extended.RelatedContent {
|
||||
if len(x.Deviations) != 0 {
|
||||
post.Related = s.DeviationList(x.Deviations)
|
||||
|
@ -60,6 +60,7 @@ form input, button, select {
|
||||
color: rgb(160, 0, 147);
|
||||
}
|
||||
.content {
|
||||
align-items: center;
|
||||
border-radius: 3px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@ -113,3 +114,30 @@ form input, button, select {
|
||||
text-align: center;
|
||||
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
|
||||
|
||||
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