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