Commit c39399403e
Unsigned
Layout: unified · split
TODO.md +1 −2
| @@ -5,14 +5,13 @@ | |||
| 5 | * **Доделать парсинг описания** | 5 | * **Доделать парсинг описания** |
| 6 | * ~~Реализовать стрипы в ежедневных артах~~ ✔️ | 6 | * ~~Реализовать стрипы в ежедневных артах~~ ✔️ |
| 7 | * ~~Исправить баг с навигацией по страницам~~ ✔️ | 7 | * ~~Исправить баг с навигацией по страницам~~ ✔️ |
| 8 | * Сделать нормальное отображение ошибок | 8 | * ~~Сделать нормальное отображение ошибок~~ ✔️ |
| 9 | * ~~Сделать единицы в конфиге более понятными~~ ✔️ | 9 | * ~~Сделать единицы в конфиге более понятными~~ ✔️ |
| 10 | * Добавить чекер инстанса на работоспособность | 10 | * Добавить чекер инстанса на работоспособность |
| 11 | * ~~Добавить просмотр понравившихся артов пользователю~~ ✔️ | 11 | * ~~Добавить просмотр понравившихся артов пользователю~~ ✔️ |
| 12 | * Добавить возможность включить темплейты в бинарник [P] | 12 | * Добавить возможность включить темплейты в бинарник [P] |
| 13 | * ~~Реализовать миниатюры и оптимизировать CSS под маленькие экраны~~ ✔️ | 13 | * ~~Реализовать миниатюры и оптимизировать CSS под маленькие экраны~~ ✔️ |
| 14 | * Написать Makefile и скрипт для автоматического развёртывания инстанса | 14 | * Написать Makefile и скрипт для автоматического развёртывания инстанса |
| 15 | * **Реализовать отображение контента, отличного от картинок (видео, аудио, etc)** | ||
| 16 | * Исправить баг с эмоджи, когда некоторые кастомные эмоции могут не отображаться | 15 | * Исправить баг с эмоджи, когда некоторые кастомные эмоции могут не отображаться |
| 17 | * ~~Добавить аргумент &filename, который будет выдавать файл с нормально выглядещем именем~~ ✔️ | 16 | * ~~Добавить аргумент &filename, который будет выдавать файл с нормально выглядещем именем~~ ✔️ |
| 18 | * ~~Улучшить систему кеширования: добавить рейтинг для удаления и копирование изображений в ОЗУ~~ ✔️ | 17 | * ~~Улучшить систему кеширования: добавить рейтинг для удаления и копирование изображений в ОЗУ~~ ✔️ |
app/api.go +5 −1
| @@ -58,8 +58,12 @@ func (a API) Random() { | |||
| 58 | a.Error("Sorry, butt NSFW on this are disabled, and the instance failed to find a random art without NSFW", 500) | 58 | a.Error("Sorry, butt NSFW on this are disabled, and the instance failed to find a random art without NSFW", 500) |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | s, err := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a') | 61 | s, err, daErr := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a') |
| 62 | try(err) | 62 | try(err) |
| 63 | if daErr.RAW != nil { | ||
| 64 | continue | ||
| 65 | } | ||
| 66 | |||
| 63 | deviation := &s.Results[rand.Intn(len(s.Results))] | 67 | deviation := &s.Results[rand.Intn(len(s.Results))] |
| 64 | 68 | ||
| 65 | if deviation.NSFW && !CFG.Nsfw { | 69 | if deviation.NSFW && !CFG.Nsfw { |
app/cache.go +1
| @@ -127,6 +127,7 @@ func InitCacheSystem() { | |||
| 127 | try(os.RemoveAll(fileName)) | 127 | try(os.RemoveAll(fileName)) |
| 128 | } | 128 | } |
| 129 | } | 129 | } |
| 130 | |||
| 130 | if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize { | 131 | if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize { |
| 131 | try(os.RemoveAll(fileName)) | 132 | try(os.RemoveAll(fileName)) |
| 132 | } | 133 | } |
app/config.go +1 −1
| @@ -89,7 +89,7 @@ func ExecuteConfig() { | |||
| 89 | 89 | ||
| 90 | lifetimeParsed = duration * int64(num) | 90 | lifetimeParsed = duration * int64(num) |
| 91 | } | 91 | } |
| 92 | CFG.Cache.MaxSize /= 1024 ^ 2 | 92 | CFG.Cache.MaxSize *= 1024 ^ 2 |
| 93 | go InitCacheSystem() | 93 | go InitCacheSystem() |
| 94 | } | 94 | } |
| 95 | devianter.UserAgent = CFG.UserAgent | 95 | devianter.UserAgent = CFG.UserAgent |
app/parsers.go +5 −1
| @@ -9,7 +9,11 @@ import ( | |||
| 9 | "golang.org/x/net/html" | 9 | "golang.org/x/net/html" |
| 10 | ) | 10 | ) |
| 11 | 11 | ||
| 12 | func (s skunkyart) ParseComments(c devianter.Comments) string { | 12 | func (s skunkyart) ParseComments(c devianter.Comments, daError devianter.Error) string { |
| 13 | if daError.RAW != nil { | ||
| 14 | return "Failed to fetch comments :(" | ||
| 15 | } | ||
| 16 | |||
| 13 | var cmmts strings.Builder | 17 | var cmmts strings.Builder |
| 14 | replied := make(map[int]string) | 18 | replied := make(map[int]string) |
| 15 | 19 | ||
app/router.go +4 −4
| @@ -64,13 +64,13 @@ func Router() { | |||
| 64 | 64 | ||
| 65 | var skunky = skunkyart{Version: Release.Version} | 65 | var skunky = skunkyart{Version: Release.Version} |
| 66 | 66 | ||
| 67 | skunky.Args = r.URL.Query() | ||
| 67 | arg := skunky.Args.Get | 68 | arg := skunky.Args.Get |
| 68 | p, _ := strconv.Atoi(arg("p")) | 69 | p, _ := strconv.Atoi(arg("p")) |
| 69 | 70 | ||
| 70 | skunky.Endpoint = path[1] | 71 | skunky.Endpoint = path[1] |
| 71 | skunky.API.main = &skunky | 72 | skunky.API.main = &skunky |
| 72 | skunky.Writer = w | 73 | skunky.Writer = w |
| 73 | skunky.Args = r.URL.Query() | ||
| 74 | skunky.BasePath = CFG.URI | 74 | skunky.BasePath = CFG.URI |
| 75 | skunky.QueryRaw = arg("q") | 75 | skunky.QueryRaw = arg("q") |
| 76 | skunky.Query = u.QueryEscape(skunky.QueryRaw) | 76 | skunky.Query = u.QueryEscape(skunky.QueryRaw) |
| @@ -128,9 +128,9 @@ func Router() { | |||
| 128 | skunky.API.Error("Not Found", 404) | 128 | skunky.API.Error("Not Found", 404) |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | // 404 | 131 | // 404 |
| 132 | default: | 132 | default: |
| 133 | skunky.ReturnHTTPError(404) | 133 | skunky.ReturnHTTPError(404) |
| 134 | } | 134 | } |
| 135 | } | 135 | } |
| 136 | 136 | ||
app/util.go +14 −1
| @@ -139,6 +139,19 @@ func UrlBuilder(strs ...string) string { | |||
| 139 | return str.String() | 139 | return str.String() |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | func (s skunkyart) Error(dAerr devianter.Error) { | ||
| 143 | s.Writer.WriteHeader(502) | ||
| 144 | |||
| 145 | var msg strings.Builder | ||
| 146 | msg.WriteString(`<html><link rel="stylesheet" href="`) | ||
| 147 | msg.WriteString(UrlBuilder("stylesheet")) | ||
| 148 | msg.WriteString(`" /><h3>DeviantArt error — '`) | ||
| 149 | msg.WriteString(dAerr.Error) | ||
| 150 | msg.WriteString("'</h3></html>") | ||
| 151 | |||
| 152 | wr(s.Writer, msg.String()) | ||
| 153 | } | ||
| 154 | |||
| 142 | func (s skunkyart) ReturnHTTPError(status int) { | 155 | func (s skunkyart) ReturnHTTPError(status int) { |
| 143 | s.Writer.WriteHeader(status) | 156 | s.Writer.WriteHeader(status) |
| 144 | 157 | ||
| @@ -203,7 +216,7 @@ func ParseMedia(media devianter.Media, thumb ...int) string { | |||
| 203 | } | 216 | } |
| 204 | return UrlBuilder("media", "file", mediaUrl[:dot], mediaUrl[dot+11:], "&filename=", filename) | 217 | return UrlBuilder("media", "file", mediaUrl[:dot], mediaUrl[dot+11:], "&filename=", filename) |
| 205 | } | 218 | } |
| 206 | return mediaUrl | 219 | return "" |
| 207 | } | 220 | } |
| 208 | 221 | ||
| 209 | func ConvertDeviantArtUrlToSkunkyArt(url string) (output string) { | 222 | func ConvertDeviantArtUrlToSkunkyArt(url string) (output string) { |
app/wrapper.go +39 −20
| @@ -18,10 +18,15 @@ func (s skunkyart) GRUser() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | var g devianter.Group | 20 | var g devianter.Group |
| 21 | var daError devianter.Error | ||
| 21 | g.Name = s.Query | 22 | g.Name = s.Query |
| 22 | var err error | 23 | var err error |
| 23 | s.Templates.GroupUser.GR, err = g.Get() | 24 | s.Templates.GroupUser.GR, err, daError = g.Get() |
| 24 | try(err) | 25 | try(err) |
| 26 | if daError.RAW != nil { | ||
| 27 | s.Error(daError) | ||
| 28 | return | ||
| 29 | } | ||
| 25 | 30 | ||
| 26 | group := &s.Templates.GroupUser | 31 | group := &s.Templates.GroupUser |
| 27 | 32 | ||
| @@ -63,12 +68,7 @@ func (s skunkyart) GRUser() { | |||
| 63 | group.About.Interests += interest.String() | 68 | group.About.Interests += interest.String() |
| 64 | } | 69 | } |
| 65 | } | 70 | } |
| 66 | group.About.Comments = s.ParseComments(devianter.GetComments( | 71 | group.About.Comments = s.ParseComments(devianter.GetComments(strconv.Itoa(group.GR.Gruser.ID),"",s.Page,4)) |
| 67 | strconv.Itoa(group.GR.Gruser.ID), | ||
| 68 | "", | ||
| 69 | s.Page, | ||
| 70 | 4, | ||
| 71 | )) | ||
| 72 | 72 | ||
| 73 | case "cover_deviation": | 73 | case "cover_deviation": |
| 74 | group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation | 74 | group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation |
| @@ -98,12 +98,17 @@ func (s skunkyart) GRUser() { | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | if s.Type == 'f' { | 100 | if s.Type == 'f' { |
| 101 | content = g.Favourites(s.Page, all, folderid) | 101 | content, daError = g.Favourites(s.Page, all, folderid) |
| 102 | } else { | 102 | } else { |
| 103 | content, err = g.Gallery(s.Page, folderid) | 103 | content, err, daError = g.Gallery(s.Page, folderid) |
| 104 | try(err) | 104 | try(err) |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | if daError.RAW != nil { | ||
| 108 | s.Error(daError) | ||
| 109 | return | ||
| 110 | } | ||
| 111 | |||
| 107 | if folderid > 0 || (s.Type == 'f' && all) { | 112 | if folderid > 0 || (s.Type == 'f' && all) { |
| 108 | group.Gallery.List = s.DeviationList(content.Content.Results, true, DeviationList{ | 113 | group.Gallery.List = s.DeviationList(content.Content.Results, true, DeviationList{ |
| 109 | More: content.Content.HasMore, | 114 | More: content.Content.HasMore, |
| @@ -172,19 +177,26 @@ func (s skunkyart) Deviation(author, postname string) { | |||
| 172 | return | 177 | return |
| 173 | } | 178 | } |
| 174 | 179 | ||
| 180 | var err devianter.Error | ||
| 175 | post := &s.Templates.Deviation | 181 | post := &s.Templates.Deviation |
| 176 | 182 | ||
| 177 | id := id_search[len(id_search)-1] | 183 | id := id_search[len(id_search)-1] |
| 178 | post.Post = devianter.GetDeviation(id, author) | 184 | post.Post, err = devianter.GetDeviation(id, author) |
| 185 | if err.RAW != nil { | ||
| 186 | s.Error(err) | ||
| 187 | return | ||
| 188 | } | ||
| 189 | |||
| 190 | if post.Post.Comments.Total <= 50 { | ||
| 191 | post.Post.Comments.Cursor = "" | ||
| 192 | } | ||
| 179 | 193 | ||
| 180 | if post.Post.Deviation.TextContent.Excerpt != "" { | 194 | if post.Post.Deviation.TextContent.Excerpt != "" { |
| 181 | post.Post.Description = ParseDescription(post.Post.Deviation.TextContent) | 195 | post.Post.Description = ParseDescription(post.Post.Deviation.TextContent) |
| 182 | } else { | 196 | } else { |
| 183 | post.Post.Description = ParseDescription(post.Post.Deviation.Extended.DescriptionText) | 197 | post.Post.Description = ParseDescription(post.Post.Deviation.Extended.DescriptionText) |
| 184 | } | 198 | } |
| 185 | // время публикации | 199 | |
| 186 | post.StringTime = post.Post.Deviation.PublishedTime.UTC().String() | ||
| 187 | post.Post.IMG = ParseMedia(post.Post.Deviation.Media) | ||
| 188 | for _, x := range post.Post.Deviation.Extended.RelatedContent { | 200 | for _, x := range post.Post.Deviation.Extended.RelatedContent { |
| 189 | if len(x.Deviations) != 0 { | 201 | if len(x.Deviations) != 0 { |
| 190 | post.Related += s.DeviationList(x.Deviations, false) | 202 | post.Related += s.DeviationList(x.Deviations, false) |
| @@ -203,17 +215,19 @@ func (s skunkyart) Deviation(author, postname string) { | |||
| 203 | post.Tags += tag.String() | 215 | post.Tags += tag.String() |
| 204 | } | 216 | } |
| 205 | 217 | ||
| 206 | if post.Post.Comments.Total <= 50 { | ||
| 207 | post.Post.Comments.Cursor = "" | ||
| 208 | } | ||
| 209 | |||
| 210 | post.Comments = s.ParseComments(devianter.GetComments(id, post.Post.Comments.Cursor, s.Page, 1)) | 218 | post.Comments = s.ParseComments(devianter.GetComments(id, post.Post.Comments.Cursor, s.Page, 1)) |
| 219 | post.StringTime = post.Post.Deviation.PublishedTime.UTC().String() | ||
| 220 | post.Post.IMG = ParseMedia(post.Post.Deviation.Media) | ||
| 211 | 221 | ||
| 212 | s.ExecuteTemplate("deviantion.htm", "html", &s) | 222 | s.ExecuteTemplate("deviantion.htm", "html", &s) |
| 213 | } | 223 | } |
| 214 | 224 | ||
| 215 | func (s skunkyart) DD() { | 225 | func (s skunkyart) DD() { |
| 216 | dd := devianter.GetDailyDeviations(s.Page) | 226 | dd, err := devianter.GetDailyDeviations(s.Page) |
| 227 | if err.RAW != nil { | ||
| 228 | s.Error(err) | ||
| 229 | return | ||
| 230 | } | ||
| 217 | var strips strings.Builder | 231 | var strips strings.Builder |
| 218 | for _, x := range dd.Strips { | 232 | for _, x := range dd.Strips { |
| 219 | strips.WriteString(`<h3 class="`) | 233 | strips.WriteString(`<h3 class="`) |
| @@ -243,12 +257,13 @@ func (s skunkyart) Search() { | |||
| 243 | } | 257 | } |
| 244 | 258 | ||
| 245 | var err error | 259 | var err error |
| 260 | var daError devianter.Error | ||
| 246 | ss := &s.Templates.Search | 261 | ss := &s.Templates.Search |
| 247 | switch s.Type { | 262 | switch s.Type { |
| 248 | case 'a', 't': | 263 | case 'a', 't': |
| 249 | ss.Content, err = devianter.PerformSearch(s.Query, s.Page, s.Type) | 264 | ss.Content, err, daError = devianter.PerformSearch(s.Query, s.Page, s.Type) |
| 250 | case 'g', 'f': | 265 | case 'g', 'f': |
| 251 | ss.Content, err = devianter.PerformSearch(s.Query, s.Page, s.Type, s.Args.Get("usr")) | 266 | ss.Content, err, daError = devianter.PerformSearch(s.Query, s.Page, s.Type, s.Args.Get("usr")) |
| 252 | case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп | 267 | case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп |
| 253 | var ( | 268 | var ( |
| 254 | usernames = make(map[int]string) | 269 | usernames = make(map[int]string) |
| @@ -297,6 +312,10 @@ func (s skunkyart) Search() { | |||
| 297 | return | 312 | return |
| 298 | } | 313 | } |
| 299 | try(err) | 314 | try(err) |
| 315 | if daError.RAW != nil { | ||
| 316 | s.Error(daError) | ||
| 317 | return | ||
| 318 | } | ||
| 300 | 319 | ||
| 301 | if s.Type != 'r' { | 320 | if s.Type != 'r' { |
| 302 | ss.List = s.DeviationList(ss.Content.Results, false, DeviationList{ | 321 | ss.List = s.DeviationList(ss.Content.Results, false, DeviationList{ |
config.example.json +1 −1
| @@ -5,7 +5,7 @@ | |||
| 5 | "enabled": true, | 5 | "enabled": true, |
| 6 | "path": "cache", | 6 | "path": "cache", |
| 7 | "lifetime": null, | 7 | "lifetime": null, |
| 8 | "max-size": 1024, | 8 | "max-size": 200, |
| 9 | "update-interval": 5 | 9 | "update-interval": 5 |
| 10 | }, | 10 | }, |
| 11 | "static-path": "static", | 11 | "static-path": "static", |
go.mod +1 −2
| @@ -2,8 +2,7 @@ module skunkyart | |||
| 2 | 2 | ||
| 3 | go 1.18 | 3 | go 1.18 |
| 4 | 4 | ||
| 5 | replace git.macaw.me/skunky/devianter v0.2.5 => /home/skunk/projects/devianter | ||
| 6 | require ( | 5 | require ( |
| 7 | git.macaw.me/skunky/devianter v0.2.5 | 6 | git.macaw.me/skunky/devianter v0.2.6-0.20240904171839-b3c99749f133 |
| 8 | golang.org/x/net v0.27.0 | 7 | golang.org/x/net v0.27.0 |
| 9 | ) | 8 | ) |
go.sum +2 −2
| @@ -1,4 +1,4 @@ | |||
| 1 | git.macaw.me/skunky/devianter v0.2.5 h1:aAc6CG/ghvG130Ob7gGUdK4IV3MSeCD5t3QIJjto1M0= | 1 | git.macaw.me/skunky/devianter v0.2.6-0.20240904171839-b3c99749f133 h1:ziutYUyDmdbsptR8Lj4lNmZUxfgwGsNbHM1mO9ATph8= |
| 2 | git.macaw.me/skunky/devianter v0.2.5/go.mod h1:ZLn527xBlnpXrUB1B8z/MhyeiWVK4nPWjyfnhWOE8Is= | 2 | git.macaw.me/skunky/devianter v0.2.6-0.20240904171839-b3c99749f133/go.mod h1:ZLn527xBlnpXrUB1B8z/MhyeiWVK4nPWjyfnhWOE8Is= |
| 3 | golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= | 3 | golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= |
| 4 | golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= | 4 | golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= |