Commit a8633b828f
Unsigned
Layout: unified · split
app/router.go +3
| @@ -62,6 +62,9 @@ func Router() { | |||
| 62 | skunky.Search() | 62 | skunky.Search() |
| 63 | case "dd": | 63 | case "dd": |
| 64 | skunky.DD() | 64 | skunky.DD() |
| 65 | case "group": | ||
| 66 | skunky.GRUser() | ||
| 67 | |||
| 65 | case "media": | 68 | case "media": |
| 66 | skunky.Emojitar(url) | 69 | skunky.Emojitar(url) |
| 67 | case "about": | 70 | case "about": |
app/util.go added +89
| @@ -0,0 +1,89 @@ | |||
| 1 | package app | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "encoding/json" | ||
| 5 | "strings" | ||
| 6 | |||
| 7 | "git.macaw.me/skunky/devianter" | ||
| 8 | ) | ||
| 9 | |||
| 10 | type text struct { | ||
| 11 | TXT string | ||
| 12 | from int | ||
| 13 | to int | ||
| 14 | } | ||
| 15 | |||
| 16 | func ParseDescription(dscr devianter.Text) string { | ||
| 17 | var parseddescription strings.Builder | ||
| 18 | TagBuilder := func(tag string, content string) string { | ||
| 19 | if tag != "" { | ||
| 20 | var htm strings.Builder | ||
| 21 | htm.WriteString("<") | ||
| 22 | htm.WriteString(tag) | ||
| 23 | htm.WriteString(">") | ||
| 24 | |||
| 25 | htm.WriteString(content) | ||
| 26 | |||
| 27 | htm.WriteString("</") | ||
| 28 | htm.WriteString(tag) | ||
| 29 | htm.WriteString(">") | ||
| 30 | return htm.String() | ||
| 31 | } | ||
| 32 | return content | ||
| 33 | } | ||
| 34 | |||
| 35 | if description, dl := dscr.Html.Markup, len(dscr.Html.Markup); dl != 0 && | ||
| 36 | description[0] == '{' && | ||
| 37 | description[dl-1] == '}' { | ||
| 38 | var descr struct { | ||
| 39 | Blocks []struct { | ||
| 40 | Key, Text, Type string | ||
| 41 | InlineStyleRanges []struct { | ||
| 42 | Offset, Length int | ||
| 43 | Style string | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | e := json.Unmarshal([]byte(description), &descr) | ||
| 48 | err(e) | ||
| 49 | |||
| 50 | for _, x := range descr.Blocks { | ||
| 51 | ranges := make(map[int]text) | ||
| 52 | for i, rngs := range x.InlineStyleRanges { | ||
| 53 | var tag string | ||
| 54 | |||
| 55 | switch rngs.Style { | ||
| 56 | case "BOLD": | ||
| 57 | tag = "b" | ||
| 58 | case "UNDERLINE": | ||
| 59 | tag = "u" | ||
| 60 | case "ITALIC": | ||
| 61 | tag = "i" | ||
| 62 | } | ||
| 63 | |||
| 64 | fromto := rngs.Offset + rngs.Length | ||
| 65 | ranges[i] = text{ | ||
| 66 | TXT: TagBuilder(tag, x.Text[rngs.Offset:fromto]), | ||
| 67 | from: rngs.Offset, | ||
| 68 | to: fromto, | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | for _, r := range ranges { | ||
| 73 | var tag string | ||
| 74 | switch x.Type { | ||
| 75 | case "header-two": | ||
| 76 | tag = "h2" | ||
| 77 | case "unstyled": | ||
| 78 | tag = "p" | ||
| 79 | } | ||
| 80 | parseddescription.WriteString(r.TXT) | ||
| 81 | parseddescription.WriteString(TagBuilder(tag, x.Text[r.to:])) | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } else if dl != 0 { | ||
| 85 | parseddescription.WriteString(description) | ||
| 86 | } | ||
| 87 | |||
| 88 | return parseddescription.String() | ||
| 89 | } | ||
app/wraper.go +69 −2
| @@ -9,6 +9,7 @@ import ( | |||
| 9 | "strconv" | 9 | "strconv" |
| 10 | "strings" | 10 | "strings" |
| 11 | "text/template" | 11 | "text/template" |
| 12 | "time" | ||
| 12 | 13 | ||
| 13 | "git.macaw.me/skunky/devianter" | 14 | "git.macaw.me/skunky/devianter" |
| 14 | ) | 15 | ) |
| @@ -117,6 +118,68 @@ func (s skunkyart) NavBase(c dlist) string { | |||
| 117 | return list.String() | 118 | return list.String() |
| 118 | } | 119 | } |
| 119 | 120 | ||
| 121 | func (s skunkyart) GRUser() { | ||
| 122 | var group struct { | ||
| 123 | GR devianter.GRuser | ||
| 124 | CreationDate string | ||
| 125 | |||
| 126 | About struct { | ||
| 127 | A devianter.About | ||
| 128 | |||
| 129 | DescriptionFormatted string | ||
| 130 | Interests string | ||
| 131 | Social string | ||
| 132 | BG devianter.Deviation | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | if len(s.Query) < 1 { | ||
| 137 | s.httperr(400) | ||
| 138 | return | ||
| 139 | } | ||
| 140 | |||
| 141 | var g devianter.Group | ||
| 142 | g.Name = s.Query | ||
| 143 | group.GR = g.GroupFunc() | ||
| 144 | |||
| 145 | if g := group.GR; !g.Owner.Group { | ||
| 146 | for _, x := range g.Gruser.Page.Modules { | ||
| 147 | var about = group.About.A | ||
| 148 | if x.ModuleData.About.RegDate != 0 { | ||
| 149 | about = x.ModuleData.About | ||
| 150 | } | ||
| 151 | group.About.DescriptionFormatted = ParseDescription(about.Description) | ||
| 152 | |||
| 153 | for _, val := range x.ModuleData.About.Interests { | ||
| 154 | var interest strings.Builder | ||
| 155 | interest.WriteString(val.Label) | ||
| 156 | interest.WriteString(": <b>") | ||
| 157 | interest.WriteString(val.Value) | ||
| 158 | interest.WriteString("</b><br>") | ||
| 159 | group.About.Interests += interest.String() | ||
| 160 | } | ||
| 161 | |||
| 162 | for _, val := range x.ModuleData.About.SocialLinks { | ||
| 163 | var social strings.Builder | ||
| 164 | social.WriteString(`<a target="_blank" href="`) | ||
| 165 | social.WriteString(val.Value) | ||
| 166 | social.WriteString(`">`) | ||
| 167 | social.WriteString(val.Value) | ||
| 168 | social.WriteString("</a><br>") | ||
| 169 | group.About.Social += social.String() | ||
| 170 | } | ||
| 171 | |||
| 172 | if rd := x.ModuleData.About.RegDate; rd != 0 { | ||
| 173 | group.CreationDate = time.Unix(time.Now().Unix()-rd, 0).UTC().String() | ||
| 174 | } | ||
| 175 | } | ||
| 176 | } else { | ||
| 177 | |||
| 178 | } | ||
| 179 | |||
| 180 | s.exe("html/gruser.htm", &group) | ||
| 181 | } | ||
| 182 | |||
| 120 | func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) string { | 183 | func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) string { |
| 121 | var list strings.Builder | 184 | var list strings.Builder |
| 122 | list.WriteString(`<div class="content">`) | 185 | list.WriteString(`<div class="content">`) |
| @@ -171,6 +234,7 @@ func (s skunkyart) Deviation(author, postname string) { | |||
| 171 | id := re[len(re)-1] | 234 | id := re[len(re)-1] |
| 172 | post.Post = devianter.DeviationFunc(id, author) | 235 | post.Post = devianter.DeviationFunc(id, author) |
| 173 | 236 | ||
| 237 | post.Post.Description = ParseDescription(post.Post.Deviation.TextContent) | ||
| 174 | // время публикации | 238 | // время публикации |
| 175 | post.StringTime = post.Post.Deviation.PublishedTime.UTC().String() | 239 | post.StringTime = post.Post.Deviation.PublishedTime.UTC().String() |
| 176 | 240 | ||
| @@ -218,6 +282,7 @@ func (s skunkyart) Deviation(author, postname string) { | |||
| 218 | cmmts.WriteString(`">`) | 282 | cmmts.WriteString(`">`) |
| 219 | cmmts.WriteString(x.User.Username) | 283 | cmmts.WriteString(x.User.Username) |
| 220 | cmmts.WriteString("</b></a> ") | 284 | cmmts.WriteString("</b></a> ") |
| 285 | |||
| 221 | if x.Parent > 0 { | 286 | if x.Parent > 0 { |
| 222 | cmmts.WriteString(` In reply to <a href="#`) | 287 | cmmts.WriteString(` In reply to <a href="#`) |
| 223 | cmmts.WriteString(strconv.Itoa(x.Parent)) | 288 | cmmts.WriteString(strconv.Itoa(x.Parent)) |
| @@ -232,6 +297,7 @@ func (s skunkyart) Deviation(author, postname string) { | |||
| 232 | cmmts.WriteString(" [") | 297 | cmmts.WriteString(" [") |
| 233 | cmmts.WriteString(x.Posted.UTC().String()) | 298 | cmmts.WriteString(x.Posted.UTC().String()) |
| 234 | cmmts.WriteString("]<p>") | 299 | cmmts.WriteString("]<p>") |
| 300 | |||
| 235 | cmmts.WriteString(x.Comment) | 301 | cmmts.WriteString(x.Comment) |
| 236 | cmmts.WriteString("<p>👍: ") | 302 | cmmts.WriteString("<p>👍: ") |
| 237 | cmmts.WriteString(strconv.Itoa(x.Likes)) | 303 | cmmts.WriteString(strconv.Itoa(x.Likes)) |
| @@ -263,7 +329,8 @@ func (s skunkyart) DD() { | |||
| 263 | 329 | ||
| 264 | func (s skunkyart) Search() { | 330 | func (s skunkyart) Search() { |
| 265 | // тут всё и так понятно | 331 | // тут всё и так понятно |
| 266 | if s.Type == 'a' || s.Type == 't' || s.Type == 'g' { | 332 | switch s.Type { |
| 333 | case 'a', 't', 'g': | ||
| 267 | var srch struct { | 334 | var srch struct { |
| 268 | Search devianter.Search | 335 | Search devianter.Search |
| 269 | List string | 336 | List string |
| @@ -278,7 +345,7 @@ func (s skunkyart) Search() { | |||
| 278 | }) | 345 | }) |
| 279 | 346 | ||
| 280 | s.exe("html/search.htm", &srch) | 347 | s.exe("html/search.htm", &srch) |
| 281 | } else { | 348 | default: |
| 282 | s.httperr(400) | 349 | s.httperr(400) |
| 283 | } | 350 | } |
| 284 | } | 351 | } |
css/skunky.css +1 −1
| @@ -8,7 +8,7 @@ a { | |||
| 8 | color: cadetblue; | 8 | color: cadetblue; |
| 9 | } | 9 | } |
| 10 | a:hover { | 10 | a:hover { |
| 11 | color: red; | 11 | color: yellow; |
| 12 | transition: 400ms; | 12 | transition: 400ms; |
| 13 | } | 13 | } |
| 14 | header h1 { | 14 | header h1 { |
html/deviantion.htm +2
| @@ -34,7 +34,9 @@ | |||
| 34 | {{end}} | 34 | {{end}} |
| 35 | <span>Published: <strong>{{.StringTime}}</strong>; Views: <strong>{{.Post.Deviation.Stats.Views}}</strong>; Favourites: <strong>{{.Post.Deviation.Stats.Favourites}}</strong>; Downloads: <strong>{{.Post.Deviation.Stats.Downloads}}</strong></span> | 35 | <span>Published: <strong>{{.StringTime}}</strong>; Views: <strong>{{.Post.Deviation.Stats.Views}}</strong>; Favourites: <strong>{{.Post.Deviation.Stats.Favourites}}</strong>; Downloads: <strong>{{.Post.Deviation.Stats.Downloads}}</strong></span> |
| 36 | {{if (ne .Post.Description "")}} | 36 | {{if (ne .Post.Description "")}} |
| 37 | <figcaption> | ||
| 37 | {{.Post.Description}} | 38 | {{.Post.Description}} |
| 39 | </figcaption> | ||
| 38 | {{end}} | 40 | {{end}} |
| 39 | {{if (ne .Comments "")}} | 41 | {{if (ne .Comments "")}} |
| 40 | {{.Comments}} | 42 | {{.Comments}} |
html/gruser.htm added +43
| @@ -0,0 +1,43 @@ | |||
| 1 | <!DOCTYPE html> | ||
| 2 | <html> | ||
| 3 | <head> | ||
| 4 | <title>SkunkyArt | {{.GR.Owner.Username}}</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 | <img src="/media/{{.GR.Owner.Username}}?type=a" width="30px" height="30px"> <b>{{.GR.Owner.Username}}</b> | ||
| 20 | {{if (eq .About.A.Gender "male")}} | ||
| 21 | ♂️ | ||
| 22 | {{end}} | ||
| 23 | {{if (eq .About.A.Gender "female")}} | ||
| 24 | ♀️ | ||
| 25 | {{end}} | ||
| 26 | [<span title="UID">{{.GR.Gruser.ID}}</span>] | ||
| 27 | [<span title="Registration date">{{.CreationDate}}</span>] | ||
| 28 | <i title="User's Tag">"{{.GR.Extra.Tag}}"</i> | ||
| 29 | |||
| 30 | <h3 id="stats"><a href="#stats">#</a> Statistics</h3> | ||
| 31 | <p>Favourites: <b>{{.GR.Extra.Stats.Favourites}}</b>; Deviations: <b>{{.GR.Extra.Stats.Deviations}}</b>; Watchers: <b>{{.GR.Extra.Stats.Watchers}}</b> | ||
| 32 | <p>Watching: <b>{{.GR.Extra.Stats.Watching}}</b>; Pageviews: <b>{{.GR.Extra.Stats.Pageviews}}</b>; Comments Made: <b>{{.GR.Extra.Stats.CommentsMade}}</b>; Friends: <b>{{.GR.Extra.Stats.Friends}}</b></p> | ||
| 33 | |||
| 34 | <h3 id="interests"><a href="#interests">#</a> Interests</h3> | ||
| 35 | {{.About.Interests}} | ||
| 36 | |||
| 37 | <h3 id="social"><a href="#social">#</a> Social Links</h3> | ||
| 38 | {{.About.Social}} | ||
| 39 | |||
| 40 | <h3 id="about"><a href="#about">#</a> About me</h3> | ||
| 41 | {{.About.DescriptionFormatted}} | ||
| 42 | </main> | ||
| 43 | </html>\ No newline at end of file | ||
main.go +4 −1
| @@ -7,7 +7,10 @@ import ( | |||
| 7 | ) | 7 | ) |
| 8 | 8 | ||
| 9 | func main() { | 9 | func main() { |
| 10 | devianter.UpdateCSRF() | 10 | err := devianter.UpdateCSRF() |
| 11 | if err != nil { | ||
| 12 | println(err.Error()) | ||
| 13 | } | ||
| 11 | 14 | ||
| 12 | app.Router() | 15 | app.Router() |
| 13 | } | 16 | } |