user favourites
This commit is contained in:
parent
513543cc7a
commit
2f8c35ba32
@ -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 |
|
|[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 |
|
|[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 |
|
|[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 |
|
|[lumaeris.com](https://skunkyart.lumaeris.com)|No|No|No| Yes | Yes | No | US |
|
2
TODO.md
2
TODO.md
@ -6,7 +6,7 @@
|
|||||||
* ~~Исправить баг с навигацией по страницам~~ ✔️
|
* ~~Исправить баг с навигацией по страницам~~ ✔️
|
||||||
* Сделать нормальное отображение ошибок
|
* Сделать нормальное отображение ошибок
|
||||||
* ~~Сделать единицы в конфиге более понятными~~ ✔️
|
* ~~Сделать единицы в конфиге более понятными~~ ✔️
|
||||||
* Добавить просмотр понравившихся артов пользователю
|
* ~~Добавить просмотр понравившихся артов пользователю~~ ✔️
|
||||||
* Добавить возможность включить темплейты в бинарник [P]
|
* Добавить возможность включить темплейты в бинарник [P]
|
||||||
* ~~Реализовать миниатюры и оптимизировать CSS под маленькие экраны~~ ✔️
|
* ~~Реализовать миниатюры и оптимизировать CSS под маленькие экраны~~ ✔️
|
||||||
* Написать Makefile и скрипт для автоматического развёртывания инстанса
|
* Написать Makefile и скрипт для автоматического развёртывания инстанса
|
||||||
|
32
app/cache.go
32
app/cache.go
@ -99,34 +99,36 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) {
|
|||||||
|
|
||||||
func InitCacheSystem() {
|
func InitCacheSystem() {
|
||||||
c := &CFG.Cache
|
c := &CFG.Cache
|
||||||
os.Mkdir(c.Path, 0700)
|
|
||||||
for {
|
for {
|
||||||
dir, e := os.Open(c.Path)
|
dir, err := os.ReadDir(c.Path)
|
||||||
try(e)
|
if err != nil {
|
||||||
stat, e := dir.Stat()
|
if os.IsNotExist(err) {
|
||||||
try(e)
|
os.Mkdir(c.Path, 0700)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range dir {
|
||||||
|
fileName := c.Path + "/" + file.Name()
|
||||||
|
fileInfo, err := file.Info()
|
||||||
|
try(err)
|
||||||
|
|
||||||
dirnames, e := dir.Readdirnames(-1)
|
|
||||||
try(e)
|
|
||||||
for _, a := range dirnames {
|
|
||||||
a = c.Path + "/" + a
|
|
||||||
if c.Lifetime != "" {
|
if c.Lifetime != "" {
|
||||||
now := time.Now().UnixMilli()
|
now := time.Now().UnixMilli()
|
||||||
|
|
||||||
f, _ := os.Stat(a)
|
stat := fileInfo.Sys().(*syscall.Stat_t)
|
||||||
stat := f.Sys().(*syscall.Stat_t)
|
|
||||||
time := statTime(stat)
|
time := statTime(stat)
|
||||||
|
|
||||||
if time+lifetimeParsed <= now {
|
if time+lifetimeParsed <= now {
|
||||||
try(os.RemoveAll(a))
|
try(os.RemoveAll(fileName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.MaxSize != 0 && stat.Size() > c.MaxSize {
|
if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize {
|
||||||
try(os.RemoveAll(a))
|
try(os.RemoveAll(fileName))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dir.Close()
|
|
||||||
time.Sleep(time.Second * time.Duration(c.UpdateInterval))
|
time.Sleep(time.Second * time.Duration(c.UpdateInterval))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
59
app/util.go
59
app/util.go
@ -16,6 +16,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* INTERNAL */
|
/* INTERNAL */
|
||||||
|
var wr = io.WriteString
|
||||||
|
|
||||||
func exit(msg string, code int) {
|
func exit(msg string, code int) {
|
||||||
println(msg)
|
println(msg)
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
@ -50,6 +52,63 @@ func RefreshInstances() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// some crap for frontend
|
// 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) {
|
func (s skunkyart) ExecuteTemplate(file, dir string, data any) {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
tmp := template.New(file)
|
tmp := template.New(file)
|
||||||
|
@ -2,9 +2,6 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -14,65 +11,6 @@ import (
|
|||||||
"golang.org/x/net/html"
|
"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() {
|
func (s skunkyart) GRUser() {
|
||||||
if len(s.Query) < 1 {
|
if len(s.Query) < 1 {
|
||||||
s.ReturnHTTPError(400)
|
s.ReturnHTTPError(400)
|
||||||
@ -82,7 +20,7 @@ func (s skunkyart) GRUser() {
|
|||||||
var g devianter.Group
|
var g devianter.Group
|
||||||
g.Name = s.Query
|
g.Name = s.Query
|
||||||
var err error
|
var err error
|
||||||
s.Templates.GroupUser.GR, err = g.GetGroup()
|
s.Templates.GroupUser.GR, err = g.Get()
|
||||||
try(err)
|
try(err)
|
||||||
|
|
||||||
group := &s.Templates.GroupUser
|
group := &s.Templates.GroupUser
|
||||||
@ -146,25 +84,38 @@ func (s skunkyart) GRUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
case 'g':
|
case 'g', 'f':
|
||||||
|
var all bool
|
||||||
|
var content devianter.Group
|
||||||
|
|
||||||
folderid, _ := strconv.Atoi(s.Args.Get("folder"))
|
folderid, _ := strconv.Atoi(s.Args.Get("folder"))
|
||||||
|
|
||||||
|
if a := s.Args.Get("all"); a == "true" {
|
||||||
|
all = true
|
||||||
|
}
|
||||||
|
|
||||||
if s.Page == 0 {
|
if s.Page == 0 {
|
||||||
s.Page++
|
s.Page++
|
||||||
}
|
}
|
||||||
|
|
||||||
gallery, err := g.GetGallery(s.Page, folderid)
|
if s.Type == 'f' {
|
||||||
|
content = g.Favourites(s.Page, all, folderid)
|
||||||
|
} else {
|
||||||
|
content, err = g.Gallery(s.Page, folderid)
|
||||||
try(err)
|
try(err)
|
||||||
|
}
|
||||||
|
|
||||||
if folderid > 0 {
|
if folderid > 0 || (s.Type == 'f' && all) {
|
||||||
group.Gallery.List = s.DeviationList(gallery.Content.Results, true, DeviationList{
|
group.Gallery.List = s.DeviationList(content.Content.Results, true, DeviationList{
|
||||||
More: gallery.Content.HasMore,
|
More: content.Content.HasMore,
|
||||||
})
|
})
|
||||||
} else {
|
} 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 {
|
if l := len(x.ModuleData.Folders.Results); l != 0 {
|
||||||
var folders strings.Builder
|
var folders strings.Builder
|
||||||
folders.WriteString(`<h1 id="folders"><a href="#folder">#</a> Folders</h1><div class="folders"><br>`)
|
folders.WriteString(`<h1 id="folders"><a href="#folder">#</a> Folders</h1><div class="folders"><br>`)
|
||||||
for _, x := range x.ModuleData.Folders.Results {
|
for _, x := range x.ModuleData.Folders.Results {
|
||||||
|
if x.FolderId != -1 && x.Size != 0 {
|
||||||
folders.WriteString(`<div class="block folder-item">`)
|
folders.WriteString(`<div class="block folder-item">`)
|
||||||
|
|
||||||
if !(x.Thumb.NSFW && !CFG.Nsfw) {
|
if !(x.Thumb.NSFW && !CFG.Nsfw) {
|
||||||
@ -192,6 +143,7 @@ func (s skunkyart) GRUser() {
|
|||||||
|
|
||||||
folders.WriteString("</div>")
|
folders.WriteString("</div>")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
folders.WriteString(`</div><h1 id="content"><a href="#content">#</a> Content</h1>`)
|
folders.WriteString(`</div><h1 id="content"><a href="#content">#</a> Content</h1>`)
|
||||||
group.Gallery.Folders = folders.String()
|
group.Gallery.Folders = folders.String()
|
||||||
}
|
}
|
||||||
@ -296,7 +248,7 @@ func (s skunkyart) Search() {
|
|||||||
switch s.Type {
|
switch s.Type {
|
||||||
case 'a', 't':
|
case 'a', 't':
|
||||||
ss.Content, err = devianter.PerformSearch(s.Query, s.Page, s.Type)
|
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"))
|
ss.Content, err = devianter.PerformSearch(s.Query, s.Page, s.Type, s.Args.Get("usr"))
|
||||||
case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп
|
case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп
|
||||||
var (
|
var (
|
||||||
|
1
go.mod
1
go.mod
@ -2,6 +2,7 @@ module skunkyart
|
|||||||
|
|
||||||
go 1.22.3
|
go 1.22.3
|
||||||
|
|
||||||
|
replace git.macaw.me/skunky/devianter v0.2.5 => /home/skunk/projects/devianter
|
||||||
require (
|
require (
|
||||||
git.macaw.me/skunky/devianter v0.2.5
|
git.macaw.me/skunky/devianter v0.2.5
|
||||||
golang.org/x/net v0.27.0
|
golang.org/x/net v0.27.0
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "bloat.cat",
|
"title": "bloat.cat",
|
||||||
"country": "Romania",
|
"country": "Germany",
|
||||||
"urls": {
|
"urls": {
|
||||||
"clearnet": "https://skunky.bloat.cat"
|
"clearnet": "https://skunky.bloat.cat"
|
||||||
},
|
},
|
||||||
|
@ -3,14 +3,25 @@
|
|||||||
{{template "head" . }}
|
{{template "head" . }}
|
||||||
<main>
|
<main>
|
||||||
<header>
|
<header>
|
||||||
<h1><a href="{{.BasePath}}">HOME</a> | <a href="{{.BasePath}}dd">DD</a>
|
<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={{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>
|
| <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">
|
<form method="get" action="{{.BasePath}}search">
|
||||||
<input type="gallery" name="q" placeholder="Search for ..." autocomplete="off" autocapitalize="none" spellcheck="false">
|
<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}}">
|
<input type="hidden" name="usr" value="{{.Templates.GroupUser.GR.Owner.Username}}">
|
||||||
<select name="type">
|
<select name="type">
|
||||||
<option value="gallery">Gallery</option>
|
<option value="gallery">Gallery</option>
|
||||||
|
<option value="folders">Folders</option>
|
||||||
<option value="all">All</option>
|
<option value="all">All</option>
|
||||||
<option value="tag">Tag</option>
|
<option value="tag">Tag</option>
|
||||||
<option value="r">Groups</option>
|
<option value="r">Groups</option>
|
||||||
|
@ -5,12 +5,13 @@
|
|||||||
"{{.QueryRaw}}"
|
"{{.QueryRaw}}"
|
||||||
{{else if eq .Endpoint "post"}}
|
{{else if eq .Endpoint "post"}}
|
||||||
{{.Templates.Deviation.Post.Deviation.Author.Username}} — {{.Templates.Deviation.Post.Deviation.Title}}
|
{{.Templates.Deviation.Post.Deviation.Author.Username}} — {{.Templates.Deviation.Post.Deviation.Title}}
|
||||||
{{else if eq .Type 'a'}}
|
{{else if eq .Endpoint "group_user"}}
|
||||||
{{if .Templates.GroupUser.GR.Owner.Username}}
|
{{if eq .Type 'g'}}
|
||||||
{{.Templates.GroupUser.GR.Owner.Username}}
|
gallery of
|
||||||
{{else}}
|
{{else if eq .Type 'f'}}
|
||||||
gallery of {{.Templates.GroupUser.GR.Owner.Username}}
|
favourites of
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{.Templates.GroupUser.GR.Owner.Username}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{.Endpoint}}
|
{{.Endpoint}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
Loading…
Reference in New Issue
Block a user