instance list update
This commit is contained in:
parent
2f8c35ba32
commit
1464584264
@ -3,5 +3,5 @@
|
|||||||
|[skunky.ebloid.ru](https://skunky.ebloid.ru/art)|[Yes](http://[201:eba5:d1fc:bf7b:cfcb:a811:4b8b:7ea3]/art)|No|No| No | No | No | Russia |
|
|[skunky.ebloid.ru](https://skunky.ebloid.ru/art)|[Yes](http://[201:eba5:d1fc:bf7b:cfcb:a811:4b8b:7ea3]/art)|No|No| No | No | No | Russia |
|
||||||
|[clovius.club](https://skunky.clovius.club)|No|No|No| Yes | Yes | No | Sweden |
|
|[clovius.club](https://skunky.clovius.club)|No|No|No| Yes | Yes | No | Sweden |
|
||||||
|[bloat.cat](https://skunky.bloat.cat)|No|No|No| Yes | Yes | No | Germany |
|
|[bloat.cat](https://skunky.bloat.cat)|No|No|No| Yes | Yes | No | Germany |
|
||||||
|[frontendfriendly.xyz](https://skunkyart.frontendfriendly.xyz)|No|No|No| Yes | Yes | No | Finland |
|
|[lumaeris.com](https://skunkyart.lumaeris.com)|No|No|No| Yes | Yes | No | Germany |
|
||||||
|[lumaeris.com](https://skunkyart.lumaeris.com)|No|No|No| Yes | Yes | No | US |
|
|[art.bloat.cat](https://art.bloat.cat)|No|No|No| Yes | Yes | No | Germany |
|
||||||
|
2
TODO.md
2
TODO.md
@ -13,7 +13,7 @@
|
|||||||
* **Реализовать отображение контента, отличного от картинок (видео, аудио, etc)**
|
* **Реализовать отображение контента, отличного от картинок (видео, аудио, etc)**
|
||||||
* Исправить баг с эмоджи, когда некоторые кастомные эмоции могут не отображаться
|
* Исправить баг с эмоджи, когда некоторые кастомные эмоции могут не отображаться
|
||||||
* ~~Добавить аргумент &filename, который будет выдавать файл с нормально выглядещем именем~~ ✔️
|
* ~~Добавить аргумент &filename, который будет выдавать файл с нормально выглядещем именем~~ ✔️
|
||||||
* ~~Улучшить систему кеширования: добавить рейтинг для удаления и копирование изображений в ОЗУ~~
|
* ~~Улучшить систему кеширования: добавить рейтинг для удаления и копирование изображений в ОЗУ~~ BUG: почему-то всё переодически встаёт раком
|
||||||
# v1.4
|
# v1.4
|
||||||
* Реализовать API
|
* Реализовать API
|
||||||
* Реализовать темы
|
* Реализовать темы
|
||||||
|
34
app/api.go
Normal file
34
app/api.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.macaw.me/skunky/devianter"
|
||||||
|
)
|
||||||
|
|
||||||
|
type API struct {
|
||||||
|
skunkyartLink *skunkyart
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a API) sendMedia(d *devianter.Deviation) {
|
||||||
|
mediaUrl, name := devianter.UrlFromMedia(d.Media)
|
||||||
|
|
||||||
|
var filename strings.Builder
|
||||||
|
filename.WriteString(`filename="`)
|
||||||
|
filename.WriteString(name)
|
||||||
|
filename.WriteString(`"`)
|
||||||
|
a.skunkyartLink.Writer.Header().Add("Content-Disposition", filename.String())
|
||||||
|
|
||||||
|
if len(mediaUrl) != 0 {
|
||||||
|
mediaUrl = mediaUrl[21:]
|
||||||
|
dot := strings.Index(mediaUrl, ".")
|
||||||
|
a.skunkyartLink.DownloadAndSendMedia(mediaUrl[:dot], mediaUrl[dot+11:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a API) Random() {
|
||||||
|
s, err := devianter.PerformSearch(string(rand.Intn(999)), rand.Intn(30), 'a')
|
||||||
|
try(err)
|
||||||
|
a.sendMedia(&s.Results[rand.Intn(len(s.Results))])
|
||||||
|
}
|
29
app/cache.go
29
app/cache.go
@ -26,8 +26,10 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) {
|
|||||||
url.WriteString(subdomain)
|
url.WriteString(subdomain)
|
||||||
url.WriteString(".wixmp.com/")
|
url.WriteString(".wixmp.com/")
|
||||||
url.WriteString(path)
|
url.WriteString(path)
|
||||||
url.WriteString("?token=")
|
if t := s.Args.Get("token"); t != "" {
|
||||||
url.WriteString(s.Args.Get("token"))
|
url.WriteString("?token=")
|
||||||
|
url.WriteString(t)
|
||||||
|
}
|
||||||
|
|
||||||
var response []byte
|
var response []byte
|
||||||
|
|
||||||
@ -40,17 +42,18 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) {
|
|||||||
if tempFS[fileName] == nil {
|
if tempFS[fileName] == nil {
|
||||||
tempFS[fileName] = &file{}
|
tempFS[fileName] = &file{}
|
||||||
}
|
}
|
||||||
f := *tempFS[fileName]
|
|
||||||
mx.Unlock()
|
mx.Unlock()
|
||||||
|
|
||||||
if f.Content != nil {
|
if tempFS[fileName].Content != nil {
|
||||||
f.Score += 2
|
response = tempFS[fileName].Content
|
||||||
|
tempFS[fileName].Score += 2
|
||||||
|
break
|
||||||
} else {
|
} else {
|
||||||
file, err := os.Open(filePath)
|
file, err := os.Open(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if dwnld := Download(url.String()); dwnld.Status == 200 && dwnld.Headers["Content-Type"][0][:5] == "image" {
|
if dwnld := Download(url.String()); dwnld.Status == 200 && dwnld.Headers["Content-Type"][0][:5] == "image" {
|
||||||
f.Content = dwnld.Body
|
response = dwnld.Body
|
||||||
try(os.WriteFile(filePath, f.Content, 0700))
|
try(os.WriteFile(filePath, response, 0700))
|
||||||
} else {
|
} else {
|
||||||
s.ReturnHTTPError(dwnld.Status)
|
s.ReturnHTTPError(dwnld.Status)
|
||||||
return
|
return
|
||||||
@ -58,11 +61,16 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) {
|
|||||||
} else {
|
} else {
|
||||||
file, e := io.ReadAll(file)
|
file, e := io.ReadAll(file)
|
||||||
try(e)
|
try(e)
|
||||||
f.Content = file
|
response = file
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer restore()
|
defer restore()
|
||||||
|
|
||||||
|
mx.RLock()
|
||||||
|
tempFS[fileName].Content = response
|
||||||
|
mx.RUnlock()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
time.Sleep(1 * time.Minute)
|
time.Sleep(1 * time.Minute)
|
||||||
|
|
||||||
@ -77,11 +85,6 @@ func (s skunkyart) DownloadAndSendMedia(subdomain, path string) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
mx.Lock()
|
|
||||||
tempFS[fileName] = &f
|
|
||||||
mx.Unlock()
|
|
||||||
response = f.Content
|
|
||||||
case CFG.Proxy:
|
case CFG.Proxy:
|
||||||
dwnld := Download(url.String())
|
dwnld := Download(url.String())
|
||||||
if dwnld.Status != 200 {
|
if dwnld.Status != 200 {
|
||||||
|
@ -82,8 +82,9 @@ func (s skunkyart) DeviationList(devs []devianter.Deviation, allowAtom bool, con
|
|||||||
|
|
||||||
for i, l := 0, len(devs); i < l; i++ {
|
for i, l := 0, len(devs); i < l; i++ {
|
||||||
data := &devs[i]
|
data := &devs[i]
|
||||||
if preview, fullview := ParseMedia(data.Media, data.Title, 320), ParseMedia(data.Media, data.Title); !(data.NSFW && !CFG.Nsfw) {
|
if preview, fullview := ParseMedia(data.Media, 320), ParseMedia(data.Media); !(data.NSFW && !CFG.Nsfw) {
|
||||||
if allowAtom && s.Atom {
|
if allowAtom && s.Atom {
|
||||||
|
s.Writer.Header().Add("Content-type", "application/atom+xml")
|
||||||
id := strconv.Itoa(data.ID)
|
id := strconv.Itoa(data.ID)
|
||||||
listContent.WriteString(`<entry><author><name>`)
|
listContent.WriteString(`<entry><author><name>`)
|
||||||
listContent.WriteString(data.Author.Username)
|
listContent.WriteString(data.Author.Username)
|
||||||
@ -183,6 +184,7 @@ type text struct {
|
|||||||
To int
|
To int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// переписать весь этот пиздец нахуй
|
||||||
func ParseDescription(dscr devianter.Text) string {
|
func ParseDescription(dscr devianter.Text) string {
|
||||||
var parsedDescription strings.Builder
|
var parsedDescription strings.Builder
|
||||||
TagBuilder := func(content string, tags ...string) string {
|
TagBuilder := func(content string, tags ...string) string {
|
||||||
@ -286,7 +288,7 @@ func ParseDescription(dscr devianter.Text) string {
|
|||||||
parsedDescription.WriteString(`<a href="`)
|
parsedDescription.WriteString(`<a href="`)
|
||||||
parsedDescription.WriteString(ConvertDeviantArtUrlToSkunkyArt(d.Url))
|
parsedDescription.WriteString(ConvertDeviantArtUrlToSkunkyArt(d.Url))
|
||||||
parsedDescription.WriteString(`"><img width="50%" src="`)
|
parsedDescription.WriteString(`"><img width="50%" src="`)
|
||||||
parsedDescription.WriteString(ParseMedia(d.Media, d.Title))
|
parsedDescription.WriteString(ParseMedia(d.Media))
|
||||||
parsedDescription.WriteString(`" title="`)
|
parsedDescription.WriteString(`" title="`)
|
||||||
parsedDescription.WriteString(d.Author.Username)
|
parsedDescription.WriteString(d.Author.Username)
|
||||||
parsedDescription.WriteString(" - ")
|
parsedDescription.WriteString(" - ")
|
||||||
|
@ -83,13 +83,15 @@ func Router() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
skunky.Endpoint = path[1]
|
skunky.Endpoint = path[1]
|
||||||
|
skunky.API.skunkyartLink = &skunky
|
||||||
|
|
||||||
// пути
|
// пути
|
||||||
switch skunky.Endpoint {
|
switch skunky.Endpoint {
|
||||||
default:
|
default:
|
||||||
skunky.ReturnHTTPError(404)
|
skunky.ReturnHTTPError(404)
|
||||||
|
|
||||||
case "":
|
case "":
|
||||||
w.Write(open("html/index.htm"))
|
skunky.ExecuteTemplate("index.htm", "html", &CFG.URI)
|
||||||
case "post":
|
case "post":
|
||||||
skunky.Deviation(path[2], path[3])
|
skunky.Deviation(path[2], path[3])
|
||||||
case "search":
|
case "search":
|
||||||
@ -120,6 +122,12 @@ func Router() {
|
|||||||
w.Write(open("css/skunky.css"))
|
w.Write(open("css/skunky.css"))
|
||||||
case "favicon.ico":
|
case "favicon.ico":
|
||||||
w.Write(open("images/logo.png"))
|
w.Write(open("images/logo.png"))
|
||||||
|
|
||||||
|
case "api":
|
||||||
|
switch path[2] {
|
||||||
|
case "random":
|
||||||
|
skunky.API.Random()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +63,8 @@ type skunkyart struct {
|
|||||||
BasePath, Endpoint string
|
BasePath, Endpoint string
|
||||||
Query, QueryRaw string
|
Query, QueryRaw string
|
||||||
|
|
||||||
|
API API
|
||||||
|
|
||||||
Templates struct {
|
Templates struct {
|
||||||
About struct {
|
About struct {
|
||||||
Proxy bool
|
Proxy bool
|
||||||
@ -182,13 +184,12 @@ func Download(urlString string) (d Downloaded) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* PARSING HELPERS */
|
/* PARSING HELPERS */
|
||||||
func ParseMedia(media devianter.Media, filename string, thumb ...int) string {
|
func ParseMedia(media devianter.Media, thumb ...int) string {
|
||||||
mediaUrl := devianter.UrlFromMedia(media, thumb...)
|
mediaUrl, filename := devianter.UrlFromMedia(media, thumb...)
|
||||||
if len(mediaUrl) != 0 && CFG.Proxy {
|
if len(mediaUrl) != 0 && CFG.Proxy {
|
||||||
mediaUrl = mediaUrl[21:]
|
mediaUrl = mediaUrl[21:]
|
||||||
dot := strings.Index(mediaUrl, ".")
|
dot := strings.Index(mediaUrl, ".")
|
||||||
|
return UrlBuilder("media", "file", mediaUrl[:dot], mediaUrl[dot+11:], "&filename=", filename)
|
||||||
return UrlBuilder("media", "file", mediaUrl[:dot], mediaUrl[dot+11:], "&filename=", url.QueryEscape(filename))
|
|
||||||
}
|
}
|
||||||
return mediaUrl
|
return mediaUrl
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ func (s skunkyart) GRUser() {
|
|||||||
case "cover_deviation":
|
case "cover_deviation":
|
||||||
group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
|
group.About.BGMeta = x.ModuleData.CoverDeviation.Deviation
|
||||||
group.About.BGMeta.Url = ConvertDeviantArtUrlToSkunkyArt(group.About.BGMeta.Url)
|
group.About.BGMeta.Url = ConvertDeviantArtUrlToSkunkyArt(group.About.BGMeta.Url)
|
||||||
group.About.BG = ParseMedia(group.About.BGMeta.Media, group.About.BGMeta.Title)
|
group.About.BG = ParseMedia(group.About.BGMeta.Media)
|
||||||
case "group_admins":
|
case "group_admins":
|
||||||
var htm strings.Builder
|
var htm strings.Builder
|
||||||
for _, z := range x.ModuleData.GroupAdmins.Results {
|
for _, z := range x.ModuleData.GroupAdmins.Results {
|
||||||
@ -122,7 +122,7 @@ func (s skunkyart) GRUser() {
|
|||||||
folders.WriteString(`<a href="`)
|
folders.WriteString(`<a href="`)
|
||||||
folders.WriteString(ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url))
|
folders.WriteString(ConvertDeviantArtUrlToSkunkyArt(x.Thumb.Url))
|
||||||
folders.WriteString(`"><img loading="lazy" src="`)
|
folders.WriteString(`"><img loading="lazy" src="`)
|
||||||
folders.WriteString(ParseMedia(x.Thumb.Media, x.Thumb.Title))
|
folders.WriteString(ParseMedia(x.Thumb.Media))
|
||||||
folders.WriteString(`" title="`)
|
folders.WriteString(`" title="`)
|
||||||
folders.WriteString(x.Thumb.Title)
|
folders.WriteString(x.Thumb.Title)
|
||||||
folders.WriteString(`"></a>`)
|
folders.WriteString(`"></a>`)
|
||||||
@ -185,7 +185,7 @@ func (s skunkyart) Deviation(author, postname string) {
|
|||||||
}
|
}
|
||||||
// время публикации
|
// время публикации
|
||||||
post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
|
post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
|
||||||
post.Post.IMG = ParseMedia(post.Post.Deviation.Media, post.Post.Deviation.Title)
|
post.Post.IMG = ParseMedia(post.Post.Deviation.Media)
|
||||||
for _, x := range post.Post.Deviation.Extended.RelatedContent {
|
for _, x := range post.Post.Deviation.Extended.RelatedContent {
|
||||||
if len(x.Deviations) != 0 {
|
if len(x.Deviations) != 0 {
|
||||||
post.Related += s.DeviationList(x.Deviations, false)
|
post.Related += s.DeviationList(x.Deviations, false)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"listen": "0:3003",
|
"listen": "0.0.0.0:3003",
|
||||||
"uri": "/",
|
"uri": "/huy/",
|
||||||
"cache": {
|
"cache": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"path": "cache",
|
"path": "cache",
|
||||||
|
4
go.mod
4
go.mod
@ -1,8 +1,8 @@
|
|||||||
module skunkyart
|
module skunkyart
|
||||||
|
|
||||||
go 1.22.3
|
go 1.18
|
||||||
|
|
||||||
replace git.macaw.me/skunky/devianter v0.2.5 => /home/skunk/projects/devianter
|
// replace git.macaw.me/skunky/devianter v0.2.5 => /home/skunk/projects/devianter
|
||||||
require (
|
require (
|
||||||
git.macaw.me/skunky/devianter v0.2.5
|
git.macaw.me/skunky/devianter v0.2.5
|
||||||
golang.org/x/net v0.27.0
|
golang.org/x/net v0.27.0
|
||||||
|
@ -35,10 +35,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "frontendfriendly.xyz",
|
"title": "lumaeris.com",
|
||||||
"country": "Finland",
|
"country": "Germany",
|
||||||
"urls": {
|
"urls": {
|
||||||
"clearnet": "https://skunkyart.frontendfriendly.xyz"
|
"clearnet": "https://skunkyart.lumaeris.com"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"nsfw": true,
|
"nsfw": true,
|
||||||
@ -46,10 +46,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "lumaeris.com",
|
"title": "art.bloat.cat",
|
||||||
"country": "US",
|
"country": "Germany",
|
||||||
"urls": {
|
"urls": {
|
||||||
"clearnet": "https://skunkyart.lumaeris.com"
|
"clearnet": "https://art.bloat.cat"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"nsfw": true,
|
"nsfw": true,
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>SkunkyArt</title>
|
<title>SkunkyArt</title>
|
||||||
<link rel="stylesheet" href="stylesheet"/>
|
<link rel="stylesheet" href="{{.}}stylesheet"/>
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<link rel="icon" type="image/x-icon" href="{{.}}favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<main>
|
<main>
|
||||||
<center>
|
<center>
|
||||||
<form method="get" action="search">
|
<form method="get" action="{{.}}search">
|
||||||
<input type="text" name="q" placeholder="Search for ..." autocomplete="off" autocapitalize="none" spellcheck="false">
|
<input type="text" name="q" placeholder="Search for ..." autocomplete="off" autocapitalize="none" spellcheck="false">
|
||||||
<select name="type">
|
<select name="type">
|
||||||
<option value="all">All</option>
|
<option value="all">All</option>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
</select>
|
</select>
|
||||||
<button type="submit">Search!</button>
|
<button type="submit">Search!</button>
|
||||||
</form>
|
</form>
|
||||||
<h1><a href="dd">Daily Deviations</a> | <a href="about">About</a> | <a href="https://git.macaw.me/skunky/SkunkyArt" target="_blank">Source Code</a></h1>
|
<h1><a href="{{.}}dd">Daily Deviations</a> | <a href="{{.}}about">About</a> | <a href="https://git.macaw.me/skunky/SkunkyArt" target="_blank">Source Code</a></h1>
|
||||||
</center>
|
</center>
|
||||||
</main>
|
</main>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user