krz/skunky-art

Alternative privacy frontend for DeviantArt.

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

048bb470ab8dc3adce83d2e615f3ab369efa2199

unsigned

author: lost+skunk <skunky@macaw.me> · 2025-02-22T12:30:29Z

Переключатель кеша в озу, небольшие улучшения ксс, фикс нсфв, фикс максимального размера кеша
 app/api.go             |  8 +++++-
 app/cache.go           | 76 ++++++++++++++++++++++++++++++--------------------
 app/config.go          |  7 +++--
 app/wrapper.go         | 13 +++++++--
 config.example.json    |  3 +-
 static/css/skunky.css  | 30 ++++++++++++++------
 static/html/gruser.htm |  2 +-
 7 files changed, 90 insertions(+), 49 deletions(-)

diff --git a/app/api.go b/app/api.go
index 048bc2a..d2a5655 100644
--- a/app/api.go
+++ b/app/api.go
@@ -41,12 +41,18 @@ func (a API) Error(description string, status int) {
 func (a API) sendMedia(d *devianter.Deviation) {
 	mediaUrl, name := devianter.UrlFromMedia(d.Media)
 	a.main.SetFilename(name)
-
 	if len(mediaUrl) != 0 {
+		return
+	}
+
+	if CFG.Proxy {
 		mediaUrl = mediaUrl[21:]
 		dot := strings.Index(mediaUrl, ".")
 		a.main.Writer.Header().Del("Content-Type")
 		a.main.DownloadAndSendMedia(mediaUrl[:dot], mediaUrl[dot+11:])
+	} else {
+		a.main.Writer.Header().Add("Location", mediaUrl)
+		a.main.Writer.WriteHeader(302)
 	}
 }
 
diff --git a/app/cache.go b/app/cache.go
index f9225be..e03db67 100644
--- a/app/cache.go
+++ b/app/cache.go
@@ -38,17 +38,7 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) {
 		fileName := sha1.Sum([]byte(subdomain + path))
 		filePath := CFG.Cache.Path + "/" + hex.EncodeToString(fileName[:])
 
-		mx.Lock()
-		if tempFS[fileName] == nil {
-			tempFS[fileName] = &file{}
-		}
-		mx.Unlock()
-
-		if tempFS[fileName].Content != nil {
-			response = tempFS[fileName].Content
-			tempFS[fileName].Score += 2
-			break
-		} else {
+		c := func() {
 			file, err := os.Open(filePath)
 			if err != nil {
 				if dwnld := Download(url.String()); dwnld.Status == 200 && dwnld.Headers["Content-Type"][0][:5] == "image" {
@@ -63,27 +53,44 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) {
 				try(e)
 				response = file
 			}
+		}
 
-			go func() {
-				defer restore()
-
-				mx.RLock()
-				tempFS[fileName].Content = response
-				mx.RUnlock()
-
-				for {
-					time.Sleep(1 * time.Minute)
+		if CFG.Cache.MemCache {
+			mx.Lock()
+			if tempFS[fileName] == nil {
+				tempFS[fileName] = &file{}
+			}
+			mx.Unlock()
 
-					mx.Lock()
-					if tempFS[fileName].Score <= 0 {
-						delete(tempFS, fileName)
+			if tempFS[fileName].Content != nil {
+				response = tempFS[fileName].Content
+				tempFS[fileName].Score += 2
+				break
+			} else {
+				c()
+				go func() {
+					defer restore()
+
+					mx.RLock()
+					tempFS[fileName].Content = response
+					mx.RUnlock()
+
+					for {
+						time.Sleep(1 * time.Minute)
+
+						mx.Lock()
+						if tempFS[fileName].Score <= 0 {
+							delete(tempFS, fileName)
+							mx.Unlock()
+							return
+						}
+						tempFS[fileName].Score--
 						mx.Unlock()
-						return
 					}
-					tempFS[fileName].Score--
-					mx.Unlock()
-				}
-			}()
+				}()
+			}
+		} else {
+			c()
 		}
 	case CFG.Proxy:
 		dwnld := Download(url.String())
@@ -112,6 +119,7 @@ func InitCacheSystem() {
 			println(err.Error())
 		}
 
+		var total int64
 		for _, file := range dir {
 			fileName := c.Path + "/" + file.Name()
 			fileInfo, err := file.Info()
@@ -128,9 +136,15 @@ func InitCacheSystem() {
 				}
 			}
 
-			if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize {
-				try(os.RemoveAll(fileName))
-			}
+			total += fileInfo.Size()
+			// if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize {
+			// 	try(os.RemoveAll(fileName))
+			// }
+		}
+
+		if c.MaxSize != 0 && total > c.MaxSize {
+			try(os.RemoveAll(c.Path))
+			os.Mkdir(c.Path, 0700)
 		}
 
 		time.Sleep(time.Second * time.Duration(c.UpdateInterval))
diff --git a/app/config.go b/app/config.go
index 2ba39a9..813453c 100644
--- a/app/config.go
+++ b/app/config.go
@@ -12,12 +12,13 @@ import (
 )
 
 var Release struct {
-	Version string
+	Version     string
 	Description string
 }
 
 type cache_config struct {
 	Enabled        bool
+	MemCache       bool `json:"memcache"`
 	Path           string
 	MaxSize        int64 `json:"max-size"`
 	Lifetime       string
@@ -93,9 +94,9 @@ func ExecuteConfig() {
 
 		About = instanceAbout{
 			Proxy: CFG.Proxy,
-			Nsfw: CFG.Nsfw,
+			Nsfw:  CFG.Nsfw,
 		}
-		
+
 		static.StaticPath = CFG.StaticPath
 		devianter.UserAgent = CFG.UserAgent
 	}
diff --git a/app/wrapper.go b/app/wrapper.go
index 5cac175..5fe1dde 100644
--- a/app/wrapper.go
+++ b/app/wrapper.go
@@ -36,13 +36,12 @@ func (s skunkyart) GRUser() {
 		for _, x := range g.Gruser.Page.Modules {
 			switch x.Name {
 			case "about", "group_about":
-				switch g.Owner.Group {
-				case true:
+				if g.Owner.Group {
 					var about = &x.ModuleData.GroupAbout
 					group.Group = true
 					group.CreationDate = x.ModuleData.GroupAbout.FoundatedAt.UTC().String()
 					group.About.DescriptionFormatted = ParseDescription(about.Description)
-				case false:
+				} else if false {
 					group.About.A = x.ModuleData.About
 					var about = &group.About.A
 					group.CreationDate = time.Unix(time.Now().Unix()-x.ModuleData.About.RegDate, 0).UTC().String()
@@ -186,6 +185,14 @@ func (s skunkyart) Deviation(author, postname string) {
 		return
 	}
 
+	if post.Post.Deviation.NSFW {
+		s.Writer.WriteHeader(403)
+		wr(s.Writer, `<html><link rel="stylesheet" href="`+
+			UrlBuilder("stylesheet")+
+			`" /><h1>NSFW content are disabled on this instance.</h1></html>`)
+		return
+	}
+
 	if post.Post.Comments.Total <= 50 {
 		post.Post.Comments.Cursor = ""
 	}
diff --git a/config.example.json b/config.example.json
index b38e47e..70e1c1b 100644
--- a/config.example.json
+++ b/config.example.json
@@ -6,11 +6,12 @@
         "path": "cache",
         "lifetime": null,
         "max-size": 200,
+        "memcache": false,
         "update-interval": 5
     },
     "static-path": "static",
     "download-proxy": "http://127.0.0.1:8080",
     "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
     "proxy": true,
-    "nsfw": true
+    "nsfw": false
 }
diff --git a/static/css/skunky.css b/static/css/skunky.css
index a7258c8..09cc71c 100644
--- a/static/css/skunky.css
+++ b/static/css/skunky.css
@@ -1,6 +1,6 @@
 /* TAGS */
 html {
-    font-family: Ubuntu;
+    font-family: ubuntu, system-ui;
     background-color:black;
     color: rgb(234, 216, 216);
 }
@@ -45,24 +45,22 @@ input:focus {
     justify-content: center;
 }
 .block {
-    max-width: 20%;
-    height: 0%;
-    padding: 4px;
-    border-radius: 2px;
-    border: 3px solid #091f19;
+    padding: 0px 0px 6px 0px;
+    border: 3px solid #000;
     word-break: break-all;
     background-color: #091f19;
     margin-left: 5px;
     margin-top: 5px;
     text-align: center;
 }
+.block h1 {
+    padding: 8.5vh;
+}
 .block:hover {
     border: 3px solid #4d27d6;
     transition: 400ms;
 }
-.block img, .plates .user-plate img {
-    width: 100%;
-}
+
 .block p {
     word-break: break-all;
 }
@@ -185,6 +183,20 @@ input:focus {
         font-size: 60%;
         max-width: 80%
     }
+    .block img, .plates .user-plate img {
+        width: 100%;
+    }
+}
+
+@media (orientation: landscape) {
+    .block {
+        width: 20%;
+    }
+    .block img, .plates .user-plate img {
+        width: 100%;
+        height: 30vh;
+        object-fit: cover;
+    }
 }
 
 @media (max-width: 1462px) and (orientation: landscape) {
diff --git a/static/html/gruser.htm b/static/html/gruser.htm
index 6593951..4e8e3d1 100644
--- a/static/html/gruser.htm
+++ b/static/html/gruser.htm
@@ -30,7 +30,7 @@
             </form> <h1>| {{.Templates.GroupUser.GR.Owner.Username}}</h1>
         </header>
         {{if eq .Type 'a'}}
-            {{if ne .Templates.GroupUser.About.BG ""}}
+            {{if and (and (ne .Templates.About.Nsfw true) (ne .Templates.GroupUser.About.BGMeta.NSFW true)) (ne .Templates.GroupUser.About.BG "")}}
             <a href="{{.Templates.GroupUser.About.BGMeta.Url}}" class="ubg"><img title="{{if ne .Templates.GroupUser.GR.Owner.Username .Templates.GroupUser.About.BGMeta.Author.Username}}
             {{.Templates.GroupUser.About.BGMeta.Author.Username}} - {{end}}{{.Templates.GroupUser.About.BGMeta.Title}}" src="{{.Templates.GroupUser.About.BG}}"></a>
             {{end}}