Commit b1ad145532
b1ad14553277d9d72a5e4b4462a52a2e2d0fdbb1
parent: 155a7b9ea6
Verified · cmc
cmc <hello@cleberg.net> · 2026-07-15 06:54 UTC
fix: remove russian language throughout
Layout: unified · split
README.md
−40
| @@ -8,7 +8,6 @@ |
| 8 | |
8 | |
| 9 | Instances: [`INSTANCES.md`](INSTANCES.md) |
9 | Instances: [`INSTANCES.md`](INSTANCES.md) |
| 10 | |
10 | |
| 11 | # EN 🇺🇸 |
| |
| 12 | ## Description |
11 | ## Description |
| 13 | SkunkyArt 🦨 — an alternative frontend for DeviantArt that works entirely |
12 | SkunkyArt 🦨 — an alternative frontend for DeviantArt that works entirely |
| 14 | without JavaScript. |
13 | without JavaScript. |
| @@ -32,42 +31,3 @@ To do this, you must either make a PR by adding your instance to the |
| 32 | `instances.json` and `INSTANCES.md` files (you can use `--add-instance` |
31 | `instances.json` and `INSTANCES.md` files (you can use `--add-instance` |
| 33 | cli-argument to automatically add the instance to these files) or create an |
32 | cli-argument to automatically add the instance to these files) or create an |
| 34 | Issue. |
33 | Issue. |
| 35 | |
| |
| 36 | ## Acknowledgements |
| |
| 37 | * [vlnst](https://git.bloat.cat/vlnst) — wrote a Docker file. |
| |
| 38 | * [Лис⚛](https://go.kde.org/matrix/#/@fox:matrix.org) — helped me understand Go |
| |
| 39 | and gave me a lot of useful advice on this language. |
| |
| 40 | * [meoww](https://codeberg.org/meoww) — translated some sentences into English |
| |
| 41 | and wrote a service for openrc |
| |
| 42 | |
| |
| 43 | # RU 🇷🇺 |
| |
| 44 | ## Описание |
| |
| 45 | SkunkyArt 🦨 — альтернативный фронтенд к DeviantArt, который полностью работает |
| |
| 46 | без JS (JavaScript). |
| |
| 47 | |
| |
| 48 | ## Сборка |
| |
| 49 | Рекомендуется производить сборку с тегом 'embed', поскольку он встраивает |
| |
| 50 | заготовки в бинарный файл. Если вы планируете изменять заготовки, то не |
| |
| 51 | используйте этот тег. Также вы можете добавить аргумент `-ldflags "-w -s"` (у |
| |
| 52 | GCCGO он называется по-другому — `gccgoflags`) для уменьшения размера выходного |
| |
| 53 | файла. Вот пример: |
| |
| 54 | |
| |
| 55 | `go build -tags embed -ldflags "-w -s"` |
| |
| 56 | |
| |
| 57 | ## Настройка |
| |
| 58 | Пример конфига находится в файле `config.example.json`. Чтобы указать свой |
| |
| 59 | конфиг, используйте cli-аргумент `--config`. |
| |
| 60 | |
| |
| 61 | См. [`SETUP-RU.md`](SETUP-RU.md) для информации о настройки фронтенда. |
| |
| 62 | |
| |
| 63 | ## Добавление инстанса в список |
| |
| 64 | Чтобы это сделать, вы должны либо сделать PR, добавив в файлы `instances.json` и |
| |
| 65 | `INSTANCES.md` свой инстанс (можете воспользоваться cli-аргументом |
| |
| 66 | `--add-instance`, который автоматически это сделает), либо создать Issue. |
| |
| 67 | |
| |
| 68 | ## Благодарности |
| |
| 69 | * [vlnst](https://git.bloat.cat/vlnst) — написал Docker-файл. |
| |
| 70 | * [Лис⚛](https://go.kde.org/matrix/#/@fox:matrix.org) — помог разобраться в Go и |
| |
| 71 | много чего полезного посоветовал по этому языку. |
| |
| 72 | * [meoww](https://codeberg.org/meoww) — перевела некоторые предложения на |
| |
| 73 | английский язык и написала сервис для openrc |
| |
SETUP-RU.md
deleted
−42
| @@ -1,42 +0,0 @@ |
| 1 | [English version 🇬🇧](SETUP.md) |
| |
| 2 | |
| |
| 3 | # Единицы измерения |
| |
| 4 | Размер файла в кеше измеряется в мегабайтах.<br> |
| |
| 5 | Единицы времени: |
| |
| 6 | * `i` — минуты |
| |
| 7 | * `h` — часы |
| |
| 8 | * `w` — недели |
| |
| 9 | * `m` — месяца |
| |
| 10 | * `y` — года |
| |
| 11 | |
| |
| 12 | # Конфигурация |
| |
| 13 | * `listen` — IP и порт для слушанья; заполняется по такой форме: ip:port |
| |
| 14 | * `uri` — URI инстанса. Пример: `"uri":"/art/"` -> https://skunky.ebloid.ru/art/ |
| |
| 15 | * `cache` — Система кеширования; по умолчанию выключена |
| |
| 16 | * `enabled` — Состояние системы кеширования; требуется булёвое значение |
| |
| 17 | * `path` — Полный путь до каталога, куда будет сохраняться кеш |
| |
| 18 | * `lifetime` — Время жизни файла в кеше, требует целочисленное значение, дополненное суффиксом времени (см. 'Единицы времени') |
| |
| 19 | * `max-size` — Максимальный размер файла |
| |
| 20 | * `update-interval` — Интервал для автоматической ротации кеша |
| |
| 21 | * `static-path` — Строка, являющаяся путём до статики. SkunkyArt при запуске скопирует содержимое этого каталога в ОЗУ. Однако, если вы собрали фронтенд с тегом 'embed', то этого не произайдёт |
| |
| 22 | * `download-proxy` — Адрес прокси для загрузки файлов |
| |
| 23 | * `user-agent` — Строка, которая используется в качестве User-Agent'а |
| |
| 24 | |
| |
| 25 | # Настройка обратного прокси |
| |
| 26 | Если вы собираетесь хостить инстанс в Интернете, то вам следует настроить заголовок прокси [`X-Forwarded-Proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto). В противном случае, все ссылки на вашем инстансе будут вида "http". Ниже есть информация о том, как настроить обратное проксирование: |
| |
| 27 | |
| |
| 28 | Nginx: |
| |
| 29 | ```apache |
| |
| 30 | server { |
| |
| 31 | listen 443 ssl; |
| |
| 32 | server_name skunky.example.com; |
| |
| 33 | |
| |
| 34 | # Если используется поддомен, то вместо ((BASE_URL)), укажите '/'. |
| |
| 35 | location ((BASE_URL)) { |
| |
| 36 | proxy_set_header X-Forwarded-Proto $scheme; |
| |
| 37 | proxy_set_header Host $host; |
| |
| 38 | proxy_http_version 1.1; |
| |
| 39 | proxy_pass http://((IP)):((PORT)); |
| |
| 40 | } |
| |
| 41 | } |
| |
| 42 | ```\ No newline at end of file |
| |
SETUP.md
−2
| @@ -1,5 +1,3 @@ |
| 1 | [Версия на русском языке 🇷🇺](SETUP-RU.md) |
| |
| 2 | |
| |
| 3 | # Units |
1 | # Units |
| 4 | Maximum file size in megabytes, requires numeric value.<br> |
2 | Maximum file size in megabytes, requires numeric value.<br> |
| 5 | Time units: |
3 | Time units: |
app/api.go
+1 −1
| @@ -57,7 +57,7 @@ func (a API) sendMedia(d *devianter.Deviation) { |
| 57 | } |
57 | } |
| 58 | } |
58 | } |
| 59 | |
59 | |
| 60 | // TODO: сделать фильтры |
60 | // TODO: add filters |
| 61 | func (a API) Random() { |
61 | func (a API) Random() { |
| 62 | // Bounded retries: the loop used to be unbounded, and the DeviantArt-error |
62 | // Bounded retries: the loop used to be unbounded, and the DeviantArt-error |
| 63 | // path never incremented attempt, so a single request could spin forever |
63 | // path never incremented attempt, so a single request could spin forever |
app/cache.go
+1 −1
| @@ -1,4 +1,4 @@ |
| 1 | // TODO: реализовать кеширование JSON и почистить код |
1 | // TODO: implement JSON caching and clean up the code |
| 2 | package app |
2 | package app |
| 3 | |
3 | |
| 4 | import ( |
4 | import ( |
app/parsers.go
+1 −1
| @@ -188,7 +188,7 @@ type text struct { |
| 188 | To int |
188 | To int |
| 189 | } |
189 | } |
| 190 | |
190 | |
| 191 | // переписать весь этот пиздец нахуй |
191 | // TODO: rewrite this whole mess |
| 192 | func ParseDescription(dscr devianter.Text) string { |
192 | func ParseDescription(dscr devianter.Text) string { |
| 193 | var parsedDescription strings.Builder |
193 | var parsedDescription strings.Builder |
| 194 | TagBuilder := func(content string, tags ...string) string { |
194 | TagBuilder := func(content string, tags ...string) string { |
app/router.go
+1 −1
| @@ -52,7 +52,7 @@ func Router() { |
| 52 | return fileReaded |
52 | return fileReaded |
| 53 | } |
53 | } |
| 54 | |
54 | |
| 55 | // функция, что управляет всем |
55 | // the function that drives everything |
| 56 | handle := func(w http.ResponseWriter, r *http.Request) { |
56 | handle := func(w http.ResponseWriter, r *http.Request) { |
| 57 | path := parsepath(r.URL.Path) |
57 | path := parsepath(r.URL.Path) |
| 58 | Host = "http://" + r.Host |
58 | Host = "http://" + r.Host |
app/util.go
+2 −2
| @@ -261,13 +261,13 @@ func GetValueOfTag(t *html.Tokenizer) string { |
| 261 | } |
261 | } |
| 262 | } |
262 | } |
| 263 | |
263 | |
| 264 | // навигация по страницам |
264 | // page navigation |
| 265 | type DeviationList struct { |
265 | type DeviationList struct { |
| 266 | Pages int |
266 | Pages int |
| 267 | More bool |
267 | More bool |
| 268 | } |
268 | } |
| 269 | |
269 | |
| 270 | // FIXME: на некоротрых артах первая страница может вызывать полное отсутствие панели навигации. |
270 | // FIXME: on some artworks the first page can make the navigation panel disappear entirely. |
| 271 | func (s skunkyart) NavBase(c DeviationList) string { |
271 | func (s skunkyart) NavBase(c DeviationList) string { |
| 272 | var list strings.Builder |
272 | var list strings.Builder |
| 273 | |
273 | |
app/wrapper.go
+3 −3
| @@ -167,7 +167,7 @@ func (s skunkyart) GRUser() { |
| 167 | } |
167 | } |
| 168 | } |
168 | } |
| 169 | |
169 | |
| 170 | // посты |
170 | // posts |
| 171 | func (s skunkyart) Deviation(author, postname string) { |
171 | func (s skunkyart) Deviation(author, postname string) { |
| 172 | id_search := regexp.MustCompile("[0-9]+").FindAllString(postname, -1) |
172 | id_search := regexp.MustCompile("[0-9]+").FindAllString(postname, -1) |
| 173 | if len(id_search) < 1 { |
173 | if len(id_search) < 1 { |
| @@ -209,7 +209,7 @@ func (s skunkyart) Deviation(author, postname string) { |
| 209 | } |
209 | } |
| 210 | } |
210 | } |
| 211 | |
211 | |
| 212 | // хештэги |
212 | // hashtags |
| 213 | for _, x := range post.Post.Deviation.Extended.Tags { |
213 | for _, x := range post.Post.Deviation.Extended.Tags { |
| 214 | var tag strings.Builder |
214 | var tag strings.Builder |
| 215 | tag.WriteString(` <a href="`) |
215 | tag.WriteString(` <a href="`) |
| @@ -270,7 +270,7 @@ func (s skunkyart) Search() { |
| 270 | ss.Content, daError, err = devianter.PerformSearch(s.Query, s.Page, s.Type) |
270 | ss.Content, daError, err = devianter.PerformSearch(s.Query, s.Page, s.Type) |
| 271 | case 'g', 'f': |
271 | case 'g', 'f': |
| 272 | ss.Content, daError, err = devianter.PerformSearch(s.Query, s.Page, s.Type, s.Args.Get("usr")) |
272 | ss.Content, daError, err = devianter.PerformSearch(s.Query, s.Page, s.Type, s.Args.Get("usr")) |
| 273 | case 'r': // скраппер, поскольку девиантартовцы зажопили гостевое API для поиска групп |
273 | case 'r': // scraper, since DeviantArt withholds the guest API for group search |
| 274 | var ( |
274 | var ( |
| 275 | usernames = make(map[int]string) |
275 | usernames = make(map[int]string) |
| 276 | url strings.Builder |
276 | url strings.Builder |
static/templates-noembed.go
+1 −1
| @@ -91,7 +91,7 @@ func try(err error) { |
| 91 | } |
91 | } |
| 92 | } |
92 | } |
| 93 | |
93 | |
| 94 | /* сделано на основе https://github.com/psanford/memfs; требуется для корректной работы templates.ParseFS */ |
94 | /* based on https://github.com/psanford/memfs; required for templates.ParseFS to work correctly */ |
| 95 | type fileInfo struct { |
95 | type fileInfo struct { |
| 96 | name string |
96 | name string |
| 97 | } |
97 | } |