Commit db53a8bd90

db53a8bd9004098e6a1507e5826a833fd9efa954

parent: 1464584264

Unsigned

lost+skunk <skunky@ebloid.ru> · 2024-09-03 12:36 UTC

Два API-эндпоинта

Layout: unified · split

TODO.md +4 −1
@@ -1,11 +1,13 @@
11# v1.3.x
22* Почистить говнокод
3* Добавить фильтры поиска
34* ~~Сделать порт под FreeBSD~~ ✔️
45* **Доделать парсинг описания**
56* ~~Реализовать стрипы в ежедневных артах~~ ✔️
67* ~~Исправить баг с навигацией по страницам~~ ✔️
78* Сделать нормальное отображение ошибок
89* ~~Сделать единицы в конфиге более понятными~~ ✔️
10* Добавить чекер инстанса на работоспособность
911* ~~Добавить просмотр понравившихся артов пользователю~~ ✔️
1012* Добавить возможность включить темплейты в бинарник [P]
1113* ~~Реализовать миниатюры и оптимизировать CSS под маленькие экраны~~ ✔️
@@ -13,9 +15,10 @@
1315* **Реализовать отображение контента, отличного от картинок (видео, аудио, etc)**
1416* Исправить баг с эмоджи, когда некоторые кастомные эмоции могут не отображаться
1517* ~~Добавить аргумент &filename, который будет выдавать файл с нормально выглядещем именем~~ ✔️
16* ~~Улучшить систему кеширования: добавить рейтинг для удаления и копирование изображений в ОЗУ~~ BUG: почему-то всё переодически встаёт раком
18* ~~Улучшить систему кеширования: добавить рейтинг для удаления и копирование изображений в ОЗУ~~ ✔️
1719# v1.4
1820* Реализовать API
1921* Реализовать темы
2022* Перейти на арены в кеше
2123* Реализовать многоязычный интерфейс
24
app/api.go +50 −11
@@ -1,6 +1,7 @@
11package app
22
33import (
4 "encoding/json"
45 "math/rand"
56 "strings"
67
@@ -8,27 +9,65 @@ import (
89)
910
1011type API struct {
11 skunkyartLink *skunkyart
12 main *skunkyart
13}
14
15type info struct {
16 Version string `json:"version"`
17 Settings settingsParams `json:"settings"`
18}
19
20func (a API) Info() {
21 json, err := json.Marshal(info{
22 Version: a.main.Version,
23 Settings: settingsParams{
24 Nsfw: CFG.Nsfw,
25 Proxy: CFG.Proxy,
26 },
27 })
28 try(err)
29 a.main.Writer.Write(json)
30 return
31}
32
33func (a API) Error(description string, status int) {
34 a.main.Writer.WriteHeader(status)
35 var response strings.Builder
36 response.WriteString(`{"error":"`)
37 response.WriteString(description)
38 response.WriteString(`"}`)
39 wr(a.main.Writer, response.String())
1240}
1341
1442func (a API) sendMedia(d *devianter.Deviation) {
1543 mediaUrl, name := devianter.UrlFromMedia(d.Media)
16
17 var filename strings.Builder
18 filename.WriteString(`filename="`)
19 filename.WriteString(name)
20 filename.WriteString(`"`)
21 a.skunkyartLink.Writer.Header().Add("Content-Disposition", filename.String())
44 a.main.SetFilename(name)
2245
2346 if len(mediaUrl) != 0 {
2447 mediaUrl = mediaUrl[21:]
2548 dot := strings.Index(mediaUrl, ".")
26 a.skunkyartLink.DownloadAndSendMedia(mediaUrl[:dot], mediaUrl[dot+11:])
49 a.main.Writer.Header().Del("Content-Type")
50 a.main.DownloadAndSendMedia(mediaUrl[:dot], mediaUrl[dot+11:])
2751 }
2852}
2953
54// TODO: сделать фильтры
3055func (a API) Random() {
31 s, err := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a')
32 try(err)
33 a.sendMedia(&s.Results[rand.Intn(len(s.Results))])
56 for attempt := 1;; {
57 if attempt > 3 {
58 a.Error("Sorry, butt NSFW on this are disabled, and the instance failed to find a random art without NSFW", 500)
59 }
60
61 s, err := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a')
62 try(err)
63 deviation := &s.Results[rand.Intn(len(s.Results))]
64
65 if deviation.NSFW && !CFG.Nsfw {
66 attempt++
67 continue
68 }
69
70 a.sendMedia(deviation)
71 return
72 }
3473}
app/cli.go +8 −3
@@ -4,19 +4,20 @@ import (
44 "bufio"
55 "bytes"
66 "encoding/json"
7 "html/template"
78 "os"
89 "time"
910)
1011
1112func ExecuteCommandLineArguments() {
12 const helpmsg = `SkunkyArt v1.3.1 [CSS improvements for mobile and the strips on Daily Deviations]
13 var helpmsg = `SkunkyArt v{{.Version}} [{{.Description}}]
1314Usage:
1415 - [-c|--config] | path to config
1516 - [-a|--add-instance] | generates 'instances.json' and 'INSTANCES.md' files with ur instance
1617 - [-h|--help] | returns this message
1718Example:
1819 ./skunkyart -c config.json
19Copyright lost+skunk, X11. https://git.macaw.me/skunky/skunkyart/src/tag/v1.3.1`
20Copyright lost+skunk, X11. https://git.macaw.me/skunky/skunkyart/src/tag/v{{.Version}}`
2021
2122 a := os.Args[1:]
2223 for n, x := range a {
@@ -28,7 +29,11 @@ Copyright lost+skunk, X11. https://git.macaw.me/skunky/skunkyart/src/tag/v1.3.1`
2829 exit("Not enought arguments", 1)
2930 }
3031 case "-h", "--help":
31 exit(helpmsg, 0)
32 var buf bytes.Buffer
33 t := template.New("help")
34 t.Parse(helpmsg)
35 t.Execute(&buf, &Release)
36 exit(buf.String(), 0)
3237 case "-a", "--add-instance":
3338 addInstance()
3439 }
app/config.go +5
@@ -11,6 +11,11 @@ import (
1111 "git.macaw.me/skunky/devianter"
1212)
1313
14var Release struct {
15 Version string
16 Description string
17}
18
1419type cache_config struct {
1520 Enabled bool
1621 Path string
app/router.go +29 −27
@@ -13,10 +13,9 @@ var Host, Path string
1313
1414func Router() {
1515 parsepath := func(path string) map[int]string {
16 path = "/"
1617 if l := len(CFG.URI); len(path) > l {
1718 path = path[l-1:]
18 } else {
19 path = "/"
2019 }
2120
2221 parsedpath := make(map[int]string)
@@ -54,44 +53,42 @@ func Router() {
5453
5554 // функция, что управляет всем
5655 handle := func(w http.ResponseWriter, r *http.Request) {
56 Path = r.URL.Path
57 path := parsepath(Path)
58 Host = "http://" + r.Host
59
5760 if h := r.Header["X-Forwarded-Proto"]; len(h) != 0 && h[0] == "https" {
58 Host = h[0] + "://" + r.Host
59 } else {
60 Host = "http://" + r.Host
61 Host = "https://" + r.Host
6162 }
6263
63 Path = r.URL.Path
64 path := parsepath(Path)
65 // структура с функциями
66 var skunky skunkyart
64 var skunky = skunkyart{Version: Release.Version}
65
66 arg := skunky.Args.Get
67 p, _ := strconv.Atoi(arg("p"))
68
69 skunky.Endpoint = path[1]
70 skunky.API.main = &skunky
6771 skunky.Writer = w
6872 skunky.Args = r.URL.Query()
6973 skunky.BasePath = CFG.URI
70
71 arg := skunky.Args.Get
7274 skunky.QueryRaw = arg("q")
7375 skunky.Query = u.QueryEscape(skunky.QueryRaw)
76 skunky.Page = p
7477
7578 if t := arg("type"); len(t) > 0 {
7679 skunky.Type = rune(t[0])
7780 }
78 p, _ := strconv.Atoi(arg("p"))
79 skunky.Page = p
8081
8182 if arg("atom") == "true" {
8283 skunky.Atom = true
8384 }
8485
85 skunky.Endpoint = path[1]
86 skunky.API.skunkyartLink = &skunky
87
88 // пути
8986 switch skunky.Endpoint {
90 default:
91 skunky.ReturnHTTPError(404)
92
87 // main
9388 case "":
9489 skunky.ExecuteTemplate("index.htm", "html", &CFG.URI)
90 case "about":
91 skunky.About()
9592 case "post":
9693 skunky.Deviation(path[2], path[3])
9794 case "search":
@@ -101,33 +98,38 @@ func Router() {
10198 case "group_user":
10299 skunky.GRUser()
103100
101 // media
104102 case "media":
105103 switch path[2] {
106104 case "file":
107105 if a := arg("filename"); a != "" {
108 var filename strings.Builder
109 filename.WriteString(`filename="`)
110 filename.WriteString(a)
111 filename.WriteString(`"`)
112 w.Header().Add("Content-Disposition", filename.String())
106 skunky.SetFilename(a)
113107 }
114108 skunky.DownloadAndSendMedia(path[3], next(path, 4))
115109 case "emojitar":
116110 skunky.Emojitar(path[3])
117111 }
118 case "about":
119 skunky.About()
120112 case "stylesheet":
121113 w.Header().Add("content-type", "text/css")
122114 w.Write(open("css/skunky.css"))
123115 case "favicon.ico":
124116 w.Write(open("images/logo.png"))
125117
118 // API
126119 case "api":
120 w.Header().Add("Content-Type", "application/json")
127121 switch path[2] {
122 case "instance":
123 skunky.API.Info()
128124 case "random":
129125 skunky.API.Random()
126 default:
127 skunky.API.Error("Not Found", 404)
130128 }
129
130 // 404
131 default:
132 skunky.ReturnHTTPError(404)
131133 }
132134 }
133135
app/util.go +13 −1
@@ -64,6 +64,7 @@ type skunkyart struct {
6464 Query, QueryRaw string
6565
6666 API API
67 Version string
6768
6869 Templates struct {
6970 About struct {
@@ -131,7 +132,7 @@ func UrlBuilder(strs ...string) string {
131132 str.WriteString(CFG.URI)
132133 for n, x := range strs {
133134 str.WriteString(x)
134 if n+1 < l && !(strs[n+1][0] == '?' || strs[n+1][0] == '&') && !(x[0] == '?' || x[0] == '&') {
135 if n := n+1; n < l && len(strs[n]) != 0 && !(strs[n][0] == '?' || strs[n][0] == '&') && !(x[0] == '?' || x[0] == '&') {
135136 str.WriteString("/")
136137 }
137138 }
@@ -153,6 +154,14 @@ func (s skunkyart) ReturnHTTPError(status int) {
153154 wr(s.Writer, msg.String())
154155}
155156
157func (s skunkyart) SetFilename(name string) {
158 var filename strings.Builder
159 filename.WriteString(`filename="`)
160 filename.WriteString(name)
161 filename.WriteString(`"`)
162 s.Writer.Header().Add("Content-Disposition", filename.String())
163}
164
156165type Downloaded struct {
157166 Headers http.Header
158167 Status int
@@ -189,6 +198,9 @@ func ParseMedia(media devianter.Media, thumb ...int) string {
189198 if len(mediaUrl) != 0 && CFG.Proxy {
190199 mediaUrl = mediaUrl[21:]
191200 dot := strings.Index(mediaUrl, ".")
201 if filename == "" {
202 filename = "image.gif"
203 }
192204 return UrlBuilder("media", "file", mediaUrl[:dot], mediaUrl[dot+11:], "&filename=", filename)
193205 }
194206 return mediaUrl
app/wrapper.go −1
@@ -42,7 +42,6 @@ func (s skunkyart) GRUser() {
4242 group.About.A = x.ModuleData.About
4343 var about = &group.About.A
4444 group.CreationDate = time.Unix(time.Now().Unix()-x.ModuleData.About.RegDate, 0).UTC().String()
45
4645 group.About.DescriptionFormatted = ParseDescription(about.Description)
4746
4847 for _, val := range x.ModuleData.About.SocialLinks {
go.mod +1 −1
@@ -2,7 +2,7 @@ module skunkyart
22
33go 1.18
44
5// replace git.macaw.me/skunky/devianter v0.2.5 => /home/skunk/projects/devianter
5replace git.macaw.me/skunky/devianter v0.2.5 => /home/skunk/projects/devianter
66require (
77 git.macaw.me/skunky/devianter v0.2.5
88 golang.org/x/net v0.27.0
main.go +2
@@ -9,6 +9,8 @@ import (
99)
1010
1111func main() {
12 app.Release.Version = "1.3.2-alpha"
13 app.Release.Description = "Two API endpoints and template embedding into binary"
1214 go app.RefreshInstances()
1315
1416 app.ExecuteCommandLineArguments()
static/html/about.htm +2 −2
@@ -44,6 +44,6 @@
4444 {{end}}
4545 </ul>
4646 </details>
47 <p>Copyright <a href="https://go.kde.org/matrix/#/@softpigeones:ebloid.ru" target="_blank">lost+skunk</a>, X11. <a href="https://git.macaw.me/skunky/skunkyart/src/tag/v1.3.1" target="_blank">SkunkyArt v1.3.1</a></p>
47 <p>Copyright <a href="https://go.kde.org/matrix/#/@softpigeones:ebloid.ru" target="_blank">lost+skunk</a>, X11. <a href="https://git.macaw.me/skunky/skunkyart/src/tag/v{{.Version}}" target="_blank">SkunkyArt v{{.Version}}</a></p>
4848 </main>
49</html>
\ No newline at end of file
49</html>