mirror of
https://git.macaw.me/skunky/SkunkyArt.git
synced 2025-04-28 03:55:07 +03:00
v1.3
This commit is contained in:
parent
2dfeaae772
commit
c5514c3875
23 changed files with 445 additions and 249 deletions
166
app/cli.go
Normal file
166
app/cli.go
Normal file
|
@ -0,0 +1,166 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ExecuteCommandLineArguments() {
|
||||
const helpmsg = `SkunkyArt v1.3.1 [CSS improvements for mobile and the strips on Daily Deviations]
|
||||
Usage:
|
||||
- [-c|--config] | path to config
|
||||
- [-a|--add-instance] | generates 'instances.json' and 'INSTANCES.md' files with ur instance
|
||||
- [-h|--help] | returns this message
|
||||
Example:
|
||||
./skunkyart -c config.json
|
||||
Copyright lost+skunk, X11. https://git.macaw.me/skunky/skunkyart/src/tag/v1.3.1`
|
||||
|
||||
a := os.Args[1:]
|
||||
for n, x := range a {
|
||||
switch x {
|
||||
case "-c", "--config":
|
||||
if len(a) >= 2 {
|
||||
CFG.cfg = a[n+1]
|
||||
} else {
|
||||
exit("Not enought arguments", 1)
|
||||
}
|
||||
case "-h", "--help":
|
||||
exit(helpmsg, 0)
|
||||
case "-a", "--add-instance":
|
||||
addInstance()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type settingsUrls struct {
|
||||
I2P string `json:"i2p,omitempty"`
|
||||
Ygg string `json:"ygg,omitempty"`
|
||||
Tor string `json:"tor,omitempty"`
|
||||
Clearnet string `json:"clearnet,omitempty"`
|
||||
}
|
||||
|
||||
type settingsParams struct {
|
||||
Nsfw bool `json:"nsfw"`
|
||||
Proxy bool `json:"proxy"`
|
||||
}
|
||||
|
||||
type settings struct {
|
||||
Title string `json:"title"`
|
||||
Country string `json:"country"`
|
||||
ModifiedSrc string `json:"modified-src,omitempty"`
|
||||
Urls settingsUrls `json:"urls"`
|
||||
Settings settingsParams `json:"settings"`
|
||||
}
|
||||
|
||||
func addInstance() {
|
||||
prompt := func(txt string, necessary bool) string {
|
||||
input := bufio.NewScanner(os.Stdin)
|
||||
for {
|
||||
print(txt)
|
||||
print(": ")
|
||||
input.Scan()
|
||||
|
||||
if i := input.Text(); necessary && i == "" {
|
||||
println("Please specify the", txt)
|
||||
} else {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var settingsVar struct {
|
||||
Instances []settings `json:"instances"`
|
||||
}
|
||||
instancesJson, err := os.OpenFile("instances.test.json", os.O_CREATE|os.O_WRONLY, 0644)
|
||||
try(err)
|
||||
defer instancesJson.Close()
|
||||
|
||||
instances, err := os.OpenFile("INSTANCES.md", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
try(err)
|
||||
defer instances.Close()
|
||||
|
||||
for {
|
||||
if Templates["instances.json"] == "" {
|
||||
print("\rDownloading instance list...")
|
||||
} else {
|
||||
println("\r\033[2KDownloaded!")
|
||||
try(json.Unmarshal([]byte(Templates["instances.json"]), &settingsVar))
|
||||
|
||||
settingsVar.Instances = append(settingsVar.Instances, settings{
|
||||
Title: prompt("Title", true),
|
||||
Country: prompt("Country", true),
|
||||
ModifiedSrc: prompt("Link to modified sources", false),
|
||||
Settings: settingsParams{
|
||||
Nsfw: CFG.Nsfw,
|
||||
Proxy: CFG.Proxy,
|
||||
},
|
||||
Urls: settingsUrls{
|
||||
Clearnet: prompt("Clearnet link", false),
|
||||
Ygg: prompt("Yggdrasil link", false),
|
||||
Tor: prompt("Onion link", false),
|
||||
I2P: prompt("I2P link", false),
|
||||
},
|
||||
})
|
||||
|
||||
j, err := json.MarshalIndent(&settingsVar, "", " ")
|
||||
try(err)
|
||||
|
||||
instancesJson.Write(j)
|
||||
|
||||
settingsVar := &settingsVar.Instances[len(settingsVar.Instances)-1]
|
||||
var mdstr bytes.Buffer
|
||||
|
||||
mdstr.WriteString("\n|")
|
||||
if settingsVar.Urls.Clearnet != "" {
|
||||
mdstr.WriteString("[")
|
||||
mdstr.WriteString(settingsVar.Title)
|
||||
mdstr.WriteString("](")
|
||||
mdstr.WriteString(settingsVar.Urls.Clearnet)
|
||||
mdstr.WriteString(")")
|
||||
} else {
|
||||
mdstr.WriteString(settingsVar.Title)
|
||||
}
|
||||
mdstr.WriteString("|")
|
||||
|
||||
urls := []string{settingsVar.Urls.Ygg, settingsVar.Urls.I2P, settingsVar.Urls.Tor}
|
||||
for i, l := 0, len(urls); i < l; i++ {
|
||||
url := urls[i]
|
||||
if url != "" {
|
||||
mdstr.WriteString("[Yes](")
|
||||
mdstr.WriteString(url)
|
||||
mdstr.WriteString(")|")
|
||||
} else {
|
||||
mdstr.WriteString("No|")
|
||||
}
|
||||
}
|
||||
|
||||
settings := []bool{settingsVar.Settings.Nsfw, settingsVar.Settings.Proxy}
|
||||
for i, l := 0, len(settings); i < l; i++ {
|
||||
if settings[i] {
|
||||
mdstr.WriteString("Yes|")
|
||||
} else {
|
||||
mdstr.WriteString("No|")
|
||||
}
|
||||
}
|
||||
|
||||
if settingsVar.ModifiedSrc != "" {
|
||||
mdstr.WriteString("[Yes](")
|
||||
mdstr.WriteString(settingsVar.ModifiedSrc)
|
||||
mdstr.WriteString(")|")
|
||||
} else {
|
||||
mdstr.WriteString("No|")
|
||||
}
|
||||
|
||||
mdstr.WriteString(settingsVar.Country)
|
||||
mdstr.WriteString("|")
|
||||
|
||||
instances.Write(mdstr.Bytes())
|
||||
break
|
||||
}
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
exit("Done! Now add the files 'instances.json' and 'INSTANCES.md' to the 'master' branch in the repository https://git.macaw.me/skunky/SkunkyArt", 0)
|
||||
}
|
|
@ -21,7 +21,7 @@ type cache_config struct {
|
|||
type config struct {
|
||||
cfg string
|
||||
Listen string
|
||||
BasePath string `json:"base-path"`
|
||||
URI string `json:"uri"`
|
||||
Cache cache_config
|
||||
Proxy, Nsfw bool
|
||||
UserAgent string `json:"user-agent"`
|
||||
|
@ -30,15 +30,15 @@ type config struct {
|
|||
}
|
||||
|
||||
var CFG = config{
|
||||
cfg: "config.json",
|
||||
Listen: "127.0.0.1:3003",
|
||||
BasePath: "/",
|
||||
cfg: "config.json",
|
||||
Listen: "127.0.0.1:3003",
|
||||
URI: "/",
|
||||
Cache: cache_config{
|
||||
Enabled: true,
|
||||
Enabled: false,
|
||||
Path: "cache",
|
||||
UpdateInterval: 1,
|
||||
},
|
||||
Dirs: []string{"html", "css"},
|
||||
Dirs: []string{"html", "css", "misc"},
|
||||
UserAgent: "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,
|
||||
|
@ -47,42 +47,6 @@ var CFG = config{
|
|||
var lifetimeParsed int64
|
||||
|
||||
func ExecuteConfig() {
|
||||
go func() {
|
||||
for {
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
recover()
|
||||
}
|
||||
}()
|
||||
Templates["instances.json"] = string(Download("https://git.macaw.me/skunky/SkunkyArt/raw/branch/master/instances.json").Body)
|
||||
}()
|
||||
time.Sleep(1 * time.Hour)
|
||||
}
|
||||
}()
|
||||
|
||||
const helpmsg = `SkunkyArt v1.3.1 [CSS improvements for mobile and strips on Daily Deviations]
|
||||
Usage:
|
||||
- [-c|--config] - path to config
|
||||
- [-h|--help] - returns this message
|
||||
Example:
|
||||
./skunkyart -c config.json
|
||||
Copyright lost+skunk, X11. https://git.macaw.me/skunky/skunkyart/src/tag/v1.3.1`
|
||||
|
||||
a := os.Args
|
||||
for n, x := range a {
|
||||
switch x {
|
||||
case "-c", "--config":
|
||||
if len(a) >= 3 {
|
||||
CFG.cfg = a[n+1]
|
||||
} else {
|
||||
exit("Not enought arguments", 1)
|
||||
}
|
||||
case "-h", "--help":
|
||||
exit(helpmsg, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if CFG.cfg != "" {
|
||||
f, err := os.ReadFile(CFG.cfg)
|
||||
tryWithExitStatus(err, 1)
|
||||
|
|
|
@ -11,7 +11,7 @@ var Host string
|
|||
|
||||
func Router() {
|
||||
parsepath := func(path string) map[int]string {
|
||||
if l := len(CFG.BasePath); len(path) > l {
|
||||
if l := len(CFG.URI); len(path) > l {
|
||||
path = path[l-1:]
|
||||
} else {
|
||||
path = "/"
|
||||
|
@ -54,7 +54,7 @@ func Router() {
|
|||
var skunky skunkyart
|
||||
skunky.Writer = w
|
||||
skunky.Args = r.URL.Query()
|
||||
skunky.BasePath = CFG.BasePath
|
||||
skunky.BasePath = CFG.URI
|
||||
|
||||
arg := skunky.Args.Get
|
||||
skunky.QueryRaw = arg("q")
|
||||
|
@ -75,7 +75,7 @@ func Router() {
|
|||
default:
|
||||
skunky.ReturnHTTPError(404)
|
||||
case "":
|
||||
skunky.ExecuteTemplate("index.htm", &CFG.BasePath)
|
||||
skunky.ExecuteTemplate("index.htm", &CFG.URI)
|
||||
case "post":
|
||||
skunky.Deviation(path[2], path[3])
|
||||
case "search":
|
||||
|
|
23
app/util.go
23
app/util.go
|
@ -32,6 +32,20 @@ func tryWithExitStatus(err error, code int) {
|
|||
}
|
||||
}
|
||||
|
||||
func RefreshInstances() {
|
||||
for {
|
||||
func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
recover()
|
||||
}
|
||||
}()
|
||||
Templates["instances.json"] = string(Download("https://git.macaw.me/skunky/SkunkyArt/raw/branch/master/instances.json").Body)
|
||||
}()
|
||||
time.Sleep(1 * time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
// some crap for frontend
|
||||
func (s skunkyart) ExecuteTemplate(file string, data any) {
|
||||
var buf strings.Builder
|
||||
|
@ -46,7 +60,7 @@ func UrlBuilder(strs ...string) string {
|
|||
var str strings.Builder
|
||||
l := len(strs)
|
||||
str.WriteString(Host)
|
||||
str.WriteString(CFG.BasePath)
|
||||
str.WriteString(CFG.URI)
|
||||
for n, x := range strs {
|
||||
str.WriteString(x)
|
||||
if n+1 < l && !(strs[n+1][0] == '?' || strs[n+1][0] == '&') && !(x[0] == '?' || x[0] == '&') {
|
||||
|
@ -220,11 +234,10 @@ func BuildUserPlate(name string) string {
|
|||
|
||||
func GetValueOfTag(t *html.Tokenizer) string {
|
||||
for tt := t.Next(); ; {
|
||||
switch tt {
|
||||
default:
|
||||
return ""
|
||||
case html.TextToken:
|
||||
if tt == html.TextToken {
|
||||
return string(t.Text())
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
112
app/wrapper.go
112
app/wrapper.go
|
@ -31,20 +31,7 @@ type skunkyart struct {
|
|||
About struct {
|
||||
Proxy bool
|
||||
Nsfw bool
|
||||
Instances []struct {
|
||||
Title string
|
||||
Country string
|
||||
Urls []struct {
|
||||
I2P string `json:"i2p"`
|
||||
Ygg string
|
||||
Tor string
|
||||
Clearnet string
|
||||
}
|
||||
Settings struct {
|
||||
Nsfw bool
|
||||
Proxy bool
|
||||
}
|
||||
}
|
||||
Instances []settings
|
||||
}
|
||||
|
||||
SomeList string
|
||||
|
@ -229,48 +216,49 @@ func (s skunkyart) GRUser() {
|
|||
// посты
|
||||
func (s skunkyart) Deviation(author, postname string) {
|
||||
id_search := regexp.MustCompile("[0-9]+").FindAllString(postname, -1)
|
||||
if len(id_search) >= 1 {
|
||||
post := &s.Templates.Deviation
|
||||
|
||||
id := id_search[len(id_search)-1]
|
||||
post.Post = devianter.GetDeviation(id, author)
|
||||
|
||||
if post.Post.Deviation.TextContent.Excerpt != "" {
|
||||
post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
|
||||
} else {
|
||||
post.Post.Description = ParseDescription(post.Post.Deviation.Extended.DescriptionText)
|
||||
}
|
||||
// время публикации
|
||||
post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
|
||||
post.Post.IMG = ParseMedia(post.Post.Deviation.Media)
|
||||
for _, x := range post.Post.Deviation.Extended.RelatedContent {
|
||||
if len(x.Deviations) != 0 {
|
||||
post.Related += s.DeviationList(x.Deviations, false)
|
||||
}
|
||||
}
|
||||
|
||||
// хештэги
|
||||
for _, x := range post.Post.Deviation.Extended.Tags {
|
||||
var tag strings.Builder
|
||||
tag.WriteString(` <a href="`)
|
||||
tag.WriteString(UrlBuilder("search", "?q=", x.Name, "&type=tag"))
|
||||
tag.WriteString(`">#`)
|
||||
tag.WriteString(x.Name)
|
||||
tag.WriteString("</a>")
|
||||
|
||||
post.Tags += tag.String()
|
||||
}
|
||||
|
||||
if post.Post.Comments.Total <= 50 {
|
||||
post.Post.Comments.Cursor = ""
|
||||
}
|
||||
|
||||
post.Comments = s.ParseComments(devianter.GetComments(id, post.Post.Comments.Cursor, s.Page, 1))
|
||||
|
||||
s.ExecuteTemplate("deviantion.htm", &s)
|
||||
} else {
|
||||
if len(id_search) < 1 {
|
||||
s.ReturnHTTPError(400)
|
||||
return
|
||||
}
|
||||
|
||||
post := &s.Templates.Deviation
|
||||
|
||||
id := id_search[len(id_search)-1]
|
||||
post.Post = devianter.GetDeviation(id, author)
|
||||
|
||||
if post.Post.Deviation.TextContent.Excerpt != "" {
|
||||
post.Post.Description = ParseDescription(post.Post.Deviation.TextContent)
|
||||
} else {
|
||||
post.Post.Description = ParseDescription(post.Post.Deviation.Extended.DescriptionText)
|
||||
}
|
||||
// время публикации
|
||||
post.StringTime = post.Post.Deviation.PublishedTime.UTC().String()
|
||||
post.Post.IMG = ParseMedia(post.Post.Deviation.Media)
|
||||
for _, x := range post.Post.Deviation.Extended.RelatedContent {
|
||||
if len(x.Deviations) != 0 {
|
||||
post.Related += s.DeviationList(x.Deviations, false)
|
||||
}
|
||||
}
|
||||
|
||||
// хештэги
|
||||
for _, x := range post.Post.Deviation.Extended.Tags {
|
||||
var tag strings.Builder
|
||||
tag.WriteString(` <a href="`)
|
||||
tag.WriteString(UrlBuilder("search", "?q=", x.Name, "&type=tag"))
|
||||
tag.WriteString(`">#`)
|
||||
tag.WriteString(x.Name)
|
||||
tag.WriteString("</a>")
|
||||
|
||||
post.Tags += tag.String()
|
||||
}
|
||||
|
||||
if post.Post.Comments.Total <= 50 {
|
||||
post.Post.Comments.Cursor = ""
|
||||
}
|
||||
|
||||
post.Comments = s.ParseComments(devianter.GetComments(id, post.Post.Comments.Cursor, s.Page, 1))
|
||||
|
||||
s.ExecuteTemplate("deviantion.htm", &s)
|
||||
}
|
||||
|
||||
func (s skunkyart) DD() {
|
||||
|
@ -298,7 +286,6 @@ func (s skunkyart) DD() {
|
|||
}
|
||||
|
||||
func (s skunkyart) Search() {
|
||||
s.Atom = false
|
||||
var err error
|
||||
ss := &s.Templates.Search
|
||||
switch s.Type {
|
||||
|
@ -365,15 +352,16 @@ func (s skunkyart) Search() {
|
|||
}
|
||||
|
||||
func (s skunkyart) Emojitar(name string) {
|
||||
if name != "" && (s.Type == 'a' || s.Type == 'e') {
|
||||
ae, e := devianter.AEmedia(name, s.Type)
|
||||
if e != nil {
|
||||
s.ReturnHTTPError(404)
|
||||
}
|
||||
wr(s.Writer, ae)
|
||||
} else {
|
||||
if name == "" || !(s.Type == 'a' || s.Type == 'e') {
|
||||
s.ReturnHTTPError(400)
|
||||
return
|
||||
}
|
||||
|
||||
ae, e := devianter.AEmedia(name, s.Type)
|
||||
if e != nil {
|
||||
s.ReturnHTTPError(404)
|
||||
}
|
||||
wr(s.Writer, ae)
|
||||
}
|
||||
|
||||
func (s skunkyart) About() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue