diff options
| -rw-r--r-- | INSTANCES.md | 2 | ||||
| -rw-r--r-- | TODO.md | 2 | ||||
| -rw-r--r-- | app/cache.go | 34 | ||||
| -rw-r--r-- | app/util.go | 59 | ||||
| -rw-r--r-- | app/wrapper.go | 144 | ||||
| -rw-r--r-- | go.mod | 1 | ||||
| -rw-r--r-- | instances.json | 2 | ||||
| -rw-r--r-- | static/html/gruser.htm | 17 | ||||
| -rw-r--r-- | static/html/head.htm | 11 |
9 files changed, 149 insertions, 123 deletions
diff --git a/INSTANCES.md b/INSTANCES.md index 1637971..d032d24 100644 --- a/INSTANCES.md +++ b/INSTANCES.md @@ -2,6 +2,6 @@ |:------:|:-------:|:-:|:-:|:--:|:--------:|:--------------:|:-----:| |[skunky.ebloid.ru](https://skunky.ebloid.ru/art)|[Yes](http://[201:eba5:d1fc:bf7b:cfcb:a811:4b8b:7ea3]/art)|No|No| No | No | No | Russia | |[clovius.club](https://skunky.clovius.club)|No|No|No| Yes | Yes | No | Sweden | -|[bloat.cat](https://skunky.bloat.cat)|No|No|No| Yes | Yes | No | Romania | +|[bloat.cat](https://skunky.bloat.cat)|No|No|No| Yes | Yes | No | Germany | |[frontendfriendly.xyz](https://skunkyart.frontendfriendly.xyz)|No|No|No| Yes | Yes | No | Finland | |[lumaeris.com](https://skunkyart.lumaeris.com)|No|No|No| Yes | Yes | No | US |
\ No newline at end of file @@ -6,7 +6,7 @@ * ~~Исправить баг с навигацией по страницам~~ ✔️ * Сделать нормальное отображение ошибок * ~~Сделать единицы в конфиге более понятными~~ ✔️ -* Добавить просмотр понравившихся артов пользователю +* ~~Добавить просмотр понравившихся артов пользователю~~ ✔️ * Добавить возможность включить темплейты в бинарник [P] * ~~Реализовать миниатюры и оптимизировать CSS под маленькие экраны~~ ✔️ * Написать Makefile и скрипт для автоматического развёртывания инстанса diff --git a/app/cache.go b/app/cache.go index dedba83..6506cfc 100644 --- a/app/cache.go +++ b/app/cache.go @@ -99,34 +99,36 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) { func InitCacheSystem() { c := &CFG.Cache - os.Mkdir(c.Path, 0700) for { - dir, e := os.Open(c.Path) - try(e) - stat, e := dir.Stat() - try(e) - - dirnames, e := dir.Readdirnames(-1) - try(e) - for _, a := range dirnames { - a = c.Path + "/" + a + dir, err := os.ReadDir(c.Path) + if err != nil { + if os.IsNotExist(err) { + os.Mkdir(c.Path, 0700) + continue + } + println(err.Error()) + } + + for _, file := range dir { + fileName := c.Path + "/" + file.Name() + fileInfo, err := file.Info() + try(err) + if c.Lifetime != "" { now := time.Now().UnixMilli() - f, _ := os.Stat(a) - stat := f.Sys().(*syscall.Stat_t) + stat := fileInfo.Sys().(*syscall.Stat_t) time := statTime(stat) if time+lifetimeParsed <= now { - try(os.RemoveAll(a)) + try(os.RemoveAll(fileName)) } } - if c.MaxSize != 0 && stat.Size() > c.MaxSize { - try(os.RemoveAll(a)) + if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize { + try(os.RemoveAll(fileName)) } } - dir.Close() time.Sleep(time.Second * time.Duration(c.UpdateInterval)) } } diff --git a/app/util.go b/app/util.go index a5b978d..8e8ef6e 100644 --- a/app/util.go +++ b/app/util.go @@ -16,6 +16,8 @@ import ( ) /* INTERNAL */ +var wr = io.WriteString + func exit(msg string, code int) { println(msg) os.Exit(code) @@ -50,6 +52,63 @@ func RefreshInstances() { } // some crap for frontend +type skunkyart struct { + Writer http.ResponseWriter + + Args url.Values + Page int + Type rune + Atom bool + + BasePath, Endpoint string + Query, QueryRaw string + + Templates struct { + About struct { + Proxy bool + Nsfw bool + Instances []settings + } + + SomeList string + DDStrips string + Deviation struct { + Post devianter.Post + Related string + StringTime string + Tags string + Comments string + } + + GroupUser struct { + GR devianter.GRuser + Admins string + Group bool + CreationDate string + + About struct { + A devianter.About + + DescriptionFormatted string + Interests, Social string + Comments string + BG string + BGMeta devianter.Deviation + } + + Gallery struct { + Folders string + Pages int + List string + } + } + Search struct { + Content devianter.Search + List string + } + } +} + func (s skunkyart) ExecuteTemplate(file, dir string, data any) { var buf strings.Builder tmp := template.New(file) diff --git a/app/wrapper.go b/app/wrapper.go index 5e8b6c1..e0e5054 100644 --- a/app/wrapper.go +++ b/app/wrapper.go @@ -2,9 +2,6 @@ package app import ( "encoding/json" - "io" - "net/http" - "net/url" "regexp" "strconv" "strings" @@ -14,65 +11,6 @@ import ( "golang.org/x/net/html" ) -var wr = io.WriteString - -type skunkyart struct { - Writer http.ResponseWriter - - Args url.Values - Page int - Type rune - Atom bool - - BasePath, Endpoint string - Query, QueryRaw string - - Templates struct { - About struct { - Proxy bool - Nsfw bool - Instances []settings - } - - SomeList string - DDStrips string - Deviation struct { - Post devianter.Post - Related string - StringTime string - Tags string - Comments string - } - - GroupUser struct { - GR devianter.GRuser - Admins string - Group bool - CreationDate string - - About struct { - A devianter.About - - DescriptionFormatted string - Interests, Social string - Comments string - BG string - BGMeta devianter.Deviation - } - - Gallery struct { - Folders string - Pages int - List string - } - } - Search struct { - Content devianter.Search - List string - } - } -} - func (s skunkyart) GRUser() { if len(s.Query) < 1 { s.ReturnHTTPError(400) @@ -82,7 +20,7 @@ func (s skunkyart) GRUser() { var g devianter.Group g.Name = s.Query var err error - s.Templates.GroupUser.GR, err = g.GetGroup() + s.Templates.GroupUser.GR, err = g.Get() try(err) group := &s.Templates.GroupUser @@ -146,51 +84,65 @@ func (s skunkyart) GRUser() { } } - case 'g': + case 'g', 'f': + var all bool + var content devianter.Group + folderid, _ := strconv.Atoi(s.Args.Get("folder")) + + if a := s.Args.Get("all"); a == "true" { + all = true + } + if s.Page == 0 { s.Page++ } - gallery, err := g.GetGallery(s.Page, folderid) - try(err) + if s.Type == 'f' { + content = g.Favourites(s.Page, all, folderid) + } else { + content, err = g.Gallery(s.Page, folderid) + try(err) + } - if folderid > 0 { - group.Gallery.List = s.DeviationList(gallery.Content.Results, true, DeviationList{ - More: gallery.Content.HasMore, + if folderid > 0 || (s.Type == 'f' && all) { + group.Gallery.List = s.DeviationList(content.Content.Results, true, DeviationList{ + More: content.Content.HasMore, }) } else { - for _, x := range gallery.Content.Gruser.Page.Modules { + for _, x := range content.Content.Gruser.Page.Modules { if l := len(x.ModuleData.Folders.Results); l != 0 { var folders strings.Builder folders.WriteString(`<h1 id="folders"><a href="#folder">#</a> Folders</h1><div class="folders"><br>`) for _, x := range x.ModuleData.Folders.Results { - folders.WriteString(`<div class="block folder-item">`) - - if !(x.Thumb.NSFW && !CFG.Nsfw) { - folders.WriteString(`<a href="`) - folders.WriteString(ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url)) - folders.WriteString(`"><img loading="lazy" src="`) - folders.WriteString(ParseMedia(x.Thumb.Media, x.Thumb.Title)) - folders.WriteString(`" title="`) - folders.WriteString(x.Thumb.Title) - folders.WriteString(`"></a>`) - } else { - folders.WriteString(`<h1>[ <span class="nsfw">NSFW</span> ]</h1>`) + if x.FolderId != -1 && x.Size != 0 { + folders.WriteString(`<div class="block folder-item">`) + + if !(x.Thumb.NSFW && !CFG.Nsfw) { + folders.WriteString(`<a href="`) + folders.WriteString(ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url)) + folders.WriteString(`"><img loading="lazy" src="`) + folders.WriteString(ParseMedia(x.Thumb.Media, x.Thumb.Title)) + folders.WriteString(`" title="`) + folders.WriteString(x.Thumb.Title) + folders.WriteString(`"></a>`) + } else { + folders.WriteString(`<h1>[ <span class="nsfw">NSFW</span> ]</h1>`) + } + folders.WriteString("<br>") + + folders.WriteString(`<a href="group_user?folder=`) + folders.WriteString(strconv.Itoa(x.FolderId)) + folders.WriteString("&q=") + folders.WriteString(s.Query) + folders.WriteString("&type=") + folders.WriteString(string(s.Type)) + folders.WriteString(`">`) + folders.WriteString(x.Name) + folders.WriteString(`</a>`) + + folders.WriteString("</div>") } - folders.WriteString("<br>") - - folders.WriteString(`<a href="group_user?folder=`) - folders.WriteString(strconv.Itoa(x.FolderId)) - folders.WriteString("&q=") - folders.WriteString(s.Query) - folders.WriteString("&type=") - folders.WriteString(string(s.Type)) - folders.WriteString(`">`) - folders.WriteString(x.Name) - folders.WriteString(`</a>`) - - folders.WriteString("</div>") } folders.WriteString(`</div><h1 id="content"><a href="#content">#</a> Content</h1>`) group.Gallery.Folders = folders.String() @@ -296,7 +248,7 @@ func (s skunkyart) Search() { switch s.Type { case 'a', 't': ss.Content, err = devianter.PerformSearch(s.Query, s.Page, s.Type) - case 'g': + case 'g', 'f': ss.Content, err = devianter.PerformSearch(s.Query, s.Page, s.Type, s.Args.Get("usr")) case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп var ( @@ -2,6 +2,7 @@ module skunkyart go 1.22.3 +replace git.macaw.me/skunky/devianter v0.2.5 => /home/skunk/projects/devianter require ( git.macaw.me/skunky/devianter v0.2.5 golang.org/x/net v0.27.0 diff --git a/instances.json b/instances.json index cd95b78..74049be 100644 --- a/instances.json +++ b/instances.json @@ -25,7 +25,7 @@ }, { "title": "bloat.cat", - "country": "Romania", + "country": "Germany", "urls": { "clearnet": "https://skunky.bloat.cat" }, diff --git a/static/html/gruser.htm b/static/html/gruser.htm index c8227ef..6593951 100644 --- a/static/html/gruser.htm +++ b/static/html/gruser.htm @@ -3,14 +3,25 @@ {{template "head" . }} <main> <header> - <h1><a href="{{.BasePath}}">HOME</a> | <a href="{{.BasePath}}dd">DD</a> - | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type={{if eq .Type 'a'}}gallery">Gallery{{else}}about">About{{end}}</a> - | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type=gallery&atom=true">RSS</a></h1> + <h1> + <a href="{{.BasePath}}">HOME</a> + | <a href="{{.BasePath}}dd">DD</a> + {{if ne .Type 'f'}} + | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type={{if eq .Type 'a'}}gallery">Gallery{{else}}about">About{{end}}</a> + | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type=favourites">Favourites</a> + {{else}} + | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type=about">About</a> + | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type=gallery">Gallery</a> + | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type=favourites">Favourites</a> + {{end}} + | <a href="group_user?q={{.Templates.GroupUser.GR.Owner.Username}}&type=gallery&atom=true">RSS</a> + </h1> <form method="get" action="{{.BasePath}}search"> <input type="gallery" name="q" placeholder="Search for ..." autocomplete="off" autocapitalize="none" spellcheck="false"> <input type="hidden" name="usr" value="{{.Templates.GroupUser.GR.Owner.Username}}"> <select name="type"> <option value="gallery">Gallery</option> + <option value="folders">Folders</option> <option value="all">All</option> <option value="tag">Tag</option> <option value="r">Groups</option> diff --git a/static/html/head.htm b/static/html/head.htm index f7f6b91..08ecf45 100644 --- a/static/html/head.htm +++ b/static/html/head.htm @@ -5,12 +5,13 @@ "{{.QueryRaw}}" {{else if eq .Endpoint "post"}} {{.Templates.Deviation.Post.Deviation.Author.Username}} — {{.Templates.Deviation.Post.Deviation.Title}} - {{else if eq .Type 'a'}} - {{if .Templates.GroupUser.GR.Owner.Username}} - {{.Templates.GroupUser.GR.Owner.Username}} - {{else}} - gallery of {{.Templates.GroupUser.GR.Owner.Username}} + {{else if eq .Endpoint "group_user"}} + {{if eq .Type 'g'}} + gallery of + {{else if eq .Type 'f'}} + favourites of {{end}} + {{.Templates.GroupUser.GR.Owner.Username}} {{else}} {{.Endpoint}} {{end}} |
