| @@ -14,6 +14,7 @@ import ( |
| 14 | 14 | "time" |
| 15 | 15 | |
| 16 | 16 | "git.macaw.me/skunky/devianter" |
| 17 | "golang.org/x/net/html" |
| 17 | 18 | ) |
| 18 | 19 | |
| 19 | 20 | // парсинг темплейтов |
| @@ -95,18 +96,59 @@ func ParseDescription(dscr devianter.Text) string { |
| 95 | 96 | description[dl-1] == '}' { |
| 96 | 97 | var descr struct { |
| 97 | 98 | Blocks []struct { |
| 98 | | Key, Text, Type string |
| 99 | Text, Type string |
| 99 | 100 | InlineStyleRanges []struct { |
| 100 | 101 | Offset, Length int |
| 101 | 102 | Style string |
| 102 | 103 | } |
| 104 | EntityRanges []struct { |
| 105 | Offset, Length int |
| 106 | Key int |
| 107 | } |
| 108 | Data struct { |
| 109 | TextAlignment string |
| 110 | } |
| 111 | } |
| 112 | EntityMap map[string]struct { |
| 113 | Type string |
| 114 | Data struct { |
| 115 | Config struct { |
| 116 | Aligment string |
| 117 | Width int |
| 118 | } |
| 119 | Data devianter.Deviation |
| 120 | } |
| 103 | 121 | } |
| 104 | 122 | } |
| 105 | 123 | e := json.Unmarshal([]byte(description), &descr) |
| 106 | 124 | err(e) |
| 107 | 125 | |
| 126 | entities := make(map[int]devianter.Deviation) |
| 127 | for n, x := range descr.EntityMap { |
| 128 | num, _ := strconv.Atoi(n) |
| 129 | entities[num] = x.Data.Data |
| 130 | } |
| 131 | |
| 108 | 132 | for _, x := range descr.Blocks { |
| 109 | 133 | ranges := make(map[int]text) |
| 134 | |
| 135 | if len(x.InlineStyleRanges) == 0 { |
| 136 | switch x.Type { |
| 137 | case "atomic": |
| 138 | d := entities[x.EntityRanges[0].Key] |
| 139 | parseddescription.WriteString(`<img width="50%" src="`) |
| 140 | parseddescription.WriteString(ParseMedia(d.Media)) |
| 141 | parseddescription.WriteString(`" title="`) |
| 142 | parseddescription.WriteString(d.Author.Username) |
| 143 | parseddescription.WriteString(" - ") |
| 144 | parseddescription.WriteString(d.Title) |
| 145 | parseddescription.WriteString(`">`) |
| 146 | case "unstyled": |
| 147 | parseddescription.WriteString(x.Text) |
| 148 | } |
| 149 | parseddescription.WriteString("<br>") |
| 150 | } |
| 151 | |
| 110 | 152 | for i, rngs := range x.InlineStyleRanges { |
| 111 | 153 | var tag string |
| 112 | 154 | |
| @@ -140,7 +182,66 @@ func ParseDescription(dscr devianter.Text) string { |
| 140 | 182 | } |
| 141 | 183 | } |
| 142 | 184 | } else if dl != 0 { |
| 143 | | parseddescription.WriteString(description) |
| 185 | tagval := func(t *html.Tokenizer) string { |
| 186 | for { |
| 187 | tt := t.Next() |
| 188 | switch tt { |
| 189 | case html.ErrorToken: |
| 190 | return "" |
| 191 | case html.TextToken: |
| 192 | return string(t.Text()) |
| 193 | } |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup)) |
| 198 | for { |
| 199 | t := tt.Next() |
| 200 | switch t { |
| 201 | case html.ErrorToken: |
| 202 | return parseddescription.String() |
| 203 | case html.StartTagToken, html.EndTagToken, html.SelfClosingTagToken: |
| 204 | token := tt.Token() |
| 205 | switch token.Data { |
| 206 | case "a": |
| 207 | for _, a := range token.Attr { |
| 208 | if a.Key == "href" { |
| 209 | url := strings.ReplaceAll(a.Val, "https://www.deviantart.com/users/outgoing?", "") |
| 210 | if strings.Contains(url, "deviantart") { |
| 211 | url = strings.ReplaceAll(url, "https://www.deviantart.com/", "") |
| 212 | url = strings.ReplaceAll(url, url[0:strings.Index(url, "/")+1], "") |
| 213 | } |
| 214 | parseddescription.WriteString("<a target=\"_blank\" href=\"" + url + "\">" + tagval(tt) + "</a> ") |
| 215 | } |
| 216 | } |
| 217 | case "img": |
| 218 | var ( |
| 219 | uri, title string |
| 220 | ) |
| 221 | for b, a := range token.Attr { |
| 222 | switch a.Key { |
| 223 | case "src": |
| 224 | if len(a.Val) > 9 && a.Val[8:9] == "e" { |
| 225 | uri = UrlBuilder("media", "emojitar", a.Val[37:len(a.Val)-4], "?type=e") |
| 226 | } |
| 227 | case "title": |
| 228 | title = a.Val |
| 229 | } |
| 230 | if title != "" { |
| 231 | for x := -1; x < b; x++ { |
| 232 | parseddescription.WriteString("<img src=\"" + uri + "\" title=\"" + title + "\">") |
| 233 | } |
| 234 | } |
| 235 | } |
| 236 | case "br", "li", "ul", "p", "b": |
| 237 | parseddescription.WriteString(token.String()) |
| 238 | case "div": |
| 239 | parseddescription.WriteString("<p> ") |
| 240 | } |
| 241 | case html.TextToken: |
| 242 | parseddescription.Write(tt.Text()) |
| 243 | } |
| 244 | } |
| 144 | 245 | } |
| 145 | 246 | |
| 146 | 247 | return parseddescription.String() |
| @@ -234,7 +335,7 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s |
| 234 | 335 | } |
| 235 | 336 | for _, data := range devs { |
| 236 | 337 | if !(data.NSFW && !CFG.Nsfw) { |
| 237 | | url := s.ParseMedia(data.Media) |
| 338 | url := ParseMedia(data.Media) |
| 238 | 339 | if s.Atom { |
| 239 | 340 | id := strconv.Itoa(data.ID) |
| 240 | 341 | list.WriteString(`<entry><author><name>`) |
| @@ -307,7 +408,6 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) s |
| 307 | 408 | return list.String() |
| 308 | 409 | } |
| 309 | 410 | |
| 310 | | // FIXME: первый комментарий не отображается. |
| 311 | 411 | func (s skunkyart) ParseComments(c devianter.Comments) string { |
| 312 | 412 | var cmmts strings.Builder |
| 313 | 413 | replied := make(map[int]string) |
| @@ -354,7 +454,7 @@ func (s skunkyart) ParseComments(c devianter.Comments) string { |
| 354 | 454 | cmmts.WriteString(x.Posted.UTC().String()) |
| 355 | 455 | cmmts.WriteString("]<p>") |
| 356 | 456 | |
| 357 | | cmmts.WriteString(x.Comment) |
| 457 | cmmts.WriteString(ParseDescription(x.TextContent)) |
| 358 | 458 | cmmts.WriteString("<p>👍: ") |
| 359 | 459 | cmmts.WriteString(strconv.Itoa(x.Likes)) |
| 360 | 460 | cmmts.WriteString(" ⏩: ") |
| @@ -369,7 +469,7 @@ func (s skunkyart) ParseComments(c devianter.Comments) string { |
| 369 | 469 | return cmmts.String() |
| 370 | 470 | } |
| 371 | 471 | |
| 372 | | func (s skunkyart) ParseMedia(media devianter.Media) string { |
| 472 | func ParseMedia(media devianter.Media) string { |
| 373 | 473 | url := devianter.UrlFromMedia(media) |
| 374 | 474 | if len(url) != 0 { |
| 375 | 475 | url = url[21:] |