diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6b41092
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+X11 License
+
+Copyright (C) 1996 X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium.
+
+X Window System is a trademark of X Consortium, Inc.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..57090ee
--- /dev/null
+++ b/README.md
@@ -0,0 +1,76 @@
+[]("https://go.kde.org/matrix/#/#skunkyart:ebloid.ru")
+# Instances
+|Инстанс|Yggdrasil|I2P|Tor|NSFW|Proxifying|Country|
+|:-----:|:-------:|:-:|:-:|:--:|:--------:|:-----:|
+|[skunky.ebloid.ru](https://skunky.ebloid.ru/art)|[Yes](http://[201:eba5:d1fc:bf7b:cfcb:a811:4b8b:7ea3]/art)|No|No| No | No | Russia |
+|[clovius.club](https://skunky.clovius.club)|No|No|No| Yes | Yes | Sweden |
+|[bloat.cat](https://skunky.bloat.cat)|No|No|No| Yes | Yes | Romania |
+|[frontendfriendly.xyz](https://skunkyart.frontendfriendly.xyz)|No|No|No| Yes | Yes | Finland |
+
+# EN 🇺🇸
+## Description
+SkunkyArt 🦨 -- alternative frontend to DeviantArt, which will work without problems even on quite old hardware, due to the lack of JavaScript.
+## Config
+The sample config is in the `config.example.json` file. To specify your own path to the config, use the CLI argument `-c` or `--config`.
+* `listen` -- the address and port on which SkunkyArt will listen
+* `base-path` -- the path to the instance. Example: "`base-path`:"/art/" -> https://skunky.ebloid.ru/art/
+* `cache` -- caching system; default is off.
+* * `path` -- the path to the cache
+* * `lifetime` -- cache file lifetime; measured in Unix milliseconds.
+* * `max-size` -- maximum file size in bytes.
+* `dirs-to-memory` -- this setting determines which directories will be copied to RAM when SkunkyArt is started. Required
+* `download-proxy` -- proxy address for downloading files.
+## Examples of reverse proxies
+Nginx:
+```apache
+server {
+ listen 443 ssl;
+ server_name skunky.example.com;
+
+ location ((BASE URL)) { # if you have a separate subdomain for the frontend, insert '/' instead of '((BASE URL))'.
+ proxy_set_header Scheme $scheme;
+ proxy_http_version 1.1;
+ proxy_pass http://((IP)):((PORT));
+ }
+}
+```
+## How do I add my instance to the list?
+To do this, you must either make a PR by adding your instance to the `instances.json` file, or report it to the room in Matrix. I don't think it needs any description. However, be aware, this list has a couple rules:
+1. the instance must not use Cloudflare.
+2. If your instance has modified source code, you need to publish it to any free platform. For example, Github and Gitlab are not.
+## Acknowledgements
+* [Лис⚛](https://go.kde.org/matrix/#/@fox:matrix.org) -- helped me understand Go and gave me a lot of useful advice on this language.
+
+# RU 🇷🇺
+## Описание
+SkunkyArt 🦨 -- альтернативный фронтенд к DeviantArt, который будет работать без проблем даже на довольно старом оборудовании, за счёт отсутствия JavaScript.
+## Конфиг
+Пример конфига находится в файле `config.example.json`. Чтобы указать свой путь до конфига, используйте CLI-аргумент `-c` или `--config`.
+* `listen` -- адрес и порт, на котором будет слушать SkunkyArt
+* `base-path` -- путь к инстансу. Пример: "base-path": "/art/" -> https://skunky.ebloid.ru/art/
+* `cache` -- система кеширования; по умолчанию - выкл.
+* * `path` -- путь до кеша
+* * `lifetime` -- время жизни файла в кеше; измеряется в Unix-миллисекундах
+* * `max-size` -- максимальный размер файла в байтах
+* `dirs-to-memory` -- данная настройка определяет какие каталоги будут скопированы в ОЗУ при запуске SkunkyArt. Обязательна
+* `download-proxy` -- адрес прокси для загрузки файлов
+## Примеры reverse-прокси
+Nginx:
+```apache
+server {
+ listen 443 ssl;
+ server_name skunky.example.com;
+
+ location ((BASE URL)) { # если у вас отдельный поддомен для фронтенда, вместо '((BASE URL))' вставляйте '/'
+ proxy_set_header Scheme $scheme;
+ proxy_http_version 1.1;
+ proxy_pass http://((IP)):((PORT));
+ }
+}
+```
+## Как добавить свой инстанс в список?
+Чтобы это сделать, вы должны либо сделать PR, добавив в файл `instances.json` свой инстанс, либо сообщить о нём в комнате в Matrix. Думаю, он не нуждается в описании. Однако учтите, у этого списка есть пара правил:
+1. Инстанс не должен использовать Cloudflare.
+2. Если ваш инстанс имеет модифицированный исходный код, то вам нужно опубликовать его на любую свободную площадку. Например, Github и Gitlab таковыми не являются.
+## Благодарности
+* [Лис⚛](https://go.kde.org/matrix/#/@fox:matrix.org) -- помог разобраться в Go и много чего полезного посоветовал по этому языку.
\ No newline at end of file
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..2334695
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,7 @@
+# v1.3.x
+* Доделать парсинг описания
+* Реализовать миниатюры и оптимизировать CSS под маленькие экраны
+# v1.4
+* Реализовать темы
+* Реализовать многоязычный интерфейс
+* Реализовать API
\ No newline at end of file
diff --git a/app/config.go b/app/config.go
index 18cea29..96aea40 100644
--- a/app/config.go
+++ b/app/config.go
@@ -2,8 +2,8 @@ package app
import (
"encoding/json"
- "errors"
"os"
+ "time"
)
type cache_config struct {
@@ -15,13 +15,13 @@ type cache_config struct {
}
type config struct {
- cfg string
- Listen string
- BasePath string `json:"base-path"`
- Cache cache_config
- Proxy, Nsfw bool
- WixmpProxy string `json:"wixmp-proxy"`
- TemplatesDir string `json:"templates-dir"`
+ cfg string
+ Listen string
+ BasePath string `json:"base-path"`
+ Cache cache_config
+ Proxy, Nsfw bool
+ DownloadProxy string `json:"download-proxy"`
+ Dirs []string `json:"dirs-to-memory"`
}
var CFG = config{
@@ -33,51 +33,52 @@ var CFG = config{
Path: "cache",
UpdateInterval: 1,
},
- TemplatesDir: "html",
- Proxy: true,
- Nsfw: true,
+ Dirs: []string{"html", "css"},
+ Proxy: true,
+ Nsfw: true,
}
func ExecuteConfig() {
- try := func(err error, exitcode int) {
- if err != nil {
- println(err.Error())
- os.Exit(exitcode)
+ go func() {
+ for {
+ Templates["instances.json"] = string(Download("https://git.macaw.me/skunky/SkunkyArt/raw/branch/master/instances.json").Body)
+ time.Sleep(1 * time.Hour)
}
- }
+ }()
- a := os.Args
- if l := len(a); l > 1 {
- switch a[1] {
- case "-c", "--config":
- if l >= 3 {
- CFG.cfg = a[2]
- } else {
- try(errors.New("Not enought arguments"), 1)
- }
- case "-h", "--help":
- try(errors.New(`SkunkyArt v1.3 [refactoring]
+ const helpmsg = `SkunkyArt v1.3 [refactoring]
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`), 0)
- default:
- try(errors.New("Unreconginzed argument: "+a[1]), 1)
+Copyright lost+skunk, X11. https://git.macaw.me/skunky/skunkyart/src/tag/v1.3`
+
+ 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)
- try(err, 1)
+ }
- try(json.Unmarshal(f, &CFG), 1)
- if CFG.Cache.Enabled && !CFG.Proxy {
- try(errors.New("Incompatible settings detected: cannot use caching media content without proxy"), 1)
- }
+ if CFG.cfg != "" {
+ f, err := os.ReadFile(CFG.cfg)
+ try_with_exitstatus(err, 1)
- if CFG.Cache.MaxSize != 0 || CFG.Cache.Lifetime != 0 {
- go InitCacheSystem()
- }
+ try_with_exitstatus(json.Unmarshal(f, &CFG), 1)
+ if CFG.Cache.Enabled && !CFG.Proxy {
+ exit("Incompatible settings detected: cannot use caching media content without proxy", 1)
+ }
+
+ if CFG.Cache.MaxSize != 0 || CFG.Cache.Lifetime != 0 {
+ go InitCacheSystem()
}
}
}
diff --git a/app/parsers.go b/app/parsers.go
new file mode 100644
index 0000000..0665476
--- /dev/null
+++ b/app/parsers.go
@@ -0,0 +1,367 @@
+package app
+
+import (
+ "encoding/json"
+ "strconv"
+ "strings"
+
+ "git.macaw.me/skunky/devianter"
+ "golang.org/x/net/html"
+)
+
+func (s skunkyart) ParseComments(c devianter.Comments) string {
+ var cmmts strings.Builder
+ replied := make(map[int]string)
+
+ cmmts.WriteString("Comments: ")
+ cmmts.WriteString(strconv.Itoa(c.Total))
+ cmmts.WriteString("")
+ for _, x := range c.Thread {
+ replied[x.ID] = x.User.Username
+ cmmts.WriteString(`