krz/skunky-art

Alternative privacy frontend for DeviantArt.

clone: git clone https://gitbay.org/krz/skunky-art.git

0f528ee9fa8b84c5e7532e22480b8b4b3ff7d5ba

unsigned

author: lost+skunk <skunky@ebloid.ru> · 2024-07-09T09:54:15Z

Поиск по группам
 app/util.go         | 40 ++++++++++++++++++++-------------
 app/wrapper.go      | 64 ++++++++++++++++++++++++++++++++++++++++++++---------
 css/skunky.css      | 14 +++++++-----
 html/about.htm      |  1 +
 html/deviantion.htm |  1 +
 html/gruser.htm     |  3 ++-
 html/index.htm      |  1 +
 html/list.htm       |  1 +
 html/search.htm     |  1 +
 9 files changed, 94 insertions(+), 32 deletions(-)

diff --git a/app/util.go b/app/util.go
index eb1c7ce..645ceb4 100644
--- a/app/util.go
+++ b/app/util.go
@@ -66,12 +66,35 @@ func (s skunkyart) ConvertDeviantArtUrlToSkunkyArt(url string) (output string) {
 	return
 }
 
+func BuildUserPlate(name string) string {
+	var htm strings.Builder
+	htm.WriteString(`<div class="user-plate"><img src="`)
+	htm.WriteString(UrlBuilder("media", "emojitar", name, "?type=a"))
+	htm.WriteString(`"><a href="`)
+	htm.WriteString(UrlBuilder("group_user", "?type=about&q=", name))
+	htm.WriteString(`">`)
+	htm.WriteString(name)
+	htm.WriteString(`</a></div>`)
+	return htm.String()
+}
+
 type text struct {
 	TXT  string
 	from int
 	to   int
 }
 
+func tagval(t *html.Tokenizer) string {
+	for tt := t.Next(); ; {
+		switch tt {
+		default:
+			return ""
+		case html.TextToken:
+			return string(t.Text())
+		}
+	}
+}
+
 func ParseDescription(dscr devianter.Text) string {
 	var parseddescription strings.Builder
 	TagBuilder := func(tag string, content string) string {
@@ -182,20 +205,7 @@ func ParseDescription(dscr devianter.Text) string {
 			}
 		}
 	} else if dl != 0 {
-		tagval := func(t *html.Tokenizer) string {
-			for {
-				tt := t.Next()
-				switch tt {
-				case html.ErrorToken:
-					return ""
-				case html.TextToken:
-					return string(t.Text())
-				}
-			}
-		}
-
-		tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup))
-		for {
+		for tt := html.NewTokenizer(strings.NewReader(dscr.Html.Markup)); ; {
 			t := tt.Next()
 			switch t {
 			case html.ErrorToken:
@@ -314,7 +324,7 @@ func (s skunkyart) NavBase(c dlist) string {
 	}
 
 	// вперёд-назад
-	if c.More {
+	if p != 417 || c.More {
 		prevrev("| Next =>", p+1, false)
 	}
 
diff --git a/app/wrapper.go b/app/wrapper.go
index 0340aed..0303c6a 100644
--- a/app/wrapper.go
+++ b/app/wrapper.go
@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"git.macaw.me/skunky/devianter"
+	"golang.org/x/net/html"
 )
 
 var wr = io.WriteString
@@ -131,13 +132,7 @@ func (s skunkyart) GRUser() {
 			case "group_admins":
 				var htm strings.Builder
 				for _, z := range x.ModuleData.GroupAdmins.Results {
-					htm.WriteString(`<div class="admin"><img src="`)
-					htm.WriteString(UrlBuilder("media", "emojitar", z.User.Username, "?type=a"))
-					htm.WriteString(`"><a href="`)
-					htm.WriteString(UrlBuilder("group_user", "?type=about&q=", z.User.Username))
-					htm.WriteString(`">`)
-					htm.WriteString(z.User.Username)
-					htm.WriteString(`</a></div>`)
+					htm.WriteString(BuildUserPlate(z.User.Username))
 				}
 				group.Admins += htm.String()
 			}
@@ -270,15 +265,62 @@ func (s skunkyart) Search() {
 		ss.Content, e = devianter.SearchFunc(s.Query, s.Page, s.Type)
 	case 'g':
 		ss.Content, e = devianter.SearchFunc(s.Query, s.Page, s.Type, s.Args.Get("usr"))
+	case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп
+		var (
+			usernames = make(map[int]string)
+			url       strings.Builder
+			num       int
+		)
+
+		s.Page++
+
+		url.WriteString("https://www.deviantart.com/groups/?q=")
+		url.WriteString(s.Query)
+		if s.Page > 1 {
+			url.WriteString("&offset=")
+			url.WriteString(strconv.Itoa(10 * s.Page))
+		}
+
+		r, err := http.Get(url.String())
+		if err != nil {
+			s.ReturnHTTPError(502)
+		}
+		defer r.Body.Close()
+
+		for z := html.NewTokenizer(r.Body); ; {
+			if n, token := z.Next(), z.Token(); n == html.StartTagToken && token.Data == "a" {
+				for _, x := range token.Attr {
+					if x.Key == "class" && x.Val == "u regular username" {
+						usernames[num] = tagval(z)
+						num++
+					}
+				}
+			} else if n == 0 {
+				break
+			} else {
+				continue
+			}
+		}
+
+		if l := len(usernames); l != 0 {
+			ss.List += `<div class="content plates">`
+			for x := 0; x < len(usernames); x++ {
+				ss.List += BuildUserPlate(usernames[x])
+			}
+			ss.List += `</div>`
+			ss.List += s.NavBase(dlist{})
+		}
 	default:
 		s.ReturnHTTPError(400)
 	}
 	err(e)
 
-	ss.List = s.DeviationList(ss.Content.Results, dlist{
-		Pages: ss.Content.Pages,
-		More:  ss.Content.HasMore,
-	})
+	if s.Type != 'r' {
+		ss.List = s.DeviationList(ss.Content.Results, dlist{
+			Pages: ss.Content.Pages,
+			More:  ss.Content.HasMore,
+		})
+	}
 
 	s.ExecuteTemplate("html/search.htm", &s)
 }
diff --git a/css/skunky.css b/css/skunky.css
index eb9b350..2abc92f 100644
--- a/css/skunky.css
+++ b/css/skunky.css
@@ -82,7 +82,7 @@ form input, button, select {
     border: 3px solid #4d27d6;
     transition: 400ms;
 }
-.block img, .admins .admin img{
+.block img, .plates .user-plate img{
     width: 100%;
 }
 .block p {
@@ -103,16 +103,20 @@ form input, button, select {
     background-color: #060820;
     border: 3px solid #060820;
 }
-.admins {
+.plates {
     display: flex
 }
-.admins .admin {
-    margin-left: 1%;
+.admins .user-plate {
+    width: 5%;
     background-color: #011522;
+}
+.plates .user-plate {
+    margin-left: 1%;
+    background-color: #091f19;
     padding: 3px;
     word-break: break-all;
     text-align: center;
-    width: 5%;
+    max-width: 15%;
 }
 
 @media screen and (orientation: portrait) {
diff --git a/html/about.htm b/html/about.htm
index 4a1b316..0495bb5 100644
--- a/html/about.htm
+++ b/html/about.htm
@@ -12,6 +12,7 @@
                 <select name="type">
                     <option value="all">All</option>
                     <option value="tag">Tag</option>
+                    <option value="r">Groups</option>
                 </select>
                 <button type="submit">Search!</button>
             </form>
diff --git a/html/deviantion.htm b/html/deviantion.htm
index 97850d3..27f1f0a 100644
--- a/html/deviantion.htm
+++ b/html/deviantion.htm
@@ -12,6 +12,7 @@
                 <select name="type">
                     <option value="all">All</option>
                     <option value="tag">Tag</option>
+                    <option value="r">Groups</option>
                 </select>
                 <button type="submit">Search!</button>
             </form>
diff --git a/html/gruser.htm b/html/gruser.htm
index a1f6e37..4f01c3e 100644
--- a/html/gruser.htm
+++ b/html/gruser.htm
@@ -22,6 +22,7 @@
                     <option value="gallery">Gallery</option>
                     <option value="all">All</option>
                     <option value="tag">Tag</option>
+                    <option value="r">Groups</option>
                 </select>
                 <button type="submit">Search!</button>
             </form> <h1>| {{.Templates.GroupUser.GR.Owner.Username}}</h1>
@@ -57,7 +58,7 @@
 
             {{if ne .Templates.GroupUser.Admins ""}}
             <h3 id="admins"><a href="#admins">#</a> Group admins</h3>
-            <div class="admins">
+            <div class="plates admins">
             {{.Templates.GroupUser.Admins}}
             </div>
             {{end}}
diff --git a/html/index.htm b/html/index.htm
index c01fd8c..01286f3 100644
--- a/html/index.htm
+++ b/html/index.htm
@@ -11,6 +11,7 @@
                 <select name="type">
                     <option value="all">All</option>
                     <option value="tag">Tag</option>
+                    <option value="r">Groups</option>
                 </select>
                 <button type="submit">Search!</button>
             </form>
diff --git a/html/list.htm b/html/list.htm
index 57b4659..38ab5e0 100644
--- a/html/list.htm
+++ b/html/list.htm
@@ -12,6 +12,7 @@
                 <select name="type">
                     <option value="all">All</option>
                     <option value="tag">Tag</option>
+                    <option value="r">Groups</option>
                 </select>
                 <button type="submit">Search!</button>
             </form>
diff --git a/html/search.htm b/html/search.htm
index 6644bfc..39e0875 100644
--- a/html/search.htm
+++ b/html/search.htm
@@ -12,6 +12,7 @@
                 <select name="type">
                     <option value="all">All</option>
                     <option value="tag">Tag</option>
+                    <option value="r">Groups</option>
                 </select>
                 <button type="submit">Search!</button>
             </form>