Commit cbafaa54d7

cbafaa54d79d73fd1cc56ecba540d4f763591100

parent: 6f872fe2f7

Unsigned

lost+skunk <skunky@macaw.me> · 2024-06-14 17:04 UTC

панель навигации, ответы и ежедневные арты

Layout: unified · split

.gitignore added +3
@@ -0,0 +1,3 @@
1**/cache
2**/config.json
3**/skunkyart
app/router.go +2
@@ -60,6 +60,8 @@ func Router() {
6060 skunky.Deviation(url[:slash], url[slash+1:])
6161 case "search":
6262 skunky.Search()
63 case "dd":
64 skunky.DD()
6365 case "media":
6466 skunky.Emojitar(url)
6567 case "about":
app/wraper.go +115 −10
@@ -47,7 +47,77 @@ func (s skunkyart) httperr(status int) {
4747 wr(s.Writer, msg.String())
4848}
4949
50func (s skunkyart) DeviationList(devs []devianter.Deviation) string {
50// навигация по страницам
51type dlist struct {
52 Pages int
53 More bool
54}
55
56// FIXME: на некоротрых артах первая страница может вызывать полное отсутствие панели навигации.
57func (s skunkyart) NavBase(c dlist) string {
58 // TODO: сделать понятнее
59 // навигация по страницам
60 var list strings.Builder
61 list.WriteString("<br>")
62 p := s.Page
63
64 // функция для генерации ссылок
65 prevrev := func(msg string, page int, onpage bool) {
66 if !onpage {
67 list.WriteString(`<a href="?p=`)
68 list.WriteString(strconv.Itoa(page))
69 if s.Type != 0 {
70 list.WriteString("&type=")
71 list.WriteRune(s.Type)
72 }
73 if s.Query != "" {
74 list.WriteString("&q=")
75 list.WriteString(s.Query)
76 }
77 list.WriteString(`">`)
78 list.WriteString(msg)
79 list.WriteString("</a> ")
80 } else {
81 list.WriteString(strconv.Itoa(page))
82 list.WriteString(" ")
83 }
84 }
85
86 // вперёд-назад
87 if p > 1 {
88 prevrev("<= Prev |", p-1, false)
89 } else {
90 p = 1
91 }
92
93 if c.Pages > 0 {
94 // назад
95 for x := p - 6; x < p && x > 0; x++ {
96 prevrev(strconv.Itoa(x), x, false)
97 }
98
99 // вперёд
100 for x := p; x <= p+6; x++ {
101 if x == p {
102 prevrev("", x, true)
103 x++
104 }
105
106 if x > p {
107 prevrev(strconv.Itoa(x), x, false)
108 }
109 }
110 }
111
112 // вперёд-назад
113 if c.More {
114 prevrev("| Next =>", p+1, false)
115 }
116
117 return list.String()
118}
119
120func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) string {
51121 var list strings.Builder
52122 list.WriteString(`<div class="content">`)
53123 for _, data := range devs {
@@ -81,6 +151,8 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation) string {
81151 list.WriteString("</a></div>")
82152 }
83153 list.WriteString("</div>")
154 list.WriteString(s.NavBase(content[0]))
155
84156 return list.String()
85157}
86158
@@ -102,7 +174,6 @@ func (s skunkyart) Deviation(author, postname string) {
102174 // время публикации
103175 post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
104176
105 println(post.Post.Description)
106177 // хештэги
107178 for _, x := range post.Post.Deviation.Extended.Tags {
108179 var tag strings.Builder
@@ -115,34 +186,52 @@ func (s skunkyart) Deviation(author, postname string) {
115186 post.Tags += tag.String()
116187 }
117188
189 // FIXME: первый комментарий не отображается.
118190 // генерация комментов
119191 var cmmts strings.Builder
120 var replied map[int]string
121 _ = replied
192 replied := make(map[int]string)
122193 c := devianter.CommentsFunc(id, post.Post.Comments.Cursor, s.Page, 1)
123194
124195 cmmts.WriteString("<details><summary>Comments: <b>")
125196 cmmts.WriteString(strconv.Itoa(c.Total))
126197 cmmts.WriteString("</b></summary>")
127198 for _, x := range c.Thread {
128 cmmts.WriteString(`<div class="msg"><p id="`)
199 replied[x.ID] = x.User.Username
200 cmmts.WriteString(`<div class="msg`)
201 if x.Parent > 0 {
202 cmmts.WriteString(` reply`)
203 }
204 cmmts.WriteString(`"><p id="`)
129205 cmmts.WriteString(strconv.Itoa(x.ID))
130206 cmmts.WriteString(`"><img src="/media/`)
131207 cmmts.WriteString(x.User.Username)
132208 cmmts.WriteString(`?type=a" width="30px" height="30px"><a href="/user/`)
133209 cmmts.WriteString(x.User.Username)
134210 cmmts.WriteString(`"><b`)
211 cmmts.WriteString(` class="`)
135212 if x.User.Banned {
136 cmmts.WriteString(` class="banned"`)
213 cmmts.WriteString(`banned`)
137214 }
138215 if x.Author {
139 cmmts.WriteString(` class="author"`)
216 cmmts.WriteString(`author`)
140217 }
141 cmmts.WriteString(">")
218 cmmts.WriteString(`">`)
142219 cmmts.WriteString(x.User.Username)
143220 cmmts.WriteString("</b></a> ")
221 if x.Parent > 0 {
222 cmmts.WriteString(` In reply to <a href="#`)
223 cmmts.WriteString(strconv.Itoa(x.Parent))
224 cmmts.WriteString(`">`)
225 if replied[x.Parent] == "" {
226 cmmts.WriteString("???")
227 } else {
228 cmmts.WriteString(replied[x.Parent])
229 }
230 cmmts.WriteString("</a>")
231 }
232 cmmts.WriteString(" [")
144233 cmmts.WriteString(x.Posted.UTC().String())
145 cmmts.WriteString("<p>")
234 cmmts.WriteString("]<p>")
146235 cmmts.WriteString(x.Comment)
147236 cmmts.WriteString("<p>👍: ")
148237 cmmts.WriteString(strconv.Itoa(x.Likes))
@@ -150,7 +239,12 @@ func (s skunkyart) Deviation(author, postname string) {
150239 cmmts.WriteString(strconv.Itoa(x.Replies))
151240 cmmts.WriteString("</p></div>\n")
152241 }
242 cmmts.WriteString(s.NavBase(dlist{
243 Pages: 0,
244 More: c.HasMore,
245 }))
153246 cmmts.WriteString("</details>")
247
154248 post.Comments = cmmts.String()
155249
156250 s.exe("html/deviantion.htm", &post)
@@ -159,6 +253,14 @@ func (s skunkyart) Deviation(author, postname string) {
159253 }
160254}
161255
256func (s skunkyart) DD() {
257 dd := devianter.DailyDeviationsFunc(s.Page)
258 s.exe("html/list.htm", s.DeviationList(dd.Deviations, dlist{
259 Pages: 0,
260 More: dd.HasMore,
261 }))
262}
263
162264func (s skunkyart) Search() {
163265 // тут всё и так понятно
164266 if s.Type == 'a' || s.Type == 't' || s.Type == 'g' {
@@ -170,7 +272,10 @@ func (s skunkyart) Search() {
170272 var e error
171273 srch.Search, e = devianter.SearchFunc(s.Query, s.Page, s.Type)
172274 err(e)
173 srch.List = s.DeviationList(srch.Search.Results)
275 srch.List = s.DeviationList(srch.Search.Results, dlist{
276 Pages: srch.Search.Pages,
277 More: srch.Search.HasMore,
278 })
174279
175280 s.exe("html/search.htm", &srch)
176281 } else {
config.example.json added +12
@@ -0,0 +1,12 @@
1{
2 "listen": "0.0.0.0:3003",
3 "base_uri": null,
4 "cache": {
5 "enabled": true,
6 "path": "cache",
7 "lifetime": null,
8 "max_size": 10000
9 },
10 "proxy": false,
11 "nsfw": false
12}
\ No newline at end of file
css/skunky.css +5
@@ -47,6 +47,11 @@ form input, button, select {
4747.msg:hover {
4848 background-color: #134134;
4949}
50.reply {
51 border-radius: 0px 2px 2px 0px;
52 border-left: #258268 solid;
53 margin-left: 40px;
54}
5055.dd {
5156 color: rgb(160, 0, 147);
5257}
html/list.htm added +21
@@ -0,0 +1,21 @@
1<!DOCTYPE html>
2<html>
3 <head>
4 <title>SkunkyArt</title>
5 <link rel="stylesheet" href="gui/css/skunky.css">
6 </head>
7 <main>
8 <header>
9 <h1><a href="/">HOME</a> | <a href="/dd">DD</a></h1>
10 <form method="get" action="/search">
11 <input type="text" name="q" placeholder="Search for ..." autocomplete="off" autocapitalize="none" spellcheck="false">
12 <select name="type">
13 <option value="all">All</option>
14 <option value="tag">Tag</option>
15 </select>
16 <button type="submit">Search!</button>
17 </form>
18 </header>
19 {{.}}
20 </main>
21</html>
\ No newline at end of file
html/search.htm −1
@@ -21,7 +21,6 @@
2121 <h1>Total resuls: {{.Search.Total}}</h1>
2222 {{end}}
2323 {{.List}}
24 {{.Search.Pages}}
2524 {{else}}
2625 <p>No results :(</p>
2726 {{end}}
main.go +7 −1
@@ -1,7 +1,13 @@
11package main
22
3import "skunkyart/app"
3import (
4 "skunkyart/app"
5
6 "git.macaw.me/skunky/devianter"
7)
48
59func main() {
10 devianter.UpdateCSRF()
11
612 app.Router()
713}