Commit 0f528ee9fa
Unsigned
Layout: unified · split
app/util.go +25 −15
| @@ -66,12 +66,35 @@ func (s skunkyart) ConvertDeviantArtUrlToSkunkyArt(url string) (output string) { | ||
| 66 | 66 | return |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | func BuildUserPlate(name string) string { | |
| 70 | var htm strings.Builder | |
| 71 | htm.WriteString(`<div class="user-plate"><img src="`) | |
| 72 | htm.WriteString(UrlBuilder("media", "emojitar", name, "?type=a")) | |
| 73 | htm.WriteString(`"><a href="`) | |
| 74 | htm.WriteString(UrlBuilder("group_user", "?type=about&q=", name)) | |
| 75 | htm.WriteString(`">`) | |
| 76 | htm.WriteString(name) | |
| 77 | htm.WriteString(`</a></div>`) | |
| 78 | return htm.String() | |
| 79 | } | |
| 80 | ||
| 69 | 81 | type text struct { |
| 70 | 82 | TXT string |
| 71 | 83 | from int |
| 72 | 84 | to int |
| 73 | 85 | } |
| 74 | 86 | |
| 87 | func tagval(t *html.Tokenizer) string { | |
| 88 | for tt := t.Next(); ; { | |
| 89 | switch tt { | |
| 90 | default: | |
| 91 | return "" | |
| 92 | case html.TextToken: | |
| 93 | return string(t.Text()) | |
| 94 | } | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 75 | 98 | func ParseDescription(dscr devianter.Text) string { |
| 76 | 99 | var parseddescription strings.Builder |
| 77 | 100 | TagBuilder := func(tag string, content string) string { |
| @@ -182,20 +205,7 @@ func ParseDescription(dscr devianter.Text) string { | ||
| 182 | 205 | } |
| 183 | 206 | } |
| 184 | 207 | } else if dl != 0 { |
| 185 | tagval := func(t *html.Tokenizer) string { | |
| 186 | for { | |
| 187 | tt := t.Next() | |
| 188 | switch tt { | |
| 189 | case html.ErrorToken: | |
| 190 | return "" | |
| 191 | case html.TextToken: | |
| 192 | return string(t.Text()) | |
| 193 | } | |
| 194 | } | |
| 195 | } | |
| 196 | ||
| 197 | tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup)) | |
| 198 | for { | |
| 208 | for tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup)); ; { | |
| 199 | 209 | t := tt.Next() |
| 200 | 210 | switch t { |
| 201 | 211 | case html.ErrorToken: |
| @@ -314,7 +324,7 @@ func (s skunkyart) NavBase(c dlist) string { | ||
| 314 | 324 | } |
| 315 | 325 | |
| 316 | 326 | // вперёд-назад |
| 317 | if c.More { | |
| 327 | if p != 417 || c.More { | |
| 318 | 328 | prevrev("| Next =>", p+1, false) |
| 319 | 329 | } |
| 320 | 330 | |
app/wrapper.go +53 −11
| @@ -10,6 +10,7 @@ import ( | ||
| 10 | 10 | "time" |
| 11 | 11 | |
| 12 | 12 | "git.macaw.me/skunky/devianter" |
| 13 | "golang.org/x/net/html" | |
| 13 | 14 | ) |
| 14 | 15 | |
| 15 | 16 | var wr = io.WriteString |
| @@ -131,13 +132,7 @@ func (s skunkyart) GRUser() { | ||
| 131 | 132 | case "group_admins": |
| 132 | 133 | var htm strings.Builder |
| 133 | 134 | for _, z := range x.ModuleData.GroupAdmins.Results { |
| 134 | htm.WriteString(`<div class="admin"><img src="`) | |
| 135 | htm.WriteString(UrlBuilder("media", "emojitar", z.User.Username, "?type=a")) | |
| 136 | htm.WriteString(`"><a href="`) | |
| 137 | htm.WriteString(UrlBuilder("group_user", "?type=about&q=", z.User.Username)) | |
| 138 | htm.WriteString(`">`) | |
| 139 | htm.WriteString(z.User.Username) | |
| 140 | htm.WriteString(`</a></div>`) | |
| 135 | htm.WriteString(BuildUserPlate(z.User.Username)) | |
| 141 | 136 | } |
| 142 | 137 | group.Admins += htm.String() |
| 143 | 138 | } |
| @@ -270,15 +265,62 @@ func (s skunkyart) Search() { | ||
| 270 | 265 | ss.Content, e = devianter.SearchFunc(s.Query, s.Page, s.Type) |
| 271 | 266 | case 'g': |
| 272 | 267 | ss.Content, e = devianter.SearchFunc(s.Query, s.Page, s.Type, s.Args.Get("usr")) |
| 268 | case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп | |
| 269 | var ( | |
| 270 | usernames = make(map[int]string) | |
| 271 | url strings.Builder | |
| 272 | num int | |
| 273 | ) | |
| 274 | ||
| 275 | s.Page++ | |
| 276 | ||
| 277 | url.WriteString("https://www.deviantart.com/groups/?q=") | |
| 278 | url.WriteString(s.Query) | |
| 279 | if s.Page > 1 { | |
| 280 | url.WriteString("&offset=") | |
| 281 | url.WriteString(strconv.Itoa(10 * s.Page)) | |
| 282 | } | |
| 283 | ||
| 284 | r, err := http.Get(url.String()) | |
| 285 | if err != nil { | |
| 286 | s.ReturnHTTPError(502) | |
| 287 | } | |
| 288 | defer r.Body.Close() | |
| 289 | ||
| 290 | for z := html.NewTokenizer(r.Body); ; { | |
| 291 | if n, token := z.Next(), z.Token(); n == html.StartTagToken && token.Data == "a" { | |
| 292 | for _, x := range token.Attr { | |
| 293 | if x.Key == "class" && x.Val == "u regular username" { | |
| 294 | usernames[num] = tagval(z) | |
| 295 | num++ | |
| 296 | } | |
| 297 | } | |
| 298 | } else if n == 0 { | |
| 299 | break | |
| 300 | } else { | |
| 301 | continue | |
| 302 | } | |
| 303 | } | |
| 304 | ||
| 305 | if l := len(usernames); l != 0 { | |
| 306 | ss.List += `<div class="content plates">` | |
| 307 | for x := 0; x < len(usernames); x++ { | |
| 308 | ss.List += BuildUserPlate(usernames[x]) | |
| 309 | } | |
| 310 | ss.List += `</div>` | |
| 311 | ss.List += s.NavBase(dlist{}) | |
| 312 | } | |
| 273 | 313 | default: |
| 274 | 314 | s.ReturnHTTPError(400) |
| 275 | 315 | } |
| 276 | 316 | err(e) |
| 277 | 317 | |
| 278 | ss.List = s.DeviationList(ss.Content.Results, dlist{ | |
| 279 | Pages: ss.Content.Pages, | |
| 280 | More: ss.Content.HasMore, | |
| 281 | }) | |
| 318 | if s.Type != 'r' { | |
| 319 | ss.List = s.DeviationList(ss.Content.Results, dlist{ | |
| 320 | Pages: ss.Content.Pages, | |
| 321 | More: ss.Content.HasMore, | |
| 322 | }) | |
| 323 | } | |
| 282 | 324 | |
| 283 | 325 | s.ExecuteTemplate("html/search.htm", &s) |
| 284 | 326 | } |
css/skunky.css +9 −5
| @@ -82,7 +82,7 @@ form input, button, select { | ||
| 82 | 82 | border: 3px solid #4d27d6; |
| 83 | 83 | transition: 400ms; |
| 84 | 84 | } |
| 85 | .block img, .admins .admin img{ | |
| 85 | .block img, .plates .user-plate img{ | |
| 86 | 86 | width: 100%; |
| 87 | 87 | } |
| 88 | 88 | .block p { |
| @@ -103,16 +103,20 @@ form input, button, select { | ||
| 103 | 103 | background-color: #060820; |
| 104 | 104 | border: 3px solid #060820; |
| 105 | 105 | } |
| 106 | .admins { | |
| 106 | .plates { | |
| 107 | 107 | display: flex |
| 108 | 108 | } |
| 109 | .admins .admin { | |
| 110 | margin-left: 1%; | |
| 109 | .admins .user-plate { | |
| 110 | width: 5%; | |
| 111 | 111 | background-color: #011522; |
| 112 | } | |
| 113 | .plates .user-plate { | |
| 114 | margin-left: 1%; | |
| 115 | background-color: #091f19; | |
| 112 | 116 | padding: 3px; |
| 113 | 117 | word-break: break-all; |
| 114 | 118 | text-align: center; |
| 115 | width: 5%; | |
| 119 | max-width: 15%; | |
| 116 | 120 | } |
| 117 | 121 | |
| 118 | 122 | @media screen and (orientation: portrait) { |
html/about.htm +1
| @@ -12,6 +12,7 @@ | ||
| 12 | 12 | <select name="type"> |
| 13 | 13 | <option value="all">All</option> |
| 14 | 14 | <option value="tag">Tag</option> |
| 15 | <option value="r">Groups</option> | |
| 15 | 16 | </select> |
| 16 | 17 | <button type="submit">Search!</button> |
| 17 | 18 | </form> |
html/deviantion.htm +1
| @@ -12,6 +12,7 @@ | ||
| 12 | 12 | <select name="type"> |
| 13 | 13 | <option value="all">All</option> |
| 14 | 14 | <option value="tag">Tag</option> |
| 15 | <option value="r">Groups</option> | |
| 15 | 16 | </select> |
| 16 | 17 | <button type="submit">Search!</button> |
| 17 | 18 | </form> |
html/gruser.htm +2 −1
| @@ -22,6 +22,7 @@ | ||
| 22 | 22 | <option value="gallery">Gallery</option> |
| 23 | 23 | <option value="all">All</option> |
| 24 | 24 | <option value="tag">Tag</option> |
| 25 | <option value="r">Groups</option> | |
| 25 | 26 | </select> |
| 26 | 27 | <button type="submit">Search!</button> |
| 27 | 28 | </form> <h1>| {{.Templates.GroupUser.GR.Owner.Username}}</h1> |
| @@ -57,7 +58,7 @@ | ||
| 57 | 58 | |
| 58 | 59 | {{if ne .Templates.GroupUser.Admins ""}} |
| 59 | 60 | <h3 id="admins"><a href="#admins">#</a> Group admins</h3> |
| 60 | <div class="admins"> | |
| 61 | <div class="plates admins"> | |
| 61 | 62 | {{.Templates.GroupUser.Admins}} |
| 62 | 63 | </div> |
| 63 | 64 | {{end}} |
html/index.htm +1
| @@ -11,6 +11,7 @@ | ||
| 11 | 11 | <select name="type"> |
| 12 | 12 | <option value="all">All</option> |
| 13 | 13 | <option value="tag">Tag</option> |
| 14 | <option value="r">Groups</option> | |
| 14 | 15 | </select> |
| 15 | 16 | <button type="submit">Search!</button> |
| 16 | 17 | </form> |
html/list.htm +1
| @@ -12,6 +12,7 @@ | ||
| 12 | 12 | <select name="type"> |
| 13 | 13 | <option value="all">All</option> |
| 14 | 14 | <option value="tag">Tag</option> |
| 15 | <option value="r">Groups</option> | |
| 15 | 16 | </select> |
| 16 | 17 | <button type="submit">Search!</button> |
| 17 | 18 | </form> |
html/search.htm +1
| @@ -12,6 +12,7 @@ | ||
| 12 | 12 | <select name="type"> |
| 13 | 13 | <option value="all">All</option> |
| 14 | 14 | <option value="tag">Tag</option> |
| 15 | <option value="r">Groups</option> | |
| 15 | 16 | </select> |
| 16 | 17 | <button type="submit">Search!</button> |
| 17 | 18 | </form> |