krz/skunky-art

Alternative privacy frontend for DeviantArt.

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

a8633b828f3e4e2d232e2194d9f2b85cdcd9e8db

unsigned

author: lost+skunk <skunky@ebloid.ru> · 2024-06-27T11:51:46Z

крымские наработки
 app/router.go       |  3 ++
 app/util.go         | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 app/wraper.go       | 71 ++++++++++++++++++++++++++++++++++++++++--
 css/skunky.css      |  2 +-
 html/deviantion.htm |  2 ++
 html/gruser.htm     | 43 ++++++++++++++++++++++++++
 main.go             |  5 ++-
 7 files changed, 211 insertions(+), 4 deletions(-)

diff --git a/app/router.go b/app/router.go
index e53f3ce..9e51fd9 100644
--- a/app/router.go
+++ b/app/router.go
@@ -62,6 +62,9 @@ func Router() {
 			skunky.Search()
 		case "dd":
 			skunky.DD()
+		case "group":
+			skunky.GRUser()
+
 		case "media":
 			skunky.Emojitar(url)
 		case "about":
diff --git a/app/util.go b/app/util.go
new file mode 100644
index 0000000..7c4d104
--- /dev/null
+++ b/app/util.go
@@ -0,0 +1,89 @@
+package app
+
+import (
+	"encoding/json"
+	"strings"
+
+	"git.macaw.me/skunky/devianter"
+)
+
+type text struct {
+	TXT  string
+	from int
+	to   int
+}
+
+func ParseDescription(dscr devianter.Text) string {
+	var parseddescription strings.Builder
+	TagBuilder := func(tag string, content string) string {
+		if tag != "" {
+			var htm strings.Builder
+			htm.WriteString("<")
+			htm.WriteString(tag)
+			htm.WriteString(">")
+
+			htm.WriteString(content)
+
+			htm.WriteString("</")
+			htm.WriteString(tag)
+			htm.WriteString(">")
+			return htm.String()
+		}
+		return content
+	}
+
+	if description, dl := dscr.Html.Markup, len(dscr.Html.Markup); dl != 0 &&
+		description[0] == '{' &&
+		description[dl-1] == '}' {
+		var descr struct {
+			Blocks []struct {
+				Key, Text, Type   string
+				InlineStyleRanges []struct {
+					Offset, Length int
+					Style          string
+				}
+			}
+		}
+		e := json.Unmarshal([]byte(description), &descr)
+		err(e)
+
+		for _, x := range descr.Blocks {
+			ranges := make(map[int]text)
+			for i, rngs := range x.InlineStyleRanges {
+				var tag string
+
+				switch rngs.Style {
+				case "BOLD":
+					tag = "b"
+				case "UNDERLINE":
+					tag = "u"
+				case "ITALIC":
+					tag = "i"
+				}
+
+				fromto := rngs.Offset + rngs.Length
+				ranges[i] = text{
+					TXT:  TagBuilder(tag, x.Text[rngs.Offset:fromto]),
+					from: rngs.Offset,
+					to:   fromto,
+				}
+			}
+
+			for _, r := range ranges {
+				var tag string
+				switch x.Type {
+				case "header-two":
+					tag = "h2"
+				case "unstyled":
+					tag = "p"
+				}
+				parseddescription.WriteString(r.TXT)
+				parseddescription.WriteString(TagBuilder(tag, x.Text[r.to:]))
+			}
+		}
+	} else if dl != 0 {
+		parseddescription.WriteString(description)
+	}
+
+	return parseddescription.String()
+}
diff --git a/app/wraper.go b/app/wraper.go
index e252530..ccaccee 100644
--- a/app/wraper.go
+++ b/app/wraper.go
@@ -9,6 +9,7 @@ import (
 	"strconv"
 	"strings"
 	"text/template"
+	"time"
 
 	"git.macaw.me/skunky/devianter"
 )
@@ -117,6 +118,68 @@ func (s skunkyart) NavBase(c dlist) string {
 	return list.String()
 }
 
+func (s skunkyart) GRUser() {
+	var group struct {
+		GR           devianter.GRuser
+		CreationDate string
+
+		About struct {
+			A devianter.About
+
+			DescriptionFormatted string
+			Interests            string
+			Social               string
+			BG                   devianter.Deviation
+		}
+	}
+
+	if len(s.Query) < 1 {
+		s.httperr(400)
+		return
+	}
+
+	var g devianter.Group
+	g.Name = s.Query
+	group.GR = g.GroupFunc()
+
+	if g := group.GR; !g.Owner.Group {
+		for _, x := range g.Gruser.Page.Modules {
+			var about = group.About.A
+			if x.ModuleData.About.RegDate != 0 {
+				about = x.ModuleData.About
+			}
+			group.About.DescriptionFormatted = ParseDescription(about.Description)
+
+			for _, val := range x.ModuleData.About.Interests {
+				var interest strings.Builder
+				interest.WriteString(val.Label)
+				interest.WriteString(": <b>")
+				interest.WriteString(val.Value)
+				interest.WriteString("</b><br>")
+				group.About.Interests += interest.String()
+			}
+
+			for _, val := range x.ModuleData.About.SocialLinks {
+				var social strings.Builder
+				social.WriteString(`<a target="_blank" href="`)
+				social.WriteString(val.Value)
+				social.WriteString(`">`)
+				social.WriteString(val.Value)
+				social.WriteString("</a><br>")
+				group.About.Social += social.String()
+			}
+
+			if rd := x.ModuleData.About.RegDate; rd != 0 {
+				group.CreationDate = time.Unix(time.Now().Unix()-rd, 0).UTC().String()
+			}
+		}
+	} else {
+
+	}
+
+	s.exe("html/gruser.htm", &group)
+}
+
 func (s skunkyart) DeviationList(devs []devianter.Deviation, content ...dlist) string {
 	var list strings.Builder
 	list.WriteString(`<div class="content">`)
@@ -171,6 +234,7 @@ func (s skunkyart) Deviation(author, postname string) {
 		id := re[len(re)-1]
 		post.Post = devianter.DeviationFunc(id, author)
 
+		post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
 		// время публикации
 		post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
 
@@ -218,6 +282,7 @@ func (s skunkyart) Deviation(author, postname string) {
 			cmmts.WriteString(`">`)
 			cmmts.WriteString(x.User.Username)
 			cmmts.WriteString("</b></a> ")
+
 			if x.Parent > 0 {
 				cmmts.WriteString(` In reply to <a href="#`)
 				cmmts.WriteString(strconv.Itoa(x.Parent))
@@ -232,6 +297,7 @@ func (s skunkyart) Deviation(author, postname string) {
 			cmmts.WriteString(" [")
 			cmmts.WriteString(x.Posted.UTC().String())
 			cmmts.WriteString("]<p>")
+
 			cmmts.WriteString(x.Comment)
 			cmmts.WriteString("<p>👍: ")
 			cmmts.WriteString(strconv.Itoa(x.Likes))
@@ -263,7 +329,8 @@ func (s skunkyart) DD() {
 
 func (s skunkyart) Search() {
 	// тут всё и так понятно
-	if s.Type == 'a' || s.Type == 't' || s.Type == 'g' {
+	switch s.Type {
+	case 'a', 't', 'g':
 		var srch struct {
 			Search devianter.Search
 			List   string
@@ -278,7 +345,7 @@ func (s skunkyart) Search() {
 		})
 
 		s.exe("html/search.htm", &srch)
-	} else {
+	default:
 		s.httperr(400)
 	}
 }
diff --git a/css/skunky.css b/css/skunky.css
index 4a4af0d..95e7984 100644
--- a/css/skunky.css
+++ b/css/skunky.css
@@ -8,7 +8,7 @@ a {
     color: cadetblue;
 }
 a:hover {
-    color: red;
+    color: yellow;
     transition: 400ms;
 }
 header h1 {
diff --git a/html/deviantion.htm b/html/deviantion.htm
index 8516965..75484f6 100644
--- a/html/deviantion.htm
+++ b/html/deviantion.htm
@@ -34,7 +34,9 @@
             {{end}}
             <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>
             {{if (ne .Post.Description "")}}
+            <figcaption>
             {{.Post.Description}}
+            </figcaption>
             {{end}}
             {{if (ne .Comments "")}}
             {{.Comments}}
diff --git a/html/gruser.htm b/html/gruser.htm
new file mode 100644
index 0000000..b81ceb1
--- /dev/null
+++ b/html/gruser.htm
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>SkunkyArt | {{.GR.Owner.Username}}</title>
+        <link rel="stylesheet" href="/gui/css/skunky.css">
+    </head>
+    <main>
+        <header>
+            <h1><a href="/">HOME</a> | <a href="/dd">DD</a></h1>
+            <form method="get" action="/search">
+                <input type="text" name="q" placeholder="Search for ..." autocomplete="off" autocapitalize="none" spellcheck="false">
+                <select name="type">
+                    <option value="all">All</option>
+                    <option value="tag">Tag</option>
+                </select>
+                <button type="submit">Search!</button>
+            </form>
+        </header>
+        <img src="/media/{{.GR.Owner.Username}}?type=a" width="30px" height="30px"> <b>{{.GR.Owner.Username}}</b>
+        {{if (eq .About.A.Gender "male")}}
+        ♂️
+        {{end}}
+        {{if (eq .About.A.Gender "female")}}
+        ♀️
+        {{end}}
+        [<span title="UID">{{.GR.Gruser.ID}}</span>]
+        [<span title="Registration date">{{.CreationDate}}</span>]
+        <i title="User's Tag">"{{.GR.Extra.Tag}}"</i>
+
+        <h3 id="stats"><a href="#stats">#</a> Statistics</h3>
+        <p>Favourites: <b>{{.GR.Extra.Stats.Favourites}}</b>; Deviations: <b>{{.GR.Extra.Stats.Deviations}}</b>; Watchers: <b>{{.GR.Extra.Stats.Watchers}}</b>
+        <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>
+    
+        <h3 id="interests"><a href="#interests">#</a> Interests</h3>
+        {{.About.Interests}}
+
+        <h3 id="social"><a href="#social">#</a> Social Links</h3>
+        {{.About.Social}}
+
+        <h3 id="about"><a href="#about">#</a> About me</h3>
+        {{.About.DescriptionFormatted}}
+    </main>
+</html>
\ No newline at end of file
diff --git a/main.go b/main.go
index eab427b..4e3af62 100644
--- a/main.go
+++ b/main.go
@@ -7,7 +7,10 @@ import (
 )
 
 func main() {
-	devianter.UpdateCSRF()
+	err := devianter.UpdateCSRF()
+	if err != nil {
+		println(err.Error())
+	}
 
 	app.Router()
 }