Commit 048bb470ab
Unsigned
Layout: unified · split
app/api.go +7 −1
| @@ -41,12 +41,18 @@ func (a API) Error(description string, status int) { | |||
| 41 | func (a API) sendMedia(d *devianter.Deviation) { | 41 | func (a API) sendMedia(d *devianter.Deviation) { |
| 42 | mediaUrl, name := devianter.UrlFromMedia(d.Media) | 42 | mediaUrl, name := devianter.UrlFromMedia(d.Media) |
| 43 | a.main.SetFilename(name) | 43 | a.main.SetFilename(name) |
| 44 | |||
| 45 | if len(mediaUrl) != 0 { | 44 | if len(mediaUrl) != 0 { |
| 45 | return | ||
| 46 | } | ||
| 47 | |||
| 48 | if CFG.Proxy { | ||
| 46 | mediaUrl = mediaUrl[21:] | 49 | mediaUrl = mediaUrl[21:] |
| 47 | dot := strings.Index(mediaUrl, ".") | 50 | dot := strings.Index(mediaUrl, ".") |
| 48 | a.main.Writer.Header().Del("Content-Type") | 51 | a.main.Writer.Header().Del("Content-Type") |
| 49 | a.main.DownloadAndSendMedia(mediaUrl[:dot], mediaUrl[dot+11:]) | 52 | a.main.DownloadAndSendMedia(mediaUrl[:dot], mediaUrl[dot+11:]) |
| 53 | } else { | ||
| 54 | a.main.Writer.Header().Add("Location", mediaUrl) | ||
| 55 | a.main.Writer.WriteHeader(302) | ||
| 50 | } | 56 | } |
| 51 | } | 57 | } |
| 52 | 58 | ||
app/cache.go +45 −31
| @@ -38,17 +38,7 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) { | |||
| 38 | fileName := sha1.Sum([]byte(subdomain + path)) | 38 | fileName := sha1.Sum([]byte(subdomain + path)) |
| 39 | filePath := CFG.Cache.Path + "/" + hex.EncodeToString(fileName[:]) | 39 | filePath := CFG.Cache.Path + "/" + hex.EncodeToString(fileName[:]) |
| 40 | 40 | ||
| 41 | mx.Lock() | 41 | c := func() { |
| 42 | if tempFS[fileName] == nil { | ||
| 43 | tempFS[fileName] = &file{} | ||
| 44 | } | ||
| 45 | mx.Unlock() | ||
| 46 | |||
| 47 | if tempFS[fileName].Content != nil { | ||
| 48 | response = tempFS[fileName].Content | ||
| 49 | tempFS[fileName].Score += 2 | ||
| 50 | break | ||
| 51 | } else { | ||
| 52 | file, err := os.Open(filePath) | 42 | file, err := os.Open(filePath) |
| 53 | if err != nil { | 43 | if err != nil { |
| 54 | if dwnld := Download(url.String()); dwnld.Status == 200 && dwnld.Headers["Content-Type"][0][:5] == "image" { | 44 | 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) { | |||
| 63 | try(e) | 53 | try(e) |
| 64 | response = file | 54 | response = file |
| 65 | } | 55 | } |
| 56 | } | ||
| 66 | 57 | ||
| 67 | go func() { | 58 | if CFG.Cache.MemCache { |
| 68 | defer restore() | 59 | mx.Lock() |
| 69 | 60 | if tempFS[fileName] == nil { | |
| 70 | mx.RLock() | 61 | tempFS[fileName] = &file{} |
| 71 | tempFS[fileName].Content = response | 62 | } |
| 72 | mx.RUnlock() | 63 | mx.Unlock() |
| 73 | |||
| 74 | for { | ||
| 75 | time.Sleep(1 * time.Minute) | ||
| 76 | 64 | ||
| 77 | mx.Lock() | 65 | if tempFS[fileName].Content != nil { |
| 78 | if tempFS[fileName].Score <= 0 { | 66 | response = tempFS[fileName].Content |
| 79 | delete(tempFS, fileName) | 67 | tempFS[fileName].Score += 2 |
| 68 | break | ||
| 69 | } else { | ||
| 70 | c() | ||
| 71 | go func() { | ||
| 72 | defer restore() | ||
| 73 | |||
| 74 | mx.RLock() | ||
| 75 | tempFS[fileName].Content = response | ||
| 76 | mx.RUnlock() | ||
| 77 | |||
| 78 | for { | ||
| 79 | time.Sleep(1 * time.Minute) | ||
| 80 | |||
| 81 | mx.Lock() | ||
| 82 | if tempFS[fileName].Score <= 0 { | ||
| 83 | delete(tempFS, fileName) | ||
| 84 | mx.Unlock() | ||
| 85 | return | ||
| 86 | } | ||
| 87 | tempFS[fileName].Score-- | ||
| 80 | mx.Unlock() | 88 | mx.Unlock() |
| 81 | return | ||
| 82 | } | 89 | } |
| 83 | tempFS[fileName].Score-- | 90 | }() |
| 84 | mx.Unlock() | 91 | } |
| 85 | } | 92 | } else { |
| 86 | }() | 93 | c() |
| 87 | } | 94 | } |
| 88 | case CFG.Proxy: | 95 | case CFG.Proxy: |
| 89 | dwnld := Download(url.String()) | 96 | dwnld := Download(url.String()) |
| @@ -112,6 +119,7 @@ func InitCacheSystem() { | |||
| 112 | println(err.Error()) | 119 | println(err.Error()) |
| 113 | } | 120 | } |
| 114 | 121 | ||
| 122 | var total int64 | ||
| 115 | for _, file := range dir { | 123 | for _, file := range dir { |
| 116 | fileName := c.Path + "/" + file.Name() | 124 | fileName := c.Path + "/" + file.Name() |
| 117 | fileInfo, err := file.Info() | 125 | fileInfo, err := file.Info() |
| @@ -128,9 +136,15 @@ func InitCacheSystem() { | |||
| 128 | } | 136 | } |
| 129 | } | 137 | } |
| 130 | 138 | ||
| 131 | if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize { | 139 | total += fileInfo.Size() |
| 132 | try(os.RemoveAll(fileName)) | 140 | // if c.MaxSize != 0 && fileInfo.Size() > c.MaxSize { |
| 133 | } | 141 | // try(os.RemoveAll(fileName)) |
| 142 | // } | ||
| 143 | } | ||
| 144 | |||
| 145 | if c.MaxSize != 0 && total > c.MaxSize { | ||
| 146 | try(os.RemoveAll(c.Path)) | ||
| 147 | os.Mkdir(c.Path, 0700) | ||
| 134 | } | 148 | } |
| 135 | 149 | ||
| 136 | time.Sleep(time.Second * time.Duration(c.UpdateInterval)) | 150 | time.Sleep(time.Second * time.Duration(c.UpdateInterval)) |
app/config.go +4 −3
| @@ -12,12 +12,13 @@ import ( | |||
| 12 | ) | 12 | ) |
| 13 | 13 | ||
| 14 | var Release struct { | 14 | var Release struct { |
| 15 | Version string | 15 | Version string |
| 16 | Description string | 16 | Description string |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | type cache_config struct { | 19 | type cache_config struct { |
| 20 | Enabled bool | 20 | Enabled bool |
| 21 | MemCache bool `json:"memcache"` | ||
| 21 | Path string | 22 | Path string |
| 22 | MaxSize int64 `json:"max-size"` | 23 | MaxSize int64 `json:"max-size"` |
| 23 | Lifetime string | 24 | Lifetime string |
| @@ -93,9 +94,9 @@ func ExecuteConfig() { | |||
| 93 | 94 | ||
| 94 | About = instanceAbout{ | 95 | About = instanceAbout{ |
| 95 | Proxy: CFG.Proxy, | 96 | Proxy: CFG.Proxy, |
| 96 | Nsfw: CFG.Nsfw, | 97 | Nsfw: CFG.Nsfw, |
| 97 | } | 98 | } |
| 98 | 99 | ||
| 99 | static.StaticPath = CFG.StaticPath | 100 | static.StaticPath = CFG.StaticPath |
| 100 | devianter.UserAgent = CFG.UserAgent | 101 | devianter.UserAgent = CFG.UserAgent |
| 101 | } | 102 | } |
app/wrapper.go +10 −3
| @@ -36,13 +36,12 @@ func (s skunkyart) GRUser() { | |||
| 36 | for _, x := range g.Gruser.Page.Modules { | 36 | for _, x := range g.Gruser.Page.Modules { |
| 37 | switch x.Name { | 37 | switch x.Name { |
| 38 | case "about", "group_about": | 38 | case "about", "group_about": |
| 39 | switch g.Owner.Group { | 39 | if g.Owner.Group { |
| 40 | case true: | ||
| 41 | var about = &x.ModuleData.GroupAbout | 40 | var about = &x.ModuleData.GroupAbout |
| 42 | group.Group = true | 41 | group.Group = true |
| 43 | group.CreationDate = x.ModuleData.GroupAbout.FoundatedAt.UTC().String() | 42 | group.CreationDate = x.ModuleData.GroupAbout.FoundatedAt.UTC().String() |
| 44 | group.About.DescriptionFormatted = ParseDescription(about.Description) | 43 | group.About.DescriptionFormatted = ParseDescription(about.Description) |
| 45 | case false: | 44 | } else if false { |
| 46 | group.About.A = x.ModuleData.About | 45 | group.About.A = x.ModuleData.About |
| 47 | var about = &group.About.A | 46 | var about = &group.About.A |
| 48 | group.CreationDate = time.Unix(time.Now().Unix()-x.ModuleData.About.RegDate, 0).UTC().String() | 47 | 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) { | |||
| 186 | return | 185 | return |
| 187 | } | 186 | } |
| 188 | 187 | ||
| 188 | if post.Post.Deviation.NSFW { | ||
| 189 | s.Writer.WriteHeader(403) | ||
| 190 | wr(s.Writer, `<html><link rel="stylesheet" href="`+ | ||
| 191 | UrlBuilder("stylesheet")+ | ||
| 192 | `" /><h1>NSFW content are disabled on this instance.</h1></html>`) | ||
| 193 | return | ||
| 194 | } | ||
| 195 | |||
| 189 | if post.Post.Comments.Total <= 50 { | 196 | if post.Post.Comments.Total <= 50 { |
| 190 | post.Post.Comments.Cursor = "" | 197 | post.Post.Comments.Cursor = "" |
| 191 | } | 198 | } |
config.example.json +2 −1
| @@ -6,11 +6,12 @@ | |||
| 6 | "path": "cache", | 6 | "path": "cache", |
| 7 | "lifetime": null, | 7 | "lifetime": null, |
| 8 | "max-size": 200, | 8 | "max-size": 200, |
| 9 | "memcache": false, | ||
| 9 | "update-interval": 5 | 10 | "update-interval": 5 |
| 10 | }, | 11 | }, |
| 11 | "static-path": "static", | 12 | "static-path": "static", |
| 12 | "download-proxy": "http://127.0.0.1:8080", | 13 | "download-proxy": "http://127.0.0.1:8080", |
| 13 | "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", | 14 | "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", |
| 14 | "proxy": true, | 15 | "proxy": true, |
| 15 | "nsfw": true | 16 | "nsfw": false |
| 16 | } | 17 | } |
static/css/skunky.css +21 −9
| @@ -1,6 +1,6 @@ | |||
| 1 | /* TAGS */ | 1 | /* TAGS */ |
| 2 | html { | 2 | html { |
| 3 | font-family: Ubuntu; | 3 | font-family: ubuntu, system-ui; |
| 4 | background-color:black; | 4 | background-color:black; |
| 5 | color: rgb(234, 216, 216); | 5 | color: rgb(234, 216, 216); |
| 6 | } | 6 | } |
| @@ -45,24 +45,22 @@ input:focus { | |||
| 45 | justify-content: center; | 45 | justify-content: center; |
| 46 | } | 46 | } |
| 47 | .block { | 47 | .block { |
| 48 | max-width: 20%; | 48 | padding: 0px 0px 6px 0px; |
| 49 | height: 0%; | 49 | border: 3px solid #000; |
| 50 | padding: 4px; | ||
| 51 | border-radius: 2px; | ||
| 52 | border: 3px solid #091f19; | ||
| 53 | word-break: break-all; | 50 | word-break: break-all; |
| 54 | background-color: #091f19; | 51 | background-color: #091f19; |
| 55 | margin-left: 5px; | 52 | margin-left: 5px; |
| 56 | margin-top: 5px; | 53 | margin-top: 5px; |
| 57 | text-align: center; | 54 | text-align: center; |
| 58 | } | 55 | } |
| 56 | .block h1 { | ||
| 57 | padding: 8.5vh; | ||
| 58 | } | ||
| 59 | .block:hover { | 59 | .block:hover { |
| 60 | border: 3px solid #4d27d6; | 60 | border: 3px solid #4d27d6; |
| 61 | transition: 400ms; | 61 | transition: 400ms; |
| 62 | } | 62 | } |
| 63 | .block img, .plates .user-plate img { | 63 | |
| 64 | width: 100%; | ||
| 65 | } | ||
| 66 | .block p { | 64 | .block p { |
| 67 | word-break: break-all; | 65 | word-break: break-all; |
| 68 | } | 66 | } |
| @@ -185,6 +183,20 @@ input:focus { | |||
| 185 | font-size: 60%; | 183 | font-size: 60%; |
| 186 | max-width: 80% | 184 | max-width: 80% |
| 187 | } | 185 | } |
| 186 | .block img, .plates .user-plate img { | ||
| 187 | width: 100%; | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 191 | @media (orientation: landscape) { | ||
| 192 | .block { | ||
| 193 | width: 20%; | ||
| 194 | } | ||
| 195 | .block img, .plates .user-plate img { | ||
| 196 | width: 100%; | ||
| 197 | height: 30vh; | ||
| 198 | object-fit: cover; | ||
| 199 | } | ||
| 188 | } | 200 | } |
| 189 | 201 | ||
| 190 | @media (max-width: 1462px) and (orientation: landscape) { | 202 | @media (max-width: 1462px) and (orientation: landscape) { |
static/html/gruser.htm +1 −1
| @@ -30,7 +30,7 @@ | |||
| 30 | </form> <h1>| {{.Templates.GroupUser.GR.Owner.Username}}</h1> | 30 | </form> <h1>| {{.Templates.GroupUser.GR.Owner.Username}}</h1> |
| 31 | </header> | 31 | </header> |
| 32 | {{if eq .Type 'a'}} | 32 | {{if eq .Type 'a'}} |
| 33 | {{if ne .Templates.GroupUser.About.BG ""}} | 33 | {{if and (and (ne .Templates.About.Nsfw true) (ne .Templates.GroupUser.About.BGMeta.NSFW true)) (ne .Templates.GroupUser.About.BG "")}} |
| 34 | <a href="{{.Templates.GroupUser.About.BGMeta.Url}}" class="ubg"><img title="{{if ne .Templates.GroupUser.GR.Owner.Username .Templates.GroupUser.About.BGMeta.Author.Username}} | 34 | <a href="{{.Templates.GroupUser.About.BGMeta.Url}}" class="ubg"><img title="{{if ne .Templates.GroupUser.GR.Owner.Username .Templates.GroupUser.About.BGMeta.Author.Username}} |
| 35 | {{.Templates.GroupUser.About.BGMeta.Author.Username}} - {{end}}{{.Templates.GroupUser.About.BGMeta.Title}}" src="{{.Templates.GroupUser.About.BG}}"></a> | 35 | {{.Templates.GroupUser.About.BGMeta.Author.Username}} - {{end}}{{.Templates.GroupUser.About.BGMeta.Title}}" src="{{.Templates.GroupUser.About.BG}}"></a> |
| 36 | {{end}} | 36 | {{end}} |