krz/skunky-art

Alternative privacy frontend for DeviantArt.

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

68248094e89b6af134147668a9add429b9a6fa77

unsigned

author: lost+skunk <skunky@ebloid.ru> · 2024-07-04T08:26:52Z

Галерея, папки и группы
 app/router.go   |  41 +++++++++++++--------
 app/util.go     |  13 +++++++
 app/wraper.go   | 109 ++++++++++++++++++++++++++++++++++++++++++--------------
 css/skunky.css  |   1 +
 html/gruser.htm |  21 ++++++++---
 5 files changed, 139 insertions(+), 46 deletions(-)

diff --git a/app/router.go b/app/router.go
index d98e2a9..4da2f7d 100644
--- a/app/router.go
+++ b/app/router.go
@@ -13,22 +13,34 @@ const addr string = "0.0.0.0:3003"
 
 // роутер
 func Router() {
-	// расшифровка эндпоинта из урл
-	endpoint := func(url string) (string, string) {
-		if CFG.Base_uri != "" {
-			url = strings.Replace(url, CFG.Base_uri, "/", 1)
+	parsepath := func(path string) map[int]string {
+		parsedpath := make(map[int]string)
+		for x := 0; true; x++ {
+			slash := strings.Index(path, "/") + 1
+			content := path[:slash]
+			path = path[slash:]
+			if slash == 0 {
+				parsedpath[x] = path
+				break
+			}
+			parsedpath[x] = content[:slash-1]
 		}
+		return parsedpath
+	}
 
-		end := strings.Index(url[1:], "/")
-		if end == -1 {
-			return url[1:], ""
+	next := func(path map[int]string, from int) (out string) {
+		for x, l := from, len(path)-1; x <= l; x++ {
+			out += path[x]
+			if x != l {
+				out += "/"
+			}
 		}
-		return url[1 : end+1], url[end+2:]
+		return
 	}
 
 	// функция, что управляет всем
 	handle := func(w http.ResponseWriter, r *http.Request) {
-		e, url := endpoint(r.URL.Path)
+		path := parsepath(r.URL.Path)
 		var wr = io.WriteString
 		open_n_send := func(name string) {
 			f, e := os.ReadFile(name)
@@ -50,14 +62,13 @@ func Router() {
 		skunky.Page = p
 
 		// пути
-		switch e {
+		switch path[1] {
 		default:
 			skunky.ReturnHTTPError(404)
-		case "/", "":
+		case "":
 			open_n_send("html/index.htm")
 		case "post":
-			slash := strings.Index(url, "/")
-			skunky.Deviation(url[:slash], url[slash+1:])
+			skunky.Deviation(path[2], path[3])
 		case "search":
 			skunky.Search()
 		case "dd":
@@ -66,12 +77,12 @@ func Router() {
 			skunky.GRUser()
 
 		case "media":
-			skunky.Emojitar(url)
+			skunky.Emojitar(path[2])
 		case "about":
 			open_n_send("html/about.htm")
 		case "gui":
 			w.Header().Add("content-type", "text/css")
-			open_n_send(url)
+			open_n_send(next(path, 2))
 		}
 	}
 
diff --git a/app/util.go b/app/util.go
index e4a1de2..cda0ffc 100644
--- a/app/util.go
+++ b/app/util.go
@@ -19,6 +19,15 @@ func (s skunkyart) ExecuteTemplate(file string, data any) {
 	wr(s.Writer, buf.String())
 }
 
+func (s skunkyart) UrlBuilder(strs ...string) string {
+	var str strings.Builder
+	for _, x := range strs {
+		str.WriteString(x)
+		str.WriteString("/")
+	}
+	return str.String()
+}
+
 func (s skunkyart) ReturnHTTPError(status int) {
 	s.Writer.WriteHeader(status)
 
@@ -142,6 +151,10 @@ func (s skunkyart) NavBase(c dlist) string {
 				list.WriteString("&q=")
 				list.WriteString(s.Query)
 			}
+			if f := s.Args.Get("folder"); f != "" {
+				list.WriteString("&folder=")
+				list.WriteString(f)
+			}
 			list.WriteString(`">`)
 			list.WriteString(msg)
 			list.WriteString("</a> ")
diff --git a/app/wraper.go b/app/wraper.go
index 2b733fd..f3f025d 100644
--- a/app/wraper.go
+++ b/app/wraper.go
@@ -1,7 +1,6 @@
 package app
 
 import (
-	"fmt"
 	"io"
 	"net/http"
 	"net/url"
@@ -24,6 +23,8 @@ type skunkyart struct {
 	Templates struct {
 		GroupUser struct {
 			GR           devianter.GRuser
+			Admins       string
+			Group        bool
 			CreationDate string
 
 			About struct {
@@ -37,8 +38,9 @@ type skunkyart struct {
 			}
 
 			Gallery struct {
-				Pages int
-				List  string
+				Folders string
+				Pages   int
+				List    string
 			}
 		}
 		Search struct {
@@ -61,19 +63,22 @@ func (s skunkyart) GRUser() {
 
 	switch s.Type {
 	case 'a':
-		if g := group.GR; !g.Owner.Group {
-			for _, x := range g.Gruser.Page.Modules {
-				switch x.Name {
-				case "about":
+		g := group.GR
+		for _, x := range g.Gruser.Page.Modules {
+			switch x.Name {
+			case "about", "group_about":
+				switch g.Owner.Group {
+				case true:
+					var about = &x.ModuleData.GroupAbout
+					group.Group = true
+					group.CreationDate = x.ModuleData.GroupAbout.FoundatedAt.UTC().String()
+					group.About.DescriptionFormatted = ParseDescription(about.Description)
+				case false:
 					group.About.A = x.ModuleData.About
-					var about = group.About.A
+					var about = &group.About.A
+					group.CreationDate = time.Unix(time.Now().Unix()-x.ModuleData.About.RegDate, 0).UTC().String()
+
 					group.About.DescriptionFormatted = ParseDescription(about.Description)
-					group.About.Comments = s.ParseComments(devianter.CommentsFunc(
-						strconv.Itoa(group.GR.Gruser.ID),
-						"",
-						s.Page,
-						4,
-					))
 
 					for _, val := range x.ModuleData.About.SocialLinks {
 						var social strings.Builder
@@ -93,25 +98,76 @@ func (s skunkyart) GRUser() {
 						interest.WriteString("</b><br>")
 						group.About.Interests += interest.String()
 					}
+				}
+				group.About.Comments = s.ParseComments(devianter.CommentsFunc(
+					strconv.Itoa(group.GR.Gruser.ID),
+					"",
+					s.Page,
+					4,
+				))
 
-					if rd := x.ModuleData.About.RegDate; rd != 0 {
-						group.CreationDate = time.Unix(time.Now().Unix()-rd, 0).UTC().String()
-					}
-				case "cover_deviation":
-					group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
-					group.About.BG = devianter.UrlFromMedia(group.About.BGMeta.Media)
+			case "cover_deviation":
+				group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
+				group.About.BG = devianter.UrlFromMedia(group.About.BGMeta.Media)
+			case "group_admins":
+				var htm strings.Builder
+				for _, z := range x.ModuleData.GroupAdmins.Results {
+					htm.WriteString(`<p><img src="`)
+					htm.WriteString("/media/")
+					htm.WriteString(z.User.Username)
+					htm.WriteString("?type=a")
+					htm.WriteString(`"><a href="`)
+					htm.WriteString("/group_user?type=about&q=")
+					htm.WriteString(z.User.Username)
+					htm.WriteString(`">`)
+					htm.WriteString(z.User.Username)
+					htm.WriteString(`</a></p>`)
 				}
+				group.Admins += htm.String()
 			}
-		} else {
 
 		}
 	case 'g':
-		gallery := g.Gallery(s.Page)
-		fmt.Println(gallery)
-		for _, x := range gallery.Content.Gruser.Page.Modules {
-			group.Gallery.List = s.DeviationList(x.ModuleData.Folder.Deviations, dlist{
-				Pages: x.ModuleData.Folder.Pages,
+		folderid, _ := strconv.Atoi(s.Args.Get("folder"))
+		if s.Page == 0 {
+			s.Page++
+		}
+
+		gallery := g.Gallery(s.Page, folderid)
+		if folderid > 0 {
+			group.Gallery.List = s.DeviationList(gallery.Content.Results, dlist{
+				More: gallery.Content.HasMore,
 			})
+		} else {
+			for _, x := range gallery.Content.Gruser.Page.Modules {
+				if l := len(x.ModuleData.Folders.Results); l != 0 {
+					var folders strings.Builder
+					folders.WriteString(`<h3 class="folders">Folders: `)
+					for n, x := range x.ModuleData.Folders.Results {
+						folders.WriteString(`<a href="?folder=`)
+						folders.WriteString(strconv.Itoa(x.FolderId))
+						folders.WriteString("&q=")
+						folders.WriteString(s.Query)
+						folders.WriteString("&type=")
+						folders.WriteString(string(s.Type))
+						folders.WriteString(`">`)
+						folders.WriteString(x.Name)
+						folders.WriteString(`</a>`)
+						if n+1 < l {
+							folders.WriteString(" | ")
+						}
+					}
+					folders.WriteString("</h3>")
+					group.Gallery.Folders = folders.String()
+				}
+
+				if x.Name == "folder_deviations" {
+					group.Gallery.List = s.DeviationList(x.ModuleData.Folder.Deviations, dlist{
+						Pages: x.ModuleData.Folder.Pages,
+						More:  x.ModuleData.Folder.HasMore,
+					})
+				}
+			}
 		}
 	default:
 		s.ReturnHTTPError(400)
@@ -193,7 +249,6 @@ func (s skunkyart) Emojitar(name string) {
 		ae, e := devianter.AEmedia(name, s.Type)
 		if e != nil {
 			s.ReturnHTTPError(404)
-			println(e.Error())
 		}
 		wr(s.Writer, ae)
 	} else {
diff --git a/css/skunky.css b/css/skunky.css
index 9c00522..9e38325 100644
--- a/css/skunky.css
+++ b/css/skunky.css
@@ -13,6 +13,7 @@ a:hover {
 }
 header h1 {
     padding-right: 0.2%;
+    padding-left: 0.2%;
 }
 header form {
     align-self: center;
diff --git a/html/gruser.htm b/html/gruser.htm
index 5a5c801..9035a88 100644
--- a/html/gruser.htm
+++ b/html/gruser.htm
@@ -19,12 +19,12 @@
                 <input type="gallery" name="q" placeholder="Search for ..." autocomplete="off" autocapitalize="none" spellcheck="false">
                 <input type="hidden" name="usr" value="{{.Templates.GroupUser.GR.Owner.Username}}">
                 <select name="type">
+                    <option value="gallery">Gallery</option>
                     <option value="all">All</option>
                     <option value="tag">Tag</option>
-                    <option value="gallery">Gallery</option>
                 </select>
                 <button type="submit">Search!</button>
-            </form>
+            </form> <h1>| {{.Templates.GroupUser.GR.Owner.Username}}</h1>
         </header>
         {{if eq .Type 'a'}}
             {{if ne .Templates.GroupUser.About.BG ""}}
@@ -42,12 +42,24 @@
             [<span title="UID">{{.Templates.GroupUser.GR.Gruser.ID}}</span>]
             [<span title="Registration date">{{.Templates.GroupUser.CreationDate}}</span>]
             {{if ne .Templates.GroupUser.GR.Extra.Tag ""}}
-            <i title="User's Tag">"{{.Templates.GroupUser.GR.Extra.Tag}}"</i>{{end}} (<b>{{.Templates.GroupUser.About.A.Country}}</b>)
+            <i title="User's Tag">"{{.Templates.GroupUser.GR.Extra.Tag}}"</i>{{end}} {{if ne .Templates.GroupUser.About.A.Country ""}}
+            (<b>{{.Templates.GroupUser.About.A.Country}}</b>)
+            {{end}}
 
+            {{if .Templates.GroupUser.Group}}
+            <h3 id="stats"><a href="#stats">#</a> Statistics</h3>
+            <p>Watchers: <b>{{.Templates.GroupUser.GR.Extra.Stats.Watchers}}</b>; Pageviews: <b>{{.Templates.GroupUser.GR.Extra.Stats.Pageviews}}</b></b>
+            {{else}}
             <h3 id="stats"><a href="#stats">#</a> Statistics</h3>
             <p>Favourites: <b>{{.Templates.GroupUser.GR.Extra.Stats.Favourites}}</b>; Deviations: <b>{{.Templates.GroupUser.GR.Extra.Stats.Deviations}}</b>; Watchers: <b>{{.Templates.GroupUser.GR.Extra.Stats.Watchers}}</b>
             <p>Watching: <b>{{.Templates.GroupUser.GR.Extra.Stats.Watching}}</b>; Pageviews: <b>{{.Templates.GroupUser.GR.Extra.Stats.Pageviews}}</b>; Comments Made: <b>{{.Templates.GroupUser.GR.Extra.Stats.CommentsMade}}</b>; Friends: <b>{{.Templates.GroupUser.GR.Extra.Stats.Friends}}</b></p>
-        
+            {{end}}
+
+            {{if ne .Templates.GroupUser.Admins ""}}
+            <h3 id="admins"><a href="#admins">#</a> Group admins</h3>
+            {{.Templates.GroupUser.Admins}}
+            {{end}}
+
             {{if ne .Templates.GroupUser.About.Interests ""}}
             <h3 id="interests"><a href="#interests">#</a> Interests</h3>
             {{.Templates.GroupUser.About.Interests}}
@@ -68,6 +80,7 @@
             {{.Templates.GroupUser.About.Comments}}
             {{end}}
         {{else}}
+            {{.Templates.GroupUser.Gallery.Folders}}
             {{.Templates.GroupUser.Gallery.List}}
         {{end}}
     </main>