1
0

Compare commits

...

44 Commits

Author SHA1 Message Date
76c274c2a2
Обновил заголовки на странице О... 2024-09-15 17:07:02 +04:00
db624f39af
Translation of a stuff page completed. 2024-09-15 17:05:27 +04:00
02e1b66072
Date format at stuff page was changed. 2024-09-15 16:20:25 +04:00
d4706e53ce
Translation of a stuff page. 2024-09-15 16:15:57 +04:00
94482d0aae
Fixed date format in mindflow. 2024-09-15 15:52:54 +04:00
f366892b59
Updated mindflow translation. 2024-09-15 15:40:14 +04:00
ed273c4815
Fixed RSS. 2024-09-15 15:29:42 +04:00
45d1a71229
Change timedate format in a guestbook. 2024-09-15 15:09:55 +04:00
917bd7e21e
Закончен перевод страницы О... 2024-09-15 15:04:23 +04:00
64057bf9d5
Translate CAPTCHA text in JS. 2024-09-15 15:03:39 +04:00
2904a07088
Make a lang cookie accessible in JS for translation. 2024-09-15 15:03:13 +04:00
439e25b28c
Ещё немного перевода страницы О... . 2024-09-15 04:18:47 +04:00
2b39a0f769
Первая часть перевода страницы О... 2024-09-15 04:11:21 +04:00
77ac80334e
Added a russian translation of privacy statements. Also corrected the text. 2024-09-15 02:57:11 +04:00
20ecf6744f
Updated translations. I found that " can be ommited. 2024-09-15 02:56:19 +04:00
841653f502
A strange escaping is being performed somewhere inside ctxi18n and i18n.M is a way to avoid it. 2024-09-15 02:55:36 +04:00
802c925450
Set lang if a lang= query set, else look for a cookie, otherwise choose a lang from Accept-Language header. 2024-09-15 00:31:00 +04:00
d26bcc58b8
Added links to set site's lang. 2024-09-15 00:29:52 +04:00
d9d7358abf
Fixed en.yaml. 2024-09-15 00:29:02 +04:00
0e889448e3
Updated index page. 2024-09-14 23:54:07 +04:00
ad02399301
Первый шаг к переводу сайта на русский. 2024-09-14 18:36:08 +04:00
50ba6bb74b
Introduce i18n. Теперь переведу сайт на русский! 2024-09-14 18:34:22 +04:00
4b351ed7a9
Update dependencies. 2024-09-14 18:32:57 +04:00
f939a056ad
Updated index.templ. 2024-09-11 01:06:27 +04:00
429284ab3d
Version set to 24.37.0. 2024-09-11 00:14:45 +04:00
028a26a6f5
Updated dependencies. 2024-09-11 00:13:38 +04:00
c3f9b8db14
Version set to 24.34.0. 2024-08-19 02:05:14 +04:00
51699ca458
Добавил русский текст на главную. :) 2024-08-19 01:50:45 +04:00
ea87940595
Update dependencies. 2024-08-19 01:47:44 +04:00
6726a7989c
Ported mindflow admin page to Templ. 2024-07-13 19:58:12 +04:00
f59da2a76e
Updated Makefile. 2024-07-12 17:09:21 +04:00
4cc8b0c761
In Makefile remove commented out sed command. 2024-07-12 16:19:17 +04:00
52e1117b7d
Updated templ dependency. 2024-07-12 16:18:22 +04:00
4b1f7ea763
In Stuff version of httpprocprobed was set to 3.2.0. 2024-07-07 19:54:21 +04:00
a5ccd81f28
Added listen option for IPv6. Added allow option for my IPv6-prefix. 2024-07-07 19:40:57 +04:00
b4171bed0d
Version set to 24.27.1. 2024-07-04 04:00:21 +04:00
2f339f6e3e
Updated sitemap.xml. 2024-07-04 03:57:10 +04:00
6e693e3b88
Introduced correct canonical link (includes schema://host). 2024-07-04 03:56:57 +04:00
da5745b368
Fixed Makefile clean. 2024-07-04 03:55:49 +04:00
3bed5474c4
Hotfix for mistaken keywords and canonical args in templ Index(). 2024-07-04 03:44:17 +04:00
20cf45bfeb
Do not convert mindflow's post date to client's TZ twice. 2024-07-02 17:28:38 +04:00
eceb06aa57
Remove about.pug and banners. 2024-07-02 17:26:58 +04:00
b13f287d5f
Place a program's version in a footer of a site. 2024-07-02 04:12:50 +04:00
cdabb77c39
Implemented a package for storing program's version. 2024-07-02 04:12:26 +04:00
34 changed files with 1024 additions and 790 deletions

View File

@ -2,25 +2,28 @@ TARGET=dwelling-home
SYSDDIR_=${shell pkg-config systemd --variable=systemdsystemunitdir}
SYSDDIR=${SYSDDIR_:/%=%}
DESTDIR:=
PREFIX:=/usr/local
VERSION=24.27.0
DESTDIR?=
PREFIX?=/usr/local
FLAGS:=-buildmode=pie -modcacherw -mod=readonly -trimpath
LDFLAGS=-ldflags "-s -w -X main.version=${VERSION}" -tags osusergo,netgo
VERSION?=24.37.0
XVER:=git.arav.su/Arav/dwelling-home/internal/version.ver=v${VERSION}
GOFLAGS:=-buildmode=pie -trimpath -mod=readonly -modcacherw
GOFLAGS+=-ldflags="-linkmode=external -s -w -X '${XVER}' -extldflags=${LDFLAGS}"
GOFLAGS+=-tags osusergo,netgo
.PHONY: run install uninstall clean
${TARGET}: web/*_templ.go
go build -o bin/$@ ${LDFLAGS} ${FLAGS} cmd/$@/main.go
go build ${GOFLAGS} -o bin/$@ cmd/$@/main.go
web/*_templ.go: web/*.templ
ifeq (,$(wildcard $(shell go env GOPATH)/bin/templ))
go install github.com/a-h/templ/cmd/templ@latest
endif
TEMPL_EXPERIMENT=rawgo $(shell go env GOPATH)/bin/templ generate
# sed -ri 's/a> "/a>"/g' web/*_templ.go
run: | ${TARGET}
bin/${TARGET} -listen 127.0.0.1:18123 -database-path . -captcha-expiry 10m \
@ -42,4 +45,4 @@ uninstall:
clean:
rm -f bin/${TARGET}
rm -f web/*.pug.go web/jade.go
rm -f web/*_templ.go

View File

@ -1,6 +1,6 @@
# Maintainer: Alexander "Arav" Andreev <me@arav.su>
pkgname=dwelling-home
pkgver=24.27.0
pkgver=24.37.0
pkgrel=1
pkgdesc="Arav's dwelling / Home"
arch=('i686' 'x86_64' 'arm' 'armv6h' 'armv7h' 'aarch64')

View File

@ -12,15 +12,15 @@ import (
"time"
dwhttp "git.arav.su/Arav/dwelling-home/internal/http"
"git.arav.su/Arav/dwelling-home/internal/version"
mfsqlite "git.arav.su/Arav/dwelling-home/pkg/mindflow/database/sqlite"
"git.arav.su/Arav/dwelling-home/web"
"git.arav.su/Arav/dwelling-home/web/locales"
"git.arav.su/Arav/httpr"
gb "git.arav.su/Arav/justguestbook"
"github.com/a-h/templ"
"github.com/invopop/ctxi18n"
)
var version string
var (
showVersion = flag.Bool("v", false, "show version")
listenAddress = flag.String("listen", "/var/run/dwelling-home/sock", "listen address (ip:port|unix_path)")
@ -34,7 +34,7 @@ func main() {
flag.Parse()
if *showVersion {
fmt.Println("dwelling-home Ver.", version, "\nCopyright (c) 2023 Alexander \"Arav\" Andreev <me@arav.su>")
fmt.Println("dwelling-home", version.GetVersion(), "\nCopyright (c) 2023,2024 Alexander \"Arav\" Andreev <me@arav.su>")
return
}
@ -52,12 +52,16 @@ func main() {
}
defer mindflowDB.Close()
if err := ctxi18n.LoadWithDefault(locales.Content, "en"); err != nil {
log.Fatalln("Failed to load i18n:", err)
}
hand := dwhttp.NewHandlers(*captchaExpiry, owner, *guestbookPageSize, guestbookDB, mindflowDB)
r := httpr.New()
r.NotFoundHandler = func(w http.ResponseWriter, r *http.Request) {
dwhttp.Error(w, http.StatusNotFound, "", "", r.Referer())
dwhttp.Error(w, http.StatusNotFound, "", "", r)
}
r.ServeStatic("/assets/*filepath", web.Assets())
@ -66,7 +70,7 @@ func main() {
r.Handler(http.MethodGet, "/rss.xml", hand.RSS)
r.Handler(http.MethodGet, "/sitemap.xml", dwhttp.ServeAsset("sitemap.xml"))
r.Handler(http.MethodGet, "/", templ.Handler(web.Index()).ServeHTTP)
r.Handler(http.MethodGet, "/", hand.Index)
r.Handler(http.MethodGet, "/privacy", hand.Privacy)
r.Handler(http.MethodGet, "/stuff", hand.Stuff)
r.Handler(http.MethodGet, "/stuff/article/*filepath", hand.Article)
@ -103,7 +107,7 @@ func main() {
s.Handler(http.MethodPatch, "/category/:id", mindflowApi.EditCategory)
s.Handler(http.MethodDelete, "/category/:id", mindflowApi.DeleteCategory)
srv := dwhttp.NewHttpServer(r)
srv := dwhttp.NewHttpServer(I18nMiddleware(r))
if err := srv.Start(*listenAddress); err != nil {
log.Fatalln(err)
@ -119,3 +123,25 @@ func main() {
<-doneSignal
}
func I18nMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
lang := "en"
if lq := r.URL.Query().Get("lang"); lq != "" {
lc := http.Cookie{Name: "lang", Value: lq, HttpOnly: false, MaxAge: 0}
http.SetCookie(w, &lc)
lang = lq
} else if l, err := r.Cookie("lang"); err == nil {
lang = l.Value
} else if al := r.Header.Get("Accept-Language"); al != "" {
lang = r.Header.Get("Accept-Language")
}
ctx, err := ctxi18n.WithLocale(r.Context(), lang)
if err != nil {
log.Println("i18nmw:", err)
}
next.ServeHTTP(w, r.WithContext(ctx))
})
}

View File

@ -1,5 +1,6 @@
server {
listen 443 http2;
listen [::]:443 http2;
listen 8090; # Tor I2P
listen [300:a98d:d6d0:8a08::f]:80; # Yggdrasil
@ -38,6 +39,7 @@ server {
proxy_set_header Schema $scheme;
allow 192.168.144.0/25;
allow 2a03:e2c0:4a0f::/48;
deny all;
}
@ -50,6 +52,7 @@ server {
proxy_set_header Schema $scheme;
allow 192.168.144.0/25;
allow 2a03:e2c0:4a0f::/48;
deny all;
}
@ -66,6 +69,7 @@ server {
proxy_buffering off;
allow 192.168.144.0/25;
allow 2a03:e2c0:4a0f::/48;
deny all;
}
@ -74,6 +78,7 @@ server {
proxy_buffering off;
allow 192.168.144.0/25;
allow 2a03:e2c0:4a0f::/48;
deny all;
}

11
go.mod
View File

@ -7,18 +7,21 @@ toolchain go1.22.4
require (
git.arav.su/Arav/justcaptcha/v2 v2.1.0
git.arav.su/Arav/justguestbook v1.3.2
github.com/a-h/templ v0.2.731
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024
github.com/a-h/templ v0.2.778
github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6
github.com/invopop/ctxi18n v0.8.1
github.com/pkg/errors v0.9.1
)
require (
github.com/fogleman/gg v1.3.0 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
golang.org/x/image v0.18.0 // indirect
github.com/invopop/yaml v0.3.1 // indirect
golang.org/x/image v0.20.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
require (
git.arav.su/Arav/httpr v0.3.2
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/mattn/go-sqlite3 v1.14.23 // indirect
)

30
go.sum
View File

@ -4,27 +4,37 @@ git.arav.su/Arav/justcaptcha/v2 v2.1.0 h1:EFerW2mP60rDczu1mPbJb7DiDeAQOcw83/KiWc
git.arav.su/Arav/justcaptcha/v2 v2.1.0/go.mod h1:Ntab6TUAqCo/H9LSWOd4IQ9ANnp8G1PEygXtORcdTOY=
git.arav.su/Arav/justguestbook v1.3.2 h1:B1AzS14dW3bVlp0Qj6pu1PrJlWaPK1mplmx3UNBcxo4=
git.arav.su/Arav/justguestbook v1.3.2/go.mod h1:Umo/AzSOKu+OU+03V7/QQ6m6N0nXyeRAGOZT4P5ol98=
github.com/a-h/templ v0.2.731 h1:yiv4C7whSUsa36y65O06DPr/U/j3+WGB0RmvLOoVFXc=
github.com/a-h/templ v0.2.731/go.mod h1:IejA/ecDD0ul0dCvgCwp9t7bUZXVpGClEAdsqZQigi8=
github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM=
github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024 h1:saBP362Qm7zDdDXqv61kI4rzhmLFq3Z1gx34xpl6cWE=
github.com/gomarkdown/markdown v0.0.0-20240626202925-2eda941fd024/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6 h1:ZPy+2XJ8u0bB3sNFi+I72gMEMS7MTg7aZCCXPOjV8iw=
github.com/gomarkdown/markdown v0.0.0-20240730141124-034f12af3bf6/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/invopop/ctxi18n v0.8.1 h1:nfy5Mk6UfvLbGRBwpTi4T1g95+rmRo8bMllUmpCvVwI=
github.com/invopop/ctxi18n v0.8.1/go.mod h1:1Osw+JGYA+anHt0Z4reF36r5FtGHYjGQ+m1X7keIhPc=
github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -53,3 +63,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -30,7 +30,7 @@ func (h *GuestbookApiHandlers) New(w http.ResponseWriter, r *http.Request) {
if !inmemdb.Solve(captcha.ID(r.FormValue("captcha_id")), captcha.Answer(r.FormValue("captcha_answer"))) {
Error(w, http.StatusForbidden, "Wrong answer given.",
"Here's your message:"+r.FormValue("message"), r.Referer())
"Here's your message:"+r.FormValue("message"), r)
return
}
@ -44,14 +44,14 @@ func (h *GuestbookApiHandlers) New(w http.ResponseWriter, r *http.Request) {
r.FormValue("website"), r.FormValue("hide_website") != "")
if err != nil {
Error(w, http.StatusInternalServerError, err.Error(),
"Here's your message:"+r.FormValue("message"), r.Referer())
"Here's your message:"+r.FormValue("message"), r)
return
}
}
if err = h.db.NewEntry(entry); err != nil {
Error(w, http.StatusInternalServerError, err.Error(),
"Here's your message:"+r.FormValue("message"), r.Referer())
"Here's your message:"+r.FormValue("message"), r)
return
}

View File

@ -51,7 +51,7 @@ func (h *MindflowApiHandlers) NewPost(w http.ResponseWriter, r *http.Request) {
if err = h.db.NewPost(post); err != nil {
msg := strings.Join([]string{"Title:", r.FormValue("title"), "| Body:", r.FormValue("body")}, " ")
Error(w, http.StatusInternalServerError, err.Error(), msg, r.Referer())
Error(w, http.StatusInternalServerError, err.Error(), msg, r)
return
}

View File

@ -1,7 +1,6 @@
package http
import (
"context"
"log"
"math"
"net/http"
@ -35,46 +34,50 @@ func NewHandlers(captchaExpire time.Duration, owner string, gbPageSize int64,
guestbookPageSize: gbPageSize}
}
func (h *Handlers) Index(w http.ResponseWriter, r *http.Request) {
web.Index(r).Render(r.Context(), w)
}
func (h *Handlers) Privacy(w http.ResponseWriter, r *http.Request) {
web.Privacy(r).Render(context.Background(), w)
web.Privacy(r).Render(r.Context(), w)
}
func (h *Handlers) Stuff(w http.ResponseWriter, r *http.Request) {
web.Stuff(r).Render(context.Background(), w)
web.Stuff(r).Render(r.Context(), w)
}
func (h *Handlers) Mindflow(w http.ResponseWriter, r *http.Request) {
posts, err := h.mindflowDB.Posts()
if err != nil {
log.Println("Cannot load posts.", err)
Error(w, http.StatusInternalServerError, "Cannot load posts.", "", r.Referer())
Error(w, http.StatusInternalServerError, "Cannot load posts.", "", r)
return
}
categories, err := h.mindflowDB.Categories()
if err != nil {
log.Println("Cannot load categories.", err)
Error(w, http.StatusInternalServerError, "Cannot load categories.", "", r.Referer())
Error(w, http.StatusInternalServerError, "Cannot load categories.", "", r)
return
}
web.Mindflow(posts, categories, r).Render(context.Background(), w)
web.Mindflow(posts, categories, r).Render(r.Context(), w)
}
func (h *Handlers) MindflowAdmin(w http.ResponseWriter, r *http.Request) {
posts, err := h.mindflowDB.Posts()
if err != nil {
Error(w, http.StatusInternalServerError, err.Error(), "failed to load posts", r.Referer())
Error(w, http.StatusInternalServerError, err.Error(), "failed to load posts", r)
return
}
categories, err := h.mindflowDB.Categories()
if err != nil {
Error(w, http.StatusInternalServerError, err.Error(), "failed to load categories", r.Referer())
Error(w, http.StatusInternalServerError, err.Error(), "failed to load categories", r)
return
}
web.MindflowAdmin(posts, categories, r).Render(context.Background(), w)
web.MindflowAdmin(posts, categories, r).Render(r.Context(), w)
}
func (h *Handlers) About(w http.ResponseWriter, r *http.Request) {
@ -92,18 +95,18 @@ func (h *Handlers) About(w http.ResponseWriter, r *http.Request) {
}
}
web.About(&lst, r).Render(context.Background(), w)
web.About(&lst, r).Render(r.Context(), w)
}
func (h *Handlers) Article(w http.ResponseWriter, r *http.Request) {
name := r.URL.Path[strings.LastIndex(r.URL.Path, "/")+1:]
artcl := web.GetArticle(name)
if artcl == nil {
Error(w, http.StatusNotFound, "", "An article \""+name+"\" doesn't exist.", r.Referer())
Error(w, http.StatusNotFound, "", "An article \""+name+"\" doesn't exist.", r)
return
}
web.Article(artcl.Title, artcl.Description, string(artcl.Body), name, artcl.Date, r).Render(context.Background(), w)
web.Article(artcl.Title, artcl.Description, string(artcl.Body), name, artcl.Date, r).Render(r.Context(), w)
}
func (h *Handlers) Guestbook(w http.ResponseWriter, r *http.Request) {
@ -140,21 +143,21 @@ func (h *Handlers) Guestbook(w http.ResponseWriter, r *http.Request) {
dwc := dwcaptcha.NewDwellingCaptcha(h.captchaExpire)
_, id := inmemdb.New(r.RemoteAddr, dwc)
web.Guestbook(string(id), h.owner, entries, pageCount, page, r).Render(context.Background(), w)
web.Guestbook(string(id), h.owner, entries, pageCount, page, r).Render(r.Context(), w)
}
func (h *Handlers) GuestbookAdmin(w http.ResponseWriter, r *http.Request) {
entriesCount, _ := h.guestbookDB.Count()
entries, err := h.guestbookDB.Entries(1, entriesCount)
if err != nil {
Error(w, http.StatusInternalServerError, err.Error(), "cannot load gb", r.Referer())
Error(w, http.StatusInternalServerError, err.Error(), "cannot load gb", r)
return
}
for _, entry := range entries {
entry.Message = strings.ReplaceAll(entry.Message, "\\n", "\n")
}
web.GuestbookAdmin(h.owner, entries, r).Render(context.Background(), w)
web.GuestbookAdmin(h.owner, entries, r).Render(r.Context(), w)
}
func (h *Handlers) RSS(w http.ResponseWriter, r *http.Request) {
@ -168,7 +171,7 @@ func (h *Handlers) RSS(w http.ResponseWriter, r *http.Request) {
scheme = "http"
}
web.RSS(scheme+"://"+r.Host, h.owner, posts, r).Render(context.Background(), w)
web.RSS(scheme+"://"+r.Host, h.owner, posts, r).Render(r.Context(), w)
}
func ServeAsset(path string) func(http.ResponseWriter, *http.Request) {
@ -178,9 +181,9 @@ func ServeAsset(path string) func(http.ResponseWriter, *http.Request) {
}
}
func Error(w http.ResponseWriter, code int, reason, message, referer string) {
func Error(w http.ResponseWriter, code int, reason, message string, r *http.Request) {
w.WriteHeader(code)
web.ErrorXXX(code, reason, message, referer).Render(context.Background(), w)
web.ErrorXXX(code, reason, message, r).Render(r.Context(), w)
}
func cleanupNewlines(text string) (out string) {

View File

@ -0,0 +1,7 @@
package version
var ver string
func GetVersion() string {
return ver
}

View File

@ -2,254 +2,507 @@ package web
import "net/http"
import "github.com/invopop/ctxi18n/i18n"
import "git.arav.su/Arav/dwelling-home/pkg/servicestat"
import "git.arav.su/Arav/dwelling-home/pkg/util"
templ About(services *servicestat.ServiceList, r *http.Request) {
@base("About", "About me and my home servers.", "about, me, servcies", "/about", aboutHead()) {
<section id="about-me">
<h2>Me</h2>
<p><b class="highlighted">Who am I?</b> My name is <span class="highlighted">A</span>lexande<span class="highlighted">r</span> <span class="highlighted">A</span>ndree<span class="highlighted">v</span>. I'm a russian guy of age 31 who likes tinkering with computers.</p>
<p><b class="highlighted">Why am I doing all of this?</b> Machines are up 24/7 anyway, so why not? And I wanted a website long ago, just didn't know what to put on it. Like if I do now... :)</p>
<p><b class="highlighted">Why am I almost &ldquo;doxxing&rdquo; myself?</b> Yes, my real first and last names and age are here, and since I self-host you can get my city as well. And I simply don't see this as a problem. :|</p>
<p><b class="highlighted">Why particularly that slogan?</b> It was the first thing that went on my mind. Don't you think of your website as of a special place of your own? Sacred in some way..? And what else do we do if not wandering through the vastness of Internet looking for something? Think about it... :)</p>
<p><b class="highlighted">Why English only?</b> I want this place to be accessible for a wide audience and English happen to be todays lingua franca, and to practice the language of course.</p>
<p>Now a little break for...</p>
</section>
<section id="my-cat">
<h3>My kot Boris :3</h3>
<div class="columns figs">
<figure>
<a href="/assets/img/photos/my_cat.webp">
<img src="/assets/img/photos/my_cat_thumb.webp" alt="My cat. :3" title=":3"/>
</a>
</figure>
<figure>
<a href="/assets/img/photos/my_cat_2.webp">
<img src="/assets/img/photos/my_cat_2_thumb.webp" alt="xDDDD" title="xDDDD"/>
</a>
</figure>
</div>
<p>And here we continue. :)</p>
</section>
<section id="more-about-me">
<h3>Hobbies</h3>
<p>Video games (since 1997)</p>
<p>Computers (since 11th November 2004)</p>
<p><s>Wasting my life on</s> Surfing the Internets (since February 2006)</p>
<p>Mapping for Half-life 2, Counter-Strike: Source (since 2006, discontinued in 2009) (everything's fuarrkin' lost, or maybe it is still on a broken IDE drive)</p>
<p>Music writing (since 2007, last track was made in 2010)</p>
<p>Programming (since 2007)</p>
<p><s>(LARP'ing as a system administrator)</s> Home servers (since 1st January 2017, when I had set up my Raspberry Pi I got the day before)</p>
<p>Software Defined Radio (since June 2018)</p>
<h3>What I know</h3>
<h4>Human languages</h4>
<p>While I like learning foreign languages, lack of usefulness for me and my lazyness prevents me from getting on any reasonable level, so I stuck to English. Knowledge of other languages I tried to learn, which are German, Norwegian, French, Polish, and Japanese, is minuscle and only declining.</p>
<p>The other language I understand well, and can somehow speak is Ukrainian, which is no surprise because of its relation with Russian. At least it should be not, yet I see that many Russians don't understand Ukrainian like at all, which is surprising for me. I accidentally learnt it just by consuming content in it with help of a dictionary to look up some words that are archaic in Russian or have different etymology.</p>
<p>As for Belarussian, situation is the same, but I don't speak it, just know some words I have accidentally memorised while listening to music.</p>
<h4>Computer languages</h4>
<p>All the programming, markup and declarative languages I use by now are Go, JavaScript (vanilla), SQL, Python, Bash, AWK, HTML, CSS, LaTeX, Markdown, JSON, XML.</p>
<p>Previously I used (in a chronological order) Pascal, Delphi, C#, C++, C, Java, PHP. Took a taste of Visual Basic, LISP, Haskell, Rust.</p>
<p>It so happened that I didn't save the source code from the past. 99% of it was written purely for education and fun, and usually never get finished. And such a code was heartlessly deleted by me. Why would I keep OpenGL hello world that draws triangles..? :)</p>
<p>At least an experience I gained isn't going anywhere. :) And I think what is on my <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceGit)) }>Gitea instance</a> can speak for me.</p>
<p>I still have an old IDE drive that got broken back in 2011. BIOS cannot see it, but it is spinning, even without any crack noises. Maybe it still has some old code. And some more from that time...</p>
<h3>What I liked</h3>
<h4>Anime</h4>
<p>Ghost in the Shell, Shaman King, Hellsing, Steins;Gate, Cowboy Beebop, Ergo Proxy, Jin-Rou, Black Lagoon, Jojo's Bizzare Adventures, Spice and Wolf, Konosuba, Demon Slayer: Kimetsu no Yaiba.</p>
<h4>Films</h4>
<p>Paths of Glory (1957), Boss Nigger (The Black Bounty Killer) (1974), Movies with Jackie Chan, Blade Runner (1982), WarGames (1983), Robocop (1987), Talk Radio (1988), Stargate (1994), Hackers (1995), Johnny Mnemonic (1995), Contact (1997), Matrix (1999, 2003), Snatch (2000), Oldboy (2003), The Day After Tomorrow (2004), Alpha Dog (2005), Constantine (2005), The Gingerdead Man (2005), Lucky Number Slevin (2006), 99 francs (2007), I Am Legend (2007), Inglourious Basterds (2009), Valhalla Rising (2009), The Guard (2011), Filth (2013), Mandariinid (2013), Gingerdead Man vs. Evil Bong (2013), Gone Girl (2014), Who am I (2014), Arrival (2016), Contratiempo (2016), Wandering Earth (2019), Wandering Earth 2 (2019), Greyhound (2020), I Care A Lot (2020), The Greatest Beer Run Ever (2022), Everything Everywhere All at Once (2022), Dungeons & Dragons: Honor Among Thieves (2023).</p>
<h4>TV series</h4>
<p>X-Files (1993&mdash;2002), Stargate: SG-1 (1997&mdash;2007), Stargate: Atlantis (2004&mdash;2009), Lost (2004&mdash;2010), Breaking Bad (2008&mdash;2013), Narcos (2015&mdash;2017), The Shivering Truth (2018&mdash;2020), Два холма (Two Hills) (2022).</p>
<h4>Games for Dendy (NES/Famicom clone)</h4>
<p>I had not just a Dendy console, no, it was embedded in a keyboard and it was named SUBOR.</p>
<p>Chip 'n Dale Rescue Rangers, and the other was an F1 game which name I don't know. Also, SUBOR had its own special cartridge called training cartridge. It had a keyboard trainer, a simple text editor, calculator, G-BASIC and F-BASIC, also had classic russian music like Moscow Nights in 8-bit.</p>
<p>Despite having BASIC on that cartridge I had no opportunity to start programming because I didn't have a manual. Anyway, I read that there was just code examples and most of them didn't work, LOL.</p>
<h4>Games for SEGA Mega Drive</h4>
<p>Not a lot of games I have played.</p>
<p>Bubba'n'Stix, Battletoads, Granada, Demolition Man, Road Rash, Doom Troopers - The Mutant Chronicles, The Lost Vikings, Ghostbusters, Mig-29 Fighter Pilot, Street Racer.</p>
<h4>Games for PC</h4>
<p>Grand Theft Auto: Vice City, Half-Life (all), StarCraft, Diablo 2, Far Cry (2004), Battlefield: Vietnam, Delta Force: Black Hawk Down, Silent Hunter 3, Grand Theft Auto: San Andreas, Boiling Point: Road to Hell, Portal, Freelancer, F.E.A.R., S.T.A.L.K.E.R., Grand Theft Auto 4, Lineage 2, The Elder Scrolls V: Skyrim, Battlefield 3, The Walking Dead, The Wolf Among Us, Payday 2, The Witcher (1st, 2nd, 3rd didn't finished yet), Minecraft, Terraria, Starbound, Euro Truck Simulator 2, Mount &amp; Blade: Warband, Papers, Please, Insurgency, Elite: Dangerous, theHunter: Call of the Wild, American Truck Simulator, Rocket League, Sea Of Thieves, Tell Some Story: Foz.</p>
<h4>Music</h4>
<p>Go check out <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceFiles)) }>my file share</a>. :)</p>
</section>
<section id="servers-summary">
<h2>My servers</h2>
<p>I have two servers laying on my PC which are a Raspberry Pi 3 rev. B single board computer and a laptop Acer Packard Bell TE69CX. Not quite impressive, I'd say, but they do what I need from them just fine, not for a real heavy load of course.</p>
<p>The laptop has a 2 core Intel Pentium 2117U 1.8GHz CPU and 10GB of RAM (2GB + 8GB), a system disk is a 120GB SSD, and a disk I use to store all the shit is a 2TB HDD, yeah, just one drive for data. Anything worthwhile is backed up (LOL, not really :^)).</p>
<p>For Raspberry Pi I use a 500GB HDD as a system/data disk.</p>
<p>Also I have a cheap VPS with 1 core 2.2GHz CPU and 512MB RAM, and a 10GB disk I use as a slave DNS server for my domain and a Postfix mail relay.</p>
<div class="columns figs">
<figure>
<a href="/assets/img/photos/raspi.webp">
<img src="/assets/img/photos/raspi_thumb.webp" alt="Raspberry Pi 3 rev. B" />
</a>
<figcaption>Raspberry Pi 3 rev. B</figcaption>
</figure>
<figure>
<a href="/assets/img/photos/acer.webp">
<img src="/assets/img/photos/acer_thumb.webp" alt="Acer Packard Bell TE69CX" title="Screen and keyboard are broken." />
</a>
<figcaption>Acer Packard Bell TE69CX</figcaption>
</figure>
</div>
</section>
<section id="services-public">
<h2>Public services</h2>
<p class="center">For everyone.</p>
<div class="columns">
<div>
<h3 class={ isServiceUp("radio", services) }>Internet-radio</h3>
<p>
<a href="https://radio.arav.su">radio.arav.su</a>.<a href="http://wsmkgnmhmzqm7kyzv7jnzzafvgm7xlmlfvzhgorpapd5or2arnhuktqd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://radio.arav.i2p">i2p</a><sup><a href="http://radio.arav.i2p/?i2paddresshelper=NfCKBu9vjLFiBMEPQGiZT9AzGlhkKHzYrKM66FL-ESeDbnYUY--NzukO9UA28s3WThhDQVge2TmyfYsaZiUw~AjuLsykxS13pebs7lkAVY1jm77La-eFFIAQ22Vtd2YgS0vbhRMzuDxKkCR1vPwNax8R2o6a07xsQvvDml6UQxG4p5vt44JA2geQNvQfm8cEiSa6gNJZJSW3rWuLDg6~1Jy3D70oSVSlNfihmG4JtNV6tVBjJE2h5gUxfhYZACttpGTPM~UNF~lrSujlBQsCqdzvLswdMw~FnvpfGzJcJroeFTerRyH6oUkkDSOK7uWwl0e70vKxrIbFgJjKtjlLWlUCI5N0TnJP4Hzt2pttB~R0hSr2vVl8ky0yJEtN3rwnrJkw7q0ZIH30ngTfxsCTbolAzl6liN9Ez5YF97zDOPnVFmvQ6Eg1PyFdypQO1PiUHqF56SWhx3utGwecUS6jJCvsKIJJVEIMVcD6h7S0z1g1rqQ4jbg5UfXPwFEgFOlzBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>I'm too lazy to make some kind of broadcasting program, so I just throw anything I like and randomise the playlist. :)</p>
<p>Technically it runs as follows: <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceGit) + "/Arav/dwelling-radio") }>dwelling-radio</a> &xrArr; Ezstream &xrArr; Icecast &xrArr; NGiNX.</p>
</div>
<div>
<h3 class={ isServiceUp("dwelling-files", services) }>File share</h3>
<p>
<a href="https://files.arav.su">files.arav.su</a>.<a href="http://qf5e43nlhvnrutmikuvbdfj3cmtthokpbaxtkm6mjlslttzvtgm4fxid.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://files.arav.i2p">i2p</a><sup><a href="http://files.arav.i2p/?i2paddresshelper=48vtYgeVnju7B2FaR0zxUL3MQXN9QjK~Ggya45aANwm86mtpemuEkaskJmEQaFSd4FcDAFIiXHfNpfGqoupLwNmtgBmGRcuVV8xb2W~W6lM0oOhovjB37EUaMWs3AI5aIES84QOqApgwYX-ANIcwa~Kg6AbMuX8D8qnejuhBbuCffYah-TD8e~O0cnyqxzLTmxIGCyk2egdYXwanJyYFDocomIVfcqfJ0MgjIHhFQtkcb0e84bxvDzcAFIpEDrzAo4GVrFn-TCu0Lyf2ccqmVpucFl0UGhuVRxEt19KLd3PxlfwHv2lmzTZtq9CbnfaoPntUPx1sf84QnZDmrXWhVK8p3VvuPZMxjyz9KyhPjrGkO4E0oibDlvKuMsGEm-GkZsKxgXo~CrdcVtN8suAwW6rACAuk8gq2jUMBZBZ12migPZ7miHftEkOFHfgfUiKBwirrw~y9Zi261WX4-EVe2oD4pkhQOrqOKIoI-vv5z9CpQ7PKL531kgkipcBseXybBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>There you'll find music, videos, books, games, programs, drivers (a very few), OS images (Winblows mainly). Go check it out!</p>
</div>
<div>
<h3 class={ isServiceUp("dwelling-upload", services) }>File upload</h3>
<p>
<a href="https://upload.arav.su">upload.arav.su</a>.<a href="http://4usftbmjpfexkr2x5xbp5ukmygpmg4fgrnx2wbifsexqctooz5hmviyd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://upload.arav.i2p">i2p</a><sup><a href="http://upload.arav.i2p/?i2paddresshelper=b5NWA2vNydWSv6~8KN4e~td2UVGkYsayKPa1PnXI87A3gsg6m978tIehHLVN4XcCfUq4aB-59hqqZicorRnHKfV3lVdx9mdhC8Bhj~bMAcwMgWoXidqZNrWMoFGzWotFsa3nWh4zsRUSfrokecC8u9Y06byfSS1siyak0J6xpsggXRqqgNF0-8ncPeqvzBxHB9NRDXWEVJGS9HSpydWl1UpjgZffcd~NZroxkSAfughHcFAn2OLKkaZRe6WqCJQfJoXTCyz4wkFmYbH1CSddWlddmWaaU7icsbQrZm3XEqKTVKvm86G6ehxmzyHqCumc4GOWswcP0E51UQVOv-WA8R6SWQAj6ZnZhnCoCNFFEfW2lBiDmTnLJbfm-C-AdI6G1~dQ1~3FCH6wXWy-2DebpyoVVt9epzU7l4l2MVeaOUahbf6wcol1UbxPoR0XlGCXDe9700TYePjtpOU9vNkk2B1dQiZ1usgwseYuO26cRogSvbi8poz4BlCNO733HR1XBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>I've made a file upload service for ya with a limit of 128MiB per file, keeping it for 36 hours, and overall storage I dedicated for it is 100GiB.</p>
</div>
<div>
<h3>Tor relay</h3>
<p><a href="https://metrics.torproject.org/rs.html#details/CEF2FD0E1973EA04D1444DDAEFF1B0BC3C0C39B1" rel="nofollow noreferrer">metrics.torproject.org</a></p>
<p><b>Since 1st December 2021 Tor is blocked in Russia, so the relay is down.</b></p>
</div>
<div>
<h3>I2P router</h3>
<p>I help the network using i2pd router.</p>
</div>
</div>
</section>
<section id="services-private">
<h2>Private services</h2>
<p class="center">For a narrow circle of people.</p>
<div class="columns">
<div>
<h3 class={ isServiceUp("mail", services) }>E-Mail server</h3>
<p>Postfix, Dovecot (w/Sieve), rspamd, ClamAV.</p>
</div>
<div>
<h3 class={ isServiceUp("mumble", services) }>Mumble</h3>
<p><a href="mumble://arav.su">mumble://arav.su</a></p>
<p>Runs with uMurmur. Protected by password.</p>
</div>
<div>
<h3 class={ isServiceUp("teamspeak3", services) }>TeamSpeak 3</h3>
<p><a href="ts3server://arav.su">ts3server://arav.su</a></p>
<p>For strangers (unregs) only an Entrance room is available. Your identifier should have a security level greater or equal to 29.</p>
</div>
<div>
<h3 class={ isServiceUp("git", services) }>Git</h3>
<p>
<a href="https://git.arav.su">git</a>.<a href="http://qqitm7qlsbbubwmjos4cqzmvkqidg34rfnbyhuydhalep33fbvh22xyd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://git.arav.i2p">i2p</a><sup><a href="http://git.arav.i2p/?i2paddresshelper=eFIfcBUv3lHFSnglHfncs5XXtYwm9gCpmAYuio~9CeENBAXKRggPiY1tQC-otCon2hCSpr56WlVBeZk1txKuUnbjHTN7GBFaKW5wJEO2WmKEWPKdcjUDOYZN0D3TwXaYfiBuELD3200lBfDmPEJ01iC2o7B5yvpOqtEKDcaqkIp4vafDuPPumJ~XiCGdUAe~vr52w3Tbuz5x7wbltk-gUELY0-ZAQBos4jOJ6QT1W1lhycHPhAK8qslgwfk94opyIl2pkRyuJhU-2VHc6Fsd621VXC86YAMT1SIfTZlFpoGVCFXDM~BXaLvygFaKf62qardAe0T48Ax6GxosAKXe-yLCVRaiD3KErULfwZXl23kQzRfxM4odG4DWeXawtuvypOmTjHT1skQHU0h52ujye5nT~2bOy14HkCoCnxJ7gSj3MjkmWLd1JhBsPH4ymRmI7jFJR1GYl8Wp5IigMBBzWfJUEEjS7QDHaRo5TCZJ9SXz6sgkGdfh74~r8FWL559gBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>Gitea. Anything I think is worth sharing is public. Private in terms of who can have account here.</p>
</div>
</div>
</section>
<section id="services-games">
<h2>Game servers</h2>
<div class="columns">
<div>
<h3 class={ isServiceUp("game-minecraft", services) }>Minecraft</h3>
<p class="highlighted">arav.su:25565</p>
<p><a href="/minemap">Web world map</a></p>
<p>Now runs a version 1.21 with Fabric. Just a fabric-api is needed to play.</p>
</div>
</div>
</section>
<section id="services-inner">
<h2>Inner services</h2>
<p class="center">Maintains other services or used exclusively by me.</p>
<div class="columns">
<div>
<h3>Web-server</h3>
<p>NGiNX. Nuff said.</p>
</div>
<div>
<h3>Database</h3>
<p>Used to run MariaDB, now my services use SQLite3.</p>
</div>
<div>
<h3>VPN</h3>
<p><s>OpenVPN</s> Wireguard.</p>
</div>
<div>
<h3>Network file storage</h3>
<p>Samba and NFSv4.</p>
</div>
<div>
<h3>Torrents</h3>
<p>I use transmission-cli. One annoying thing, it creates .part files for one of ignored files.</p>
</div>
<div>
<h3>Printing</h3>
<p>CUPS with ccpd (Canon CAPT printer).</p>
<p>It is guaranteed to work after reboot. :) If a kernel got updated &mdash; reboot. If you didn't use it for a long time and restart of CUPS and ccpd services after connecting a printer didn't work &mdash; reboot. xD</p>
</div>
<div>
<h3>DNS</h3>
<p>BIND9 via DNSCrypt-proxy.</p>
<p>For LAN I use &ldquo;arav.home.arpa&rdquo; domain. &ldquo;.home.arpa&rdquo; part is a special-use domain introduced in RFC 8375.</p>
<p>Master server lives on the laptop. It serves my external domain, internal one, and work as a recursion server to serve DNS queries from LAN. Raspberry Pi is a slave for the internal domain and recursion. And on the VPS lives a slave for my external domain.</p>
</div>
</div>
</section>
<section id="contacts">
<h2>Contacts</h2>
<span>E-Mail:&nbsp;<a href="mailto:me@arav.su">me@arav.su</a></span>
<span>PGP&nbsp;key:&nbsp;<a href="/assets/pgp.asc">7398 50CD 5051 DE55 4368 7092 2596 9B23 DCB5 CA34</a></span>
</section>
<section id="donation">
<h2>Donation</h2>
<p class="center">Just in case. %^)</p>
<table>
<tr>
<td>USDT&nbsp;(TRC&nbsp;20):</td>
<td>TGSEiAh9nAhCL6YPVA6zHUsnuoccW8tjep</td>
</tr>
<tr>
<td>USDT&nbsp;(ERC&nbsp;20):</td>
<td>0x584b3ab1b31d7248e2c0ba5d317e9ba88a4fb1b4</td>
</tr>
<tr>
<td>TON:</td>
<td>EQC4L0tZMDZ8IPGbyXQafoh2n-N9HbJwVp5EtrYGsRCuR28G</td>
</tr>
<tr>
<td>Bitcoin:</td>
<td>bc1qrmpahnvtqp34kpjaghnmq8acq27n0eke5w35ec</td>
</tr>
<tr>
<td>Etherium:</td>
<td>0x584b3ab1b31d7248e2c0ba5d317e9ba88a4fb1b4</td>
</tr>
<tr>
<td>Monero:</td>
<td>48namnfX17TX1kEGCpkXaRWhtw8p92cQjd5uQg7ivybgUuW4BTVaX8egxQhEi75JwuUGn3MDLKHYGNhu4eCfM6dRAAL2QAq</td>
</tr>
</table>
<div class="center">
<a href="https://www.donationalerts.com/r/arav">DonationAlerts</a>
<span><a href="https://www.tinkoff.ru/rm/andreev.aleksandr1164/5nVjK98501">T-bank</a> (<a href="https://www.tinkoff.ru/baf/5zRsqEQic6r">referal</a>)</span>
<a href="https://ruvds.com/pay/b5a7a24e142e4d30a46c7c8e09e8e07f">Help pay my VPS</a>
</div>
</section>
@base(i18n.T(ctx, "base.section.about"), "About me and my home servers.", "about, me, servcies", "/about", r, aboutHead()) {
if c := i18n.GetLocale(ctx).Code(); c == "ru" {
@aboutRu(services, r)
{{ return }}
}
@aboutEn(services, r)
}
}
templ aboutRu(services *servicestat.ServiceList, r *http.Request) {
<section id="about-me">
<h2>Обо мне</h2>
<p><b class="highlighted">Кто я?</b> Меня зовут Александр Андреев. Я простой русский чел 31 года от роду, который любит возиться с компьютерами.</p>
<p><b class="highlighted">Зачем делаю это всё?</b> Давненько хотел собственный веб-сайт, да и серваки всё равно 24 на 7 пашут, так что почему бы и нет? Да и практика никогда не помешает. :)</p>
<p><b class="highlighted">Почему я почти раскрыл себя?</b> Да, за каким-то хреном я разместил свои настоящие фамилию и имя здесь. А теперь поздно хвататься, т.к. всё уже разнеслось по веб-архивам, да и похер, если честно. :)</p>
<p><b class="highlighted">Почему такой слоган?</b> Хотелось что-нибудь воткнуть под названием сайта и эта фраза пришлась как раз. Не хочу особо филосовствовать. :) Но ведь странники мы, да? Иначе как ещё на подобные места натыкаться, если не странствовать по сети? :)</p>
<p><b class="highlighted"><s>Why English only?</s></b> Для большего охвата аудитории и практики я вёл этот сайт чисто на английском, да и две версии сайта вести было тупо лень, да и технически даже думать не хотелось как организовать перевод. :/ Но теперь всё поменялось! ^_^</p>
<p>А теперь небольшой перерыв ради...</p>
</section>
<section id="my-cat">
<h3>...моего кота Бориса :3</h3>
<div class="columns figs">
<figure>
<a href="/assets/img/photos/my_cat.webp">
<img src="/assets/img/photos/my_cat_thumb.webp" alt="My cat. :3" title=":3"/>
</a>
</figure>
<figure>
<a href="/assets/img/photos/my_cat_2.webp">
<img src="/assets/img/photos/my_cat_2_thumb.webp" alt="xDDDD" title="xDDDD"/>
</a>
</figure>
</div>
<p>А теперь продолжаем. :)</p>
</section>
<section id="more-about-me">
<h3>Хобби</h3>
<p>Видео-игры (с 1997)</p>
<p>Компьютеры (с 11 ноября 2004)</p>
<p><s>Просирание жизни</s> Странствие по интернетам (с февраля 2006)</p>
<p>Маппинг для Half-life 2, Counter-Strike: Source (с 2006, прекратил в 2009) (всё просрал, хотя, возможно лежит на нечитаемом IDE диске)</p>
<p>Написание музыки (с 2007, последний трек закончил в 2010, файлы проектов тоже проёбаны, но могут лежать на том диске)</p>
<p>Программирование (с 2007)</p>
<p><s>(Игры в сисадмина)</s> Домашние сервера (с 1 января 2017, когда настроил Raspberry Pi 3, что пришел днём ранее)</p>
<p>Программно Определяемое Радио (SDR, Software Defined Radio) (с июня 2018)</p>
<h3>Что знаю</h3>
<h4>Иностранные языки</h4>
<p>Покуда я люблю учить языки, отсутствие практической пользы и лень не дают мне нормально что-то выучить, так что я остановился на английском. Ранее брался учить немецкий, норвежский, французский, польский и японский. Конечно же знания у меня так себе, хорошо если прочесть могу, конечно по разному, разместил их в порядке убывания знаний.</p>
<p>Есть ещё один язык который я неплохо понимаю, но при этом никогда специально не учил, разве что смотрел отдельные слова ради интереса, и этот язык &mdash; украинский. За последнюю декаду прям прилип ко мне конкретно, хех. :) Та й взагалi, не розумiю тих, хто говорить, що зовсiм не розумiє українську. Її навiть не треба спецiйно вчити, просто читай контент на нiй, слухай й вона сама прилипне. :) Ну що тут можна додати? Тiльки слава Українi у складi Росiї! Все так, треба-треба. Хохли сосати! Тепер ви руськi всi. хД А якщо серйозно, хай мова продовжає iснувати, нiчого проти ней не маю, дуже гарна. Давайте жити дружно, хохли їбанi. :)</p>
<p>На счёт белорусского, примерно та же ситуация, однако, на нём я не могу разговаривать, так, знаю несколько слов, что случайно запомнились, но вполне понимаю, когда читаю на нём или слушаю песни.</p>
<h4>Компьютерные языки</h4>
<p>Используемые мною ныне языки: Go, JavaScript (vanilla), SQL, Python, Bash, AWK, HTML, CSS, LaTeX, Markdown, JSON, XML.</p>
<p>Ранее использовал (в хронологическом порядке): Pascal, Delphi, C#, C++, C, Java, PHP. Пробовал: Visual Basic, LISP, Haskell, Rust.</p>
<p>Так уж вышло, что я проэтовал весь код из прошлого. Да и 99% того, что былр написано в процессе изучения и по фану никогда не было закончено. Такой код я хладнокровно удалял. Да и на кой хранить, например, хеллоу ворлд для OpenGL?.. :)</p>
<p>А вот опыт, полученный в процессе, как раз никуда ни проэтовался. :) И мой <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceGit)) }>инстанс Gitea</a> вполне может говорить за меня.</p>
<p>У меня до сих пор валяется старый IDE НЖМД, что перестал видиться в системе в 2011. По крайней мере он раскручивается, да к тому же без каких-либо шумов страшных. Уже не помню что на нем, думаю там и совсем старый учебный код лежит, и карты, что создавал тогда для халфы с каэской... :)</p>
<h3>Что нравится</h3>
<h4>Аниме</h4>
<p>Ghost in the Shell, Shaman King, Hellsing, Steins;Gate, Cowboy Beebop, Ergo Proxy, Jin-Rou, Black Lagoon, Jojo's Bizzare Adventures, Spice and Wolf, Konosuba, Demon Slayer: Kimetsu no Yaiba.</p>
<h4>Фильмы</h4>
<p>Paths of Glory (1957), Boss Nigger (The Black Bounty Killer) (1974), Movies with Jackie Chan, Blade Runner (1982), WarGames (1983), Robocop (1987), Talk Radio (1988), Stargate (1994), Hackers (1995), Johnny Mnemonic (1995), Contact (1997), Matrix (1999, 2003), Snatch (2000), Oldboy (2003), The Day After Tomorrow (2004), Alpha Dog (2005), Constantine (2005), The Gingerdead Man (2005), Lucky Number Slevin (2006), 99 francs (2007), I Am Legend (2007), Inglourious Basterds (2009), Valhalla Rising (2009), The Guard (2011), Filth (2013), Mandariinid (2013), Gingerdead Man vs. Evil Bong (2013), Gone Girl (2014), Who am I (2014), Arrival (2016), Contratiempo (2016), Wandering Earth (2019), Wandering Earth 2 (2019), Greyhound (2020), I Care A Lot (2020), The Greatest Beer Run Ever (2022), Everything Everywhere All at Once (2022), Dungeons & Dragons: Honor Among Thieves (2023).</p>
<h4>Сериалы</h4>
<p>X-Files (1993&mdash;2002), Stargate: SG-1 (1997&mdash;2007), Stargate: Atlantis (2004&mdash;2009), Lost (2004&mdash;2010), Breaking Bad (2008&mdash;2013), Narcos (2015&mdash;2017), The Shivering Truth (2018&mdash;2020), Два холма (Two Hills) (2022).</p>
<h4>Игры для Dendy</h4>
<p>У меня была не просто Денди, а оная встроенная в клавиатуру, называлась СЮБОР.</p>
<p>Chip 'n Dale Rescue Rangers, а другая игра была гонкой формула 1. Ещё у сюбора был обучающий картридж, а на нём был клавиатурный тренажер, простой текстовый редактор, калькулятор, G-BASIC и F-BASIC, ещё был раздел с нашей 8-битной музыкой по типу Московских вечеров.</p>
<p>Хоть и был там бейсик, но программистом не стал, ибо мануала не было. Да и в интернете нашел инфу, что там были просто примеры кода без объяснения, дак ещё он и нерабочий был, ЛОЛ.</p>
<h4>Игры для SEGA Mega Drive</h4>
<p>Не много игр было мною играно.</p>
<p>Bubba'n'Stix, Battletoads, Granada, Demolition Man, Road Rash, Doom Troopers - The Mutant Chronicles, The Lost Vikings, Ghostbusters, Mig-29 Fighter Pilot, Street Racer.</p>
<h4>Игры для ПК</h4>
<p>Grand Theft Auto: Vice City, Half-Life (all), StarCraft, Diablo 2, Far Cry (2004), Battlefield: Vietnam, Delta Force: Black Hawk Down, Silent Hunter 3, Grand Theft Auto: San Andreas, Boiling Point: Road to Hell, Portal, Freelancer, F.E.A.R., S.T.A.L.K.E.R., Grand Theft Auto 4, Lineage 2, The Elder Scrolls V: Skyrim, Battlefield 3, The Walking Dead, The Wolf Among Us, Payday 2, The Witcher (1st, 2nd, 3rd didn't finished yet), Minecraft, Terraria, Starbound, Euro Truck Simulator 2, Mount &amp; Blade: Warband, Papers, Please, Insurgency, Elite: Dangerous, theHunter: Call of the Wild, American Truck Simulator, Rocket League, Sea Of Thieves, Tell Some Story: Foz.</p>
<h4>Музыка</h4>
<p>Прошу посетить <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceFiles)) + "/music" }>мою файловую шару</a>. :)</p>
</section>
<section id="servers-summary">
<h2>О моих серверах</h2>
<p>У меня два сервера, которые лежат на системнике. Первый это Raspberry Pi 3 rev. B, а второй &mdash; ноутбук Acer Packard Bell TE69CX. Не впечатляет, но то, что на них возложено исполняют в полной мере, конечно под реальной нагрузкой задохнуться, в этом сомнений нет. :)</p>
<p>У ноута следующие характеристики: проц Intel Pentium 2117U 1,8GHz с двумя ядрами, ОЗУ установлено 10ГБ (две плашки 8+2), системный диск это SSD на 120ГБ, а диск с данными на 2ТБ, и да, для данных всего один диск. Но не беспокойтесь, что нужно забекаплено (ну почти, за актуальностью бекапов плохо слежу %)).</p>
<p>К малинке прицеплен внешний НЖМД на 500ГБ и для системы и для данных.</p>
<p>А ещё я обзавёлся дешевой VPS-кой с 1 ядром на 2,2ГГц и 512МБ ОЗУ с диском на 10ГБ. Использую как вторичный сервер DNS и как рилей для отправки почты.</p>
<div class="columns figs">
<figure>
<a href="/assets/img/photos/raspi.webp">
<img src="/assets/img/photos/raspi_thumb.webp" alt="Raspberry Pi 3 rev. B" />
</a>
<figcaption>Raspberry Pi 3 rev. B</figcaption>
</figure>
<figure>
<a href="/assets/img/photos/acer.webp">
<img src="/assets/img/photos/acer_thumb.webp" alt="Acer Packard Bell TE69CX" title="Экран разбит, а клава просто перестала работать." />
</a>
<figcaption>Acer Packard Bell TE69CX</figcaption>
</figure>
</div>
</section>
<section id="services-public">
<h2>Публичные сервисы</h2>
<p class="center">Для всех.</p>
<div class="columns">
<div>
<h3 class={ isServiceUp("radio", services) }>Интернет-радио</h3>
<p>
<a href="https://radio.arav.su">radio.arav.su</a>.<a href="http://wsmkgnmhmzqm7kyzv7jnzzafvgm7xlmlfvzhgorpapd5or2arnhuktqd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://radio.arav.i2p">i2p</a><sup><a href="http://radio.arav.i2p/?i2paddresshelper=NfCKBu9vjLFiBMEPQGiZT9AzGlhkKHzYrKM66FL-ESeDbnYUY--NzukO9UA28s3WThhDQVge2TmyfYsaZiUw~AjuLsykxS13pebs7lkAVY1jm77La-eFFIAQ22Vtd2YgS0vbhRMzuDxKkCR1vPwNax8R2o6a07xsQvvDml6UQxG4p5vt44JA2geQNvQfm8cEiSa6gNJZJSW3rWuLDg6~1Jy3D70oSVSlNfihmG4JtNV6tVBjJE2h5gUxfhYZACttpGTPM~UNF~lrSujlBQsCqdzvLswdMw~FnvpfGzJcJroeFTerRyH6oUkkDSOK7uWwl0e70vKxrIbFgJjKtjlLWlUCI5N0TnJP4Hzt2pttB~R0hSr2vVl8ky0yJEtN3rwnrJkw7q0ZIH30ngTfxsCTbolAzl6liN9Ez5YF97zDOPnVFmvQ6Eg1PyFdypQO1PiUHqF56SWhx3utGwecUS6jJCvsKIJJVEIMVcD6h7S0z1g1rqQ4jbg5UfXPwFEgFOlzBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>Составлять программу вещания лень, да и не больно-то и нужно. Просто закинуть музыку, перемешать. :)</p>
<p>Технически устроено так: <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceGit) + "/Arav/dwelling-radio") }>dwelling-radio</a> (помимо фронта, ещё и плейлист выдаёт и следит за статами) &xrArr; Ezstream &xrArr; Icecast &xrArr; NGiNX.</p>
</div>
<div>
<h3 class={ isServiceUp("dwelling-files", services) }>Файловая шара</h3>
<p>
<a href="https://files.arav.su">files.arav.su</a>.<a href="http://qf5e43nlhvnrutmikuvbdfj3cmtthokpbaxtkm6mjlslttzvtgm4fxid.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://files.arav.i2p">i2p</a><sup><a href="http://files.arav.i2p/?i2paddresshelper=48vtYgeVnju7B2FaR0zxUL3MQXN9QjK~Ggya45aANwm86mtpemuEkaskJmEQaFSd4FcDAFIiXHfNpfGqoupLwNmtgBmGRcuVV8xb2W~W6lM0oOhovjB37EUaMWs3AI5aIES84QOqApgwYX-ANIcwa~Kg6AbMuX8D8qnejuhBbuCffYah-TD8e~O0cnyqxzLTmxIGCyk2egdYXwanJyYFDocomIVfcqfJ0MgjIHhFQtkcb0e84bxvDzcAFIpEDrzAo4GVrFn-TCu0Lyf2ccqmVpucFl0UGhuVRxEt19KLd3PxlfwHv2lmzTZtq9CbnfaoPntUPx1sf84QnZDmrXWhVK8p3VvuPZMxjyz9KyhPjrGkO4E0oibDlvKuMsGEm-GkZsKxgXo~CrdcVtN8suAwW6rACAuk8gq2jUMBZBZ12migPZ7miHftEkOFHfgfUiKBwirrw~y9Zi261WX4-EVe2oD4pkhQOrqOKIoI-vv5z9CpQ7PKL531kgkipcBseXybBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>Всё чем могу поделиться. Музыка, видосы всякие, книги, игры, программы, немного драйверов, образы с виндой. В общем, заходите.</p>
</div>
<div>
<h3 class={ isServiceUp("dwelling-upload", services) }>Файлообменник</h3>
<p>
<a href="https://upload.arav.su">upload.arav.su</a>.<a href="http://4usftbmjpfexkr2x5xbp5ukmygpmg4fgrnx2wbifsexqctooz5hmviyd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://upload.arav.i2p">i2p</a><sup><a href="http://upload.arav.i2p/?i2paddresshelper=b5NWA2vNydWSv6~8KN4e~td2UVGkYsayKPa1PnXI87A3gsg6m978tIehHLVN4XcCfUq4aB-59hqqZicorRnHKfV3lVdx9mdhC8Bhj~bMAcwMgWoXidqZNrWMoFGzWotFsa3nWh4zsRUSfrokecC8u9Y06byfSS1siyak0J6xpsggXRqqgNF0-8ncPeqvzBxHB9NRDXWEVJGS9HSpydWl1UpjgZffcd~NZroxkSAfughHcFAn2OLKkaZRe6WqCJQfJoXTCyz4wkFmYbH1CSddWlddmWaaU7icsbQrZm3XEqKTVKvm86G6ehxmzyHqCumc4GOWswcP0E51UQVOv-WA8R6SWQAj6ZnZhnCoCNFFEfW2lBiDmTnLJbfm-C-AdI6G1~dQ1~3FCH6wXWy-2DebpyoVVt9epzU7l4l2MVeaOUahbf6wcol1UbxPoR0XlGCXDe9700TYePjtpOU9vNkk2B1dQiZ1usgwseYuO26cRogSvbi8poz4BlCNO733HR1XBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>Сделал свой собственный файлообменник, которым решил поделиться с миром. Лимит 128МБ на файл, хранение 36 часов, а всего выделил 100ГиБ под него.</p>
</div>
<div>
<h3>Ретранслятор Tor</h3>
<p><a href="https://metrics.torproject.org/rs.html#details/CEF2FD0E1973EA04D1444DDAEFF1B0BC3C0C39B1" rel="nofollow noreferrer">metrics.torproject.org</a></p>
<p><b>С 1 декабря 2021 Tor заблокирован в России, так что нет больше релея.</b></p>
</div>
<div>
<h3>Роутер I2P</h3>
<p>Помогаю сети и хосчусь сам с помощью i2pd.</p>
</div>
</div>
</section>
<section id="services-private">
<h2>Приватные сервисы</h2>
<p class="center">Для себя и друзей.</p>
<div class="columns">
<div>
<h3 class={ isServiceUp("mail", services) }>Сервер E-Mail</h3>
<p>Postfix, Dovecot (w/Sieve), rspamd, ClamAV.</p>
</div>
<div>
<h3 class={ isServiceUp("mumble", services) }>Mumble</h3>
<p><a href="mumble://arav.su">mumble://arav.su</a></p>
<p>Работает на uMurmur. Защищен паролем.</p>
</div>
<div>
<h3 class={ isServiceUp("teamspeak3", services) }>TeamSpeak 3</h3>
<p><a href="ts3server://arav.su">ts3server://arav.su</a></p>
<p>Для чужаков (незарегистрированных) доступна только комната Entrance room. Также установил ограничение по минимальному уровню секьюрности идентификатора равным 29.</p>
</div>
<div>
<h3 class={ isServiceUp("git", services) }>Git</h3>
<p>
<a href="https://git.arav.su">git</a>.<a href="http://qqitm7qlsbbubwmjos4cqzmvkqidg34rfnbyhuydhalep33fbvh22xyd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://git.arav.i2p">i2p</a><sup><a href="http://git.arav.i2p/?i2paddresshelper=eFIfcBUv3lHFSnglHfncs5XXtYwm9gCpmAYuio~9CeENBAXKRggPiY1tQC-otCon2hCSpr56WlVBeZk1txKuUnbjHTN7GBFaKW5wJEO2WmKEWPKdcjUDOYZN0D3TwXaYfiBuELD3200lBfDmPEJ01iC2o7B5yvpOqtEKDcaqkIp4vafDuPPumJ~XiCGdUAe~vr52w3Tbuz5x7wbltk-gUELY0-ZAQBos4jOJ6QT1W1lhycHPhAK8qslgwfk94opyIl2pkRyuJhU-2VHc6Fsd621VXC86YAMT1SIfTZlFpoGVCFXDM~BXaLvygFaKf62qardAe0T48Ax6GxosAKXe-yLCVRaiD3KErULfwZXl23kQzRfxM4odG4DWeXawtuvypOmTjHT1skQHU0h52ujye5nT~2bOy14HkCoCnxJ7gSj3MjkmWLd1JhBsPH4ymRmI7jFJR1GYl8Wp5IigMBBzWfJUEEjS7QDHaRo5TCZJ9SXz6sgkGdfh74~r8FWL559gBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>Gitea. Вход на посмотреть/взять свободный. Всё остальное с аккаунтом.</p>
</div>
</div>
</section>
<section id="services-games">
<h2>Игровые сервера</h2>
<div class="columns">
<div>
<h3 class={ isServiceUp("game-minecraft", services) }>Minecraft</h3>
<p class="highlighted">arav.su:25565</p>
<p><a href="/minemap">Карта мира</a></p>
<p>Сейчас работает на версии 1.21 с API Fabric. Для игры здесь требуется только fabric-api.</p>
</div>
</div>
</section>
<section id="services-inner">
<h2>Внутренние сервисы</h2>
<p class="center">Сюда входят вспомогательные сервисы и сугубо мной используемые.</p>
<div class="columns">
<div>
<h3>Web-server</h3>
<p>NGiNX. Что ещё добавить?</p>
</div>
<div>
<h3>Database</h3>
<p>Раньше использовал MariaDB, сейчас сервисы перевёл на SQLite3, в будущем если будет надо, то уже PostgreSQL буду использовать.</p>
</div>
<div>
<h3>VPN</h3>
<p><s>OpenVPN</s> Wireguard.</p>
</div>
<div>
<h3>Сетевое хранилище данных</h3>
<p>Samba и NFSv4.</p>
</div>
<div>
<h3>Торренты</h3>
<p>Использую transmission-cli. Одна вещь есть раздражающая, временами он создаёт .part-файлы для одного из проигнорированных файлов.</p>
</div>
<div>
<h3>Печать</h3>
<p>CUPS с ccpd (Canon CAPT printer).</p>
<p>Хз, то работает и так, а то и после перезагрузки никак не заведешь, уже подзабил и просто перетыкаю в свой комп принтер, один хер дома печатаю. :)</p>
</div>
<div>
<h3>DNS</h3>
<p>BIND9 через DNSCrypt-proxy.</p>
<p>Для локалки остановился на домене arav.home.arpa (для уникальности, а то вдруг с чьей локалкой надо будет объединиться, хех), .home.arpa введён в RFC 8375 как домен специального назначения для пользования внутри ЛВС.</p>
<p>Основной сервер живёт на ноуте, вторичные на малинке и на VPS, но, конечно же, на VPS только внешний домен, и VPS не является рекурсивным, в отличие от первых двух.</p>
</div>
</div>
</section>
<section id="contacts">
<h2>Контакты</h2>
<span>E-Mail:&nbsp;<a href="mailto:me@arav.su">me@arav.su</a></span>
<span>PGP&nbsp;ключ:&nbsp;<a href="/assets/pgp.asc">7398 50CD 5051 DE55 4368 7092 2596 9B23 DCB5 CA34</a></span>
</section>
<section id="donation">
<h2>Пожертвования</h2>
<p class="center">Просто на всякий. %^)</p>
<table>
<tr>
<td>USDT&nbsp;(TRC&nbsp;20):</td>
<td>TGSEiAh9nAhCL6YPVA6zHUsnuoccW8tjep</td>
</tr>
<tr>
<td>USDT&nbsp;(ERC&nbsp;20):</td>
<td>0x584b3ab1b31d7248e2c0ba5d317e9ba88a4fb1b4</td>
</tr>
<tr>
<td>TON:</td>
<td>EQC4L0tZMDZ8IPGbyXQafoh2n-N9HbJwVp5EtrYGsRCuR28G</td>
</tr>
<tr>
<td>Bitcoin:</td>
<td>bc1qrmpahnvtqp34kpjaghnmq8acq27n0eke5w35ec</td>
</tr>
<tr>
<td>Etherium:</td>
<td>0x584b3ab1b31d7248e2c0ba5d317e9ba88a4fb1b4</td>
</tr>
<tr>
<td>Monero:</td>
<td>48namnfX17TX1kEGCpkXaRWhtw8p92cQjd5uQg7ivybgUuW4BTVaX8egxQhEi75JwuUGn3MDLKHYGNhu4eCfM6dRAAL2QAq</td>
</tr>
</table>
<div class="center">
<a href="https://www.donationalerts.com/r/arav">DonationAlerts</a>
<span><a href="https://www.tinkoff.ru/rm/andreev.aleksandr1164/5nVjK98501">T-банк</a> (<a href="https://www.tinkoff.ru/baf/5zRsqEQic6r">рефералка</a>)</span>
<a href="https://ruvds.com/pay/b5a7a24e142e4d30a46c7c8e09e8e07f">Моя VPS-ка</a>
</div>
</section>
}
templ aboutEn(services *servicestat.ServiceList, r *http.Request) {
<section id="about-me">
<h2>Me</h2>
<p><b class="highlighted">Who am I?</b> My name is <span class="highlighted">A</span>lexande<span class="highlighted">r</span> <span class="highlighted">A</span>ndree<span class="highlighted">v</span>. I'm a russian guy of age 31 who likes tinkering with computers.</p>
<p><b class="highlighted">Why am I doing all of this?</b> Machines are up 24/7 anyway, so why not? And I wanted a website long ago, just didn't know what to put on it. Like if I do now... :)</p>
<p><b class="highlighted">Why am I almost &ldquo;doxxing&rdquo; myself?</b> Yes, my real first and last names and age are here, and since I self-host you can get my city as well. And I simply don't see this as a problem. :|</p>
<p><b class="highlighted">Why particularly that slogan?</b> It was the first thing that went on my mind. Don't you think of your website as of a special place of your own? Sacred in some way..? And what else do we do if not wandering through the vastness of Internet looking for something? Think about it... :)</p>
<p><b class="highlighted">Why English only?</b> I want this place to be accessible for a wide audience and English happen to be todays lingua franca, and to practice the language of course.</p>
<p>Now a little break for...</p>
</section>
<section id="my-cat">
<h3>My kot Boris :3</h3>
<div class="columns figs">
<figure>
<a href="/assets/img/photos/my_cat.webp">
<img src="/assets/img/photos/my_cat_thumb.webp" alt="My cat. :3" title=":3"/>
</a>
</figure>
<figure>
<a href="/assets/img/photos/my_cat_2.webp">
<img src="/assets/img/photos/my_cat_2_thumb.webp" alt="xDDDD" title="xDDDD"/>
</a>
</figure>
</div>
<p>And here we continue. :)</p>
</section>
<section id="more-about-me">
<h3>Hobbies</h3>
<p>Video games (since 1997)</p>
<p>Computers (since 11th November 2004)</p>
<p><s>Wasting my life on</s> Surfing the Internets (since February 2006)</p>
<p>Mapping for Half-life 2, Counter-Strike: Source (since 2006, discontinued in 2009) (everything's fuarrkin' lost, or maybe it is still on a broken IDE drive)</p>
<p>Music writing (since 2007, last track was made in 2010)</p>
<p>Programming (since 2007)</p>
<p><s>(LARP'ing as a system administrator)</s> Home servers (since 1st January 2017, when I had set up my Raspberry Pi I got the day before)</p>
<p>Software Defined Radio (since June 2018)</p>
<h3>What I know</h3>
<h4>Human languages</h4>
<p>While I like learning foreign languages, lack of usefulness for me and my lazyness prevents me from getting on any reasonable level, so I stuck to English. Knowledge of other languages I tried to learn, which are German, Norwegian, French, Polish, and Japanese, is minuscle and only declining.</p>
<p>The other language I understand well, and can somehow speak is Ukrainian, which is no surprise because of its relation with Russian. At least it should be not, yet I see that many Russians don't understand Ukrainian like at all, which is surprising for me. I accidentally learnt it just by consuming content in it with help of a dictionary to look up some words that are archaic in Russian or have different etymology.</p>
<p>As for Belarussian, situation is the same, but I don't speak it, just know some words I have accidentally memorised while listening to music.</p>
<h4>Computer languages</h4>
<p>All the programming, markup and declarative languages I use by now are Go, JavaScript (vanilla), SQL, Python, Bash, AWK, HTML, CSS, LaTeX, Markdown, JSON, XML.</p>
<p>Previously I used (in a chronological order) Pascal, Delphi, C#, C++, C, Java, PHP. Took a taste of Visual Basic, LISP, Haskell, Rust.</p>
<p>It so happened that I didn't save the source code from the past. 99% of it was written purely for education and fun, and usually never get finished. And such a code was heartlessly deleted by me. Why would I keep OpenGL hello world that draws triangles..? :)</p>
<p>At least an experience I gained isn't going anywhere. :) And I think what is on my <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceGit)) }>Gitea instance</a> can speak for me.</p>
<p>I still have an old IDE drive that got broken back in 2011. BIOS cannot see it, but it is spinning, even without any crack noises. Maybe it still has some old code. And some more from that time...</p>
<h3>What I liked</h3>
<h4>Anime</h4>
<p>Ghost in the Shell, Shaman King, Hellsing, Steins;Gate, Cowboy Beebop, Ergo Proxy, Jin-Rou, Black Lagoon, Jojo's Bizzare Adventures, Spice and Wolf, Konosuba, Demon Slayer: Kimetsu no Yaiba.</p>
<h4>Films</h4>
<p>Paths of Glory (1957), Boss Nigger (The Black Bounty Killer) (1974), Movies with Jackie Chan, Blade Runner (1982), WarGames (1983), Robocop (1987), Talk Radio (1988), Stargate (1994), Hackers (1995), Johnny Mnemonic (1995), Contact (1997), Matrix (1999, 2003), Snatch (2000), Oldboy (2003), The Day After Tomorrow (2004), Alpha Dog (2005), Constantine (2005), The Gingerdead Man (2005), Lucky Number Slevin (2006), 99 francs (2007), I Am Legend (2007), Inglourious Basterds (2009), Valhalla Rising (2009), The Guard (2011), Filth (2013), Mandariinid (2013), Gingerdead Man vs. Evil Bong (2013), Gone Girl (2014), Who am I (2014), Arrival (2016), Contratiempo (2016), Wandering Earth (2019), Wandering Earth 2 (2019), Greyhound (2020), I Care A Lot (2020), The Greatest Beer Run Ever (2022), Everything Everywhere All at Once (2022), Dungeons & Dragons: Honor Among Thieves (2023).</p>
<h4>TV series</h4>
<p>X-Files (1993&mdash;2002), Stargate: SG-1 (1997&mdash;2007), Stargate: Atlantis (2004&mdash;2009), Lost (2004&mdash;2010), Breaking Bad (2008&mdash;2013), Narcos (2015&mdash;2017), The Shivering Truth (2018&mdash;2020), Два холма (Two Hills) (2022).</p>
<h4>Games for Dendy (NES/Famicom clone)</h4>
<p>I had not just a Dendy console, no, it was embedded in a keyboard and it was named SUBOR.</p>
<p>Chip 'n Dale Rescue Rangers, and the other was an F1 game which name I don't know. Also, SUBOR had its own special cartridge called training cartridge. It had a keyboard trainer, a simple text editor, calculator, G-BASIC and F-BASIC, also had classic russian music like Moscow Nights in 8-bit.</p>
<p>Despite having BASIC on that cartridge I had no opportunity to start programming because I didn't have a manual. Anyway, I read that there was just code examples and most of them didn't work, LOL.</p>
<h4>Games for SEGA Mega Drive</h4>
<p>Not a lot of games I have played.</p>
<p>Bubba'n'Stix, Battletoads, Granada, Demolition Man, Road Rash, Doom Troopers - The Mutant Chronicles, The Lost Vikings, Ghostbusters, Mig-29 Fighter Pilot, Street Racer.</p>
<h4>Games for PC</h4>
<p>Grand Theft Auto: Vice City, Half-Life (all), StarCraft, Diablo 2, Far Cry (2004), Battlefield: Vietnam, Delta Force: Black Hawk Down, Silent Hunter 3, Grand Theft Auto: San Andreas, Boiling Point: Road to Hell, Portal, Freelancer, F.E.A.R., S.T.A.L.K.E.R., Grand Theft Auto 4, Lineage 2, The Elder Scrolls V: Skyrim, Battlefield 3, The Walking Dead, The Wolf Among Us, Payday 2, The Witcher (1st, 2nd, 3rd didn't finished yet), Minecraft, Terraria, Starbound, Euro Truck Simulator 2, Mount &amp; Blade: Warband, Papers, Please, Insurgency, Elite: Dangerous, theHunter: Call of the Wild, American Truck Simulator, Rocket League, Sea Of Thieves, Tell Some Story: Foz.</p>
<h4>Music</h4>
<p>Go check out <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceFiles)) }>my file share</a>. :)</p>
</section>
<section id="servers-summary">
<h2>My servers</h2>
<p>I have two servers laying on my PC which are a Raspberry Pi 3 rev. B single board computer and a laptop Acer Packard Bell TE69CX. Not quite impressive, I'd say, but they do what I need from them just fine, not for a real heavy load of course.</p>
<p>The laptop has a 2 core Intel Pentium 2117U 1.8GHz CPU and 10GB of RAM (2GB + 8GB), a system disk is a 120GB SSD, and a disk I use to store all the shit is a 2TB HDD, yeah, just one drive for data. Anything worthwhile is backed up (LOL, not really :^)).</p>
<p>For Raspberry Pi I use a 500GB HDD as a system/data disk.</p>
<p>Also I have a cheap VPS with 1 core 2.2GHz CPU and 512MB RAM, and a 10GB disk I use as a slave DNS server for my domain and a Postfix mail relay.</p>
<div class="columns figs">
<figure>
<a href="/assets/img/photos/raspi.webp">
<img src="/assets/img/photos/raspi_thumb.webp" alt="Raspberry Pi 3 rev. B" />
</a>
<figcaption>Raspberry Pi 3 rev. B</figcaption>
</figure>
<figure>
<a href="/assets/img/photos/acer.webp">
<img src="/assets/img/photos/acer_thumb.webp" alt="Acer Packard Bell TE69CX" title="Screen and keyboard are broken." />
</a>
<figcaption>Acer Packard Bell TE69CX</figcaption>
</figure>
</div>
</section>
<section id="services-public">
<h2>Public services</h2>
<p class="center">For everyone.</p>
<div class="columns">
<div>
<h3 class={ isServiceUp("radio", services) }>Internet-radio</h3>
<p>
<a href="https://radio.arav.su">radio.arav.su</a>.<a href="http://wsmkgnmhmzqm7kyzv7jnzzafvgm7xlmlfvzhgorpapd5or2arnhuktqd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://radio.arav.i2p">i2p</a><sup><a href="http://radio.arav.i2p/?i2paddresshelper=NfCKBu9vjLFiBMEPQGiZT9AzGlhkKHzYrKM66FL-ESeDbnYUY--NzukO9UA28s3WThhDQVge2TmyfYsaZiUw~AjuLsykxS13pebs7lkAVY1jm77La-eFFIAQ22Vtd2YgS0vbhRMzuDxKkCR1vPwNax8R2o6a07xsQvvDml6UQxG4p5vt44JA2geQNvQfm8cEiSa6gNJZJSW3rWuLDg6~1Jy3D70oSVSlNfihmG4JtNV6tVBjJE2h5gUxfhYZACttpGTPM~UNF~lrSujlBQsCqdzvLswdMw~FnvpfGzJcJroeFTerRyH6oUkkDSOK7uWwl0e70vKxrIbFgJjKtjlLWlUCI5N0TnJP4Hzt2pttB~R0hSr2vVl8ky0yJEtN3rwnrJkw7q0ZIH30ngTfxsCTbolAzl6liN9Ez5YF97zDOPnVFmvQ6Eg1PyFdypQO1PiUHqF56SWhx3utGwecUS6jJCvsKIJJVEIMVcD6h7S0z1g1rqQ4jbg5UfXPwFEgFOlzBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>I'm too lazy to make some kind of broadcasting program, so I just throw anything I like and randomise the playlist. :)</p>
<p>Technically it runs as follows: <a href={ templ.SafeURL(util.GetServiceByHost(r.Host, util.ServiceGit) + "/Arav/dwelling-radio") }>dwelling-radio</a> &xrArr; Ezstream &xrArr; Icecast &xrArr; NGiNX.</p>
</div>
<div>
<h3 class={ isServiceUp("dwelling-files", services) }>File share</h3>
<p>
<a href="https://files.arav.su">files.arav.su</a>.<a href="http://qf5e43nlhvnrutmikuvbdfj3cmtthokpbaxtkm6mjlslttzvtgm4fxid.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://files.arav.i2p">i2p</a><sup><a href="http://files.arav.i2p/?i2paddresshelper=48vtYgeVnju7B2FaR0zxUL3MQXN9QjK~Ggya45aANwm86mtpemuEkaskJmEQaFSd4FcDAFIiXHfNpfGqoupLwNmtgBmGRcuVV8xb2W~W6lM0oOhovjB37EUaMWs3AI5aIES84QOqApgwYX-ANIcwa~Kg6AbMuX8D8qnejuhBbuCffYah-TD8e~O0cnyqxzLTmxIGCyk2egdYXwanJyYFDocomIVfcqfJ0MgjIHhFQtkcb0e84bxvDzcAFIpEDrzAo4GVrFn-TCu0Lyf2ccqmVpucFl0UGhuVRxEt19KLd3PxlfwHv2lmzTZtq9CbnfaoPntUPx1sf84QnZDmrXWhVK8p3VvuPZMxjyz9KyhPjrGkO4E0oibDlvKuMsGEm-GkZsKxgXo~CrdcVtN8suAwW6rACAuk8gq2jUMBZBZ12migPZ7miHftEkOFHfgfUiKBwirrw~y9Zi261WX4-EVe2oD4pkhQOrqOKIoI-vv5z9CpQ7PKL531kgkipcBseXybBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>There you'll find music, videos, books, games, programs, drivers (a very few), OS images (Winblows mainly). Go check it out!</p>
</div>
<div>
<h3 class={ isServiceUp("dwelling-upload", services) }>File upload</h3>
<p>
<a href="https://upload.arav.su">upload.arav.su</a>.<a href="http://4usftbmjpfexkr2x5xbp5ukmygpmg4fgrnx2wbifsexqctooz5hmviyd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://upload.arav.i2p">i2p</a><sup><a href="http://upload.arav.i2p/?i2paddresshelper=b5NWA2vNydWSv6~8KN4e~td2UVGkYsayKPa1PnXI87A3gsg6m978tIehHLVN4XcCfUq4aB-59hqqZicorRnHKfV3lVdx9mdhC8Bhj~bMAcwMgWoXidqZNrWMoFGzWotFsa3nWh4zsRUSfrokecC8u9Y06byfSS1siyak0J6xpsggXRqqgNF0-8ncPeqvzBxHB9NRDXWEVJGS9HSpydWl1UpjgZffcd~NZroxkSAfughHcFAn2OLKkaZRe6WqCJQfJoXTCyz4wkFmYbH1CSddWlddmWaaU7icsbQrZm3XEqKTVKvm86G6ehxmzyHqCumc4GOWswcP0E51UQVOv-WA8R6SWQAj6ZnZhnCoCNFFEfW2lBiDmTnLJbfm-C-AdI6G1~dQ1~3FCH6wXWy-2DebpyoVVt9epzU7l4l2MVeaOUahbf6wcol1UbxPoR0XlGCXDe9700TYePjtpOU9vNkk2B1dQiZ1usgwseYuO26cRogSvbi8poz4BlCNO733HR1XBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>I've made a file upload service for ya with a limit of 128MiB per file, keeping it for 36 hours, and overall storage I dedicated for it is 100GiB.</p>
</div>
<div>
<h3>Tor relay</h3>
<p><a href="https://metrics.torproject.org/rs.html#details/CEF2FD0E1973EA04D1444DDAEFF1B0BC3C0C39B1" rel="nofollow noreferrer">metrics.torproject.org</a></p>
<p><b>Since 1st December 2021 Tor is blocked in Russia, so the relay is down.</b></p>
</div>
<div>
<h3>I2P router</h3>
<p>I help the network using i2pd router.</p>
</div>
</div>
</section>
<section id="services-private">
<h2>Private services</h2>
<p class="center">For a narrow circle of people.</p>
<div class="columns">
<div>
<h3 class={ isServiceUp("mail", services) }>E-Mail server</h3>
<p>Postfix, Dovecot (w/Sieve), rspamd, ClamAV.</p>
</div>
<div>
<h3 class={ isServiceUp("mumble", services) }>Mumble</h3>
<p><a href="mumble://arav.su">mumble://arav.su</a></p>
<p>Runs with uMurmur. Protected by password.</p>
</div>
<div>
<h3 class={ isServiceUp("teamspeak3", services) }>TeamSpeak 3</h3>
<p><a href="ts3server://arav.su">ts3server://arav.su</a></p>
<p>For strangers (unregs) only an Entrance room is available. Your identifier should have a security level greater or equal to 29.</p>
</div>
<div>
<h3 class={ isServiceUp("git", services) }>Git</h3>
<p>
<a href="https://git.arav.su">git</a>.<a href="http://qqitm7qlsbbubwmjos4cqzmvkqidg34rfnbyhuydhalep33fbvh22xyd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::e]">ygg</a>.<a href="http://git.arav.i2p">i2p</a><sup><a href="http://git.arav.i2p/?i2paddresshelper=eFIfcBUv3lHFSnglHfncs5XXtYwm9gCpmAYuio~9CeENBAXKRggPiY1tQC-otCon2hCSpr56WlVBeZk1txKuUnbjHTN7GBFaKW5wJEO2WmKEWPKdcjUDOYZN0D3TwXaYfiBuELD3200lBfDmPEJ01iC2o7B5yvpOqtEKDcaqkIp4vafDuPPumJ~XiCGdUAe~vr52w3Tbuz5x7wbltk-gUELY0-ZAQBos4jOJ6QT1W1lhycHPhAK8qslgwfk94opyIl2pkRyuJhU-2VHc6Fsd621VXC86YAMT1SIfTZlFpoGVCFXDM~BXaLvygFaKf62qardAe0T48Ax6GxosAKXe-yLCVRaiD3KErULfwZXl23kQzRfxM4odG4DWeXawtuvypOmTjHT1skQHU0h52ujye5nT~2bOy14HkCoCnxJ7gSj3MjkmWLd1JhBsPH4ymRmI7jFJR1GYl8Wp5IigMBBzWfJUEEjS7QDHaRo5TCZJ9SXz6sgkGdfh74~r8FWL559gBQAEAAcAAA==" title="Address helper">ah</a></sup>
</p>
<p>Gitea. Anything I think is worth sharing is public. Private in terms of who can have account here.</p>
</div>
</div>
</section>
<section id="services-games">
<h2>Game servers</h2>
<div class="columns">
<div>
<h3 class={ isServiceUp("game-minecraft", services) }>Minecraft</h3>
<p class="highlighted">arav.su:25565</p>
<p><a href="/minemap">Web world map</a></p>
<p>Now runs a version 1.21 with Fabric. Just a fabric-api is needed to play.</p>
</div>
</div>
</section>
<section id="services-inner">
<h2>Inner services</h2>
<p class="center">Maintains other services or used exclusively by me.</p>
<div class="columns">
<div>
<h3>Web-server</h3>
<p>NGiNX. Nuff said.</p>
</div>
<div>
<h3>Database</h3>
<p>Used to run MariaDB, now my services use SQLite3.</p>
</div>
<div>
<h3>VPN</h3>
<p><s>OpenVPN</s> Wireguard.</p>
</div>
<div>
<h3>Network file storage</h3>
<p>Samba and NFSv4.</p>
</div>
<div>
<h3>Torrents</h3>
<p>I use transmission-cli. One annoying thing, it creates .part files for one of ignored files.</p>
</div>
<div>
<h3>Printing</h3>
<p>CUPS with ccpd (Canon CAPT printer).</p>
<p>It is guaranteed to work after reboot. :) If a kernel got updated &mdash; reboot. If you didn't use it for a long time and restart of CUPS and ccpd services after connecting a printer didn't work &mdash; reboot. xD</p>
</div>
<div>
<h3>DNS</h3>
<p>BIND9 via DNSCrypt-proxy.</p>
<p>For LAN I use &ldquo;arav.home.arpa&rdquo; domain. &ldquo;.home.arpa&rdquo; part is a special-use domain introduced in RFC 8375.</p>
<p>Master server lives on the laptop. It serves my external domain, internal one, and work as a recursion server to serve DNS queries from LAN. Raspberry Pi is a slave for the internal domain and recursion. And on the VPS lives a slave for my external domain.</p>
</div>
</div>
</section>
<section id="contacts">
<h2>Contacts</h2>
<span>E-Mail:&nbsp;<a href="mailto:me@arav.su">me@arav.su</a></span>
<span>PGP&nbsp;key:&nbsp;<a href="/assets/pgp.asc">7398 50CD 5051 DE55 4368 7092 2596 9B23 DCB5 CA34</a></span>
</section>
<section id="donation">
<h2>Donation</h2>
<p class="center">Just in case. %^)</p>
<table>
<tr>
<td>USDT&nbsp;(TRC&nbsp;20):</td>
<td>TGSEiAh9nAhCL6YPVA6zHUsnuoccW8tjep</td>
</tr>
<tr>
<td>USDT&nbsp;(ERC&nbsp;20):</td>
<td>0x584b3ab1b31d7248e2c0ba5d317e9ba88a4fb1b4</td>
</tr>
<tr>
<td>TON:</td>
<td>EQC4L0tZMDZ8IPGbyXQafoh2n-N9HbJwVp5EtrYGsRCuR28G</td>
</tr>
<tr>
<td>Bitcoin:</td>
<td>bc1qrmpahnvtqp34kpjaghnmq8acq27n0eke5w35ec</td>
</tr>
<tr>
<td>Etherium:</td>
<td>0x584b3ab1b31d7248e2c0ba5d317e9ba88a4fb1b4</td>
</tr>
<tr>
<td>Monero:</td>
<td>48namnfX17TX1kEGCpkXaRWhtw8p92cQjd5uQg7ivybgUuW4BTVaX8egxQhEi75JwuUGn3MDLKHYGNhu4eCfM6dRAAL2QAq</td>
</tr>
</table>
<div class="center">
<a href="https://www.donationalerts.com/r/arav">DonationAlerts</a>
<span><a href="https://www.tinkoff.ru/rm/andreev.aleksandr1164/5nVjK98501">T-bank</a> (<a href="https://www.tinkoff.ru/baf/5zRsqEQic6r">referal</a>)</span>
<a href="https://ruvds.com/pay/b5a7a24e142e4d30a46c7c8e09e8e07f">Help pay my VPS</a>
</div>
</section>
}
func isServiceUp(service string, services *servicestat.ServiceList) string {
if v, ok := (*services)[service]; ok && v {
return "service-up"

View File

@ -4,14 +4,15 @@ import "time"
import "net/http"
import "git.arav.su/Arav/dwelling-home/pkg/util"
import "github.com/invopop/ctxi18n/i18n"
templ Article(title, description, body, urlName string, date time.Time, r *http.Request) {
@base(title + " - Stuff", description, "", "/stuff/article/"+urlName, articleHead()) {
@base(title + " - " + i18n.T(ctx, "base.section.stuff"), description, "", "/stuff/article/"+urlName, r, articleHead()) {
<article>
<header>
<h2>{ title }</h2>
<div class="menu">
<a href="/stuff#articles">Go back to articles list</a>
<a href="/stuff#articles">{ i18n.T(ctx, "article.go-back") }</a>
{{ dctz := util.ToClientTimezone(date, r) }}
<time datetime={ dctz.Format("2006-01-02") }>{ dctz.Format("02 January 2006") }</time>
</div>

View File

@ -1,6 +1,6 @@
body {
margin-top: 25vh;
min-height: 75vh; }
margin-top: 18vh;
min-height: 82vh; }
header.main {
align-items: center;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -13,8 +13,9 @@ async function getNewCaptcha() {
g_captcha_timeout_remain = g_captcha_timeout_seconds;
}
e_captcha.children[3].innerHTML =
`<button id="refresh">Refresh</button>ed in <b><span id="remain">600</span></b> seconds.`;
e_captcha.children[3].innerHTML = document.cookie.includes("lang=ru") ?
`<button id="refresh">Обновит</button>ся через <b><span id="remain">600</span></b> секунд(у).`
: `<button id="refresh">Refresh</button>ed in <b><span id="remain">600</span></b> seconds.`;
const captcha_refresh = document.getElementById("refresh");
const captcha_remain = document.getElementById("remain");

View File

@ -34,7 +34,7 @@
</url>
<url>
<loc>https://arav.su/about</loc>
<lastmod>2024-04-16</lastmod>
<lastmod>2024-07-01</lastmod>
</url>
<url>
<loc>https://arav.su/guestbook</loc>

View File

@ -1,8 +1,14 @@
package web
import "strings"
import "net/http"
templ base(title, description, keywords, canonical string, head templ.Component) {
import "github.com/invopop/ctxi18n/i18n"
import "git.arav.su/Arav/dwelling-home/internal/version"
import "git.arav.su/Arav/dwelling-home/pkg/util"
templ base(title, description, keywords, canonical string, r *http.Request, head templ.Component) {
<!DOCTYPE html>
<html>
<head>
@ -21,7 +27,7 @@ templ base(title, description, keywords, canonical string, head templ.Component)
<link rel="stylesheet" href="/assets/css/main.css"/>
<link rel="alternate" href="/rss.xml" type="application/rss+xml" title="Arav's dwelling"/>
if canonical != "" {
<link rel="canonical" href={ string(templ.URL(canonical)) }/>
<link rel="canonical" href={ util.GetServiceByHost(r.Host, util.ServiceHome) + canonical }/>
}
if head != nil {
@head
@ -33,12 +39,12 @@ templ base(title, description, keywords, canonical string, head templ.Component)
<text y="7" textLength="360" lengthAdjust="spacingAndGlyphs">Arav's dwelling</text>
<text y="25" textLength="360" lengthAdjust="spacingAndGlyphs">Welcome to my sacred place, wanderer</text>
</svg>
{{ mainNavSections := []string{"Stuff", "Mindflow", "About", "Guestbook"} }}
{{ mainNavSections := []string{i18n.T(ctx, "base.section.stuff"), i18n.T(ctx, "base.section.mindflow"), i18n.T(ctx, "base.section.about"), i18n.T(ctx, "base.section.guestbook")} }}
{{ mainNavLinks := []templ.SafeURL{"/stuff", "/mindflow", "/about", "/guestbook"} }}
<nav>
<ul>
if title != "" {
<li><a href="/">Home</a></li>
<li><a href="/">{ i18n.T(ctx, "base.section.home") }</a></li>
}
for i, s := range mainNavSections {
if strings.HasSuffix(title, s) {
@ -49,8 +55,8 @@ templ base(title, description, keywords, canonical string, head templ.Component)
</ul>
if title != "" {
<h1>
if strings.HasSuffix(title, "- Stuff") {
Stuff
if strings.HasSuffix(title, "- " + i18n.T(ctx, "base.section.stuff")) {
{ i18n.T(ctx, "base.section.stuff") }
} else {
{ title }
}
@ -62,9 +68,12 @@ templ base(title, description, keywords, canonical string, head templ.Component)
{ children... }
</main>
<footer>
<a href="/rss.xml" title="Stay up to date on what's going on.">RSS feed</a>
<a href="/rss.xml" title={ i18n.T(ctx, "base.rss-feed-title") }>{ i18n.T(ctx, "base.rss-feed") }</a>
<br/>
&copy; 2017&mdash;2024 Alexander &quot;Arav&quot; Andreev &lt;<a href="mailto:me@arav.su">me@arav.su</a>&gt; <a href="/privacy">Privacy statements</a>
<a href="?lang=ru">рус</a>
<a href="?lang=en">eng</a>
<br/>
{ version.GetVersion() } &copy; 2017&mdash;2024 { i18n.T(ctx, "base.copy-author") } &lt;<a href="mailto:me@arav.su">me@arav.su</a>&gt; <a href="/privacy">{ i18n.T(ctx, "base.privacy-statements-link") }</a>
</footer>
</body>
</html>

View File

@ -3,9 +3,9 @@ package web
import "fmt"
import "net/http"
templ ErrorXXX(errCode int, reason, message, referer string) {
templ ErrorXXX(errCode int, reason, message string, r *http.Request) {
{{ errText := http.StatusText(errCode) }}
@base(errText, errText, "", "", errorXXXHead()) {
@base(errText, errText, "", "", r, errorXXXHead()) {
<section id="error">
<h1>{ fmt.Sprint(errCode) }</h1>
{ errText }
@ -16,9 +16,9 @@ templ ErrorXXX(errCode int, reason, message, referer string) {
<p>{ message }</p>
}
</section>
if referer != "" {
if r.Referer() != "" {
<section>
<h2><a href={ templ.URL(referer) }>Go back</a></h2>
<h2><a href={ templ.URL(r.Referer()) }>Go back</a></h2>
</section>
}
}

View File

@ -6,40 +6,42 @@ import "strings"
import "time"
import "net/http"
import "github.com/invopop/ctxi18n/i18n"
import "git.arav.su/Arav/justguestbook"
import "git.arav.su/Arav/dwelling-home/pkg/util"
templ Guestbook(captchaID, owner string, entries []*justguestbook.Entry, pageCount, pageCur int64, r *http.Request) {
@base("Guestbook", "This is my guestbook. Welcome.", "guestbook, personal", "/guestbook", guestbookHead()) {
@base(i18n.T(ctx, "base.section.guestbook"), i18n.T(ctx, "guestbook.description"), "guestbook, personal", "/guestbook", r, guestbookHead()) {
<form id="new-post" action="/api/guestbook" method="POST">
<input type="text" name="name" maxlength="80" placeholder="Name (Anonymous if left blank)"/>
<input type="text" name="website" maxlength="255" placeholder="Website (optional)"/>
<textarea name="message" maxlength="4096" placeholder="Your message" required></textarea>
<input type="text" name="name" maxlength="80" placeholder={ i18n.T(ctx, "guestbook.form.name") }/>
<input type="text" name="website" maxlength="255" placeholder={ i18n.T(ctx, "guestbook.form.website") }/>
<textarea name="message" maxlength="4096" placeholder={ i18n.T(ctx, "guestbook.form.message") } required></textarea>
<span class="checkboxes">
<input type="checkbox" name="hide_website" id="hide-website" checked/>
<label for="hide-website">Hide website <small>(only I can see if set)</small></label>
<label for="hide-website">{ i18n.T(ctx, "guestbook.form.hide-website-1") } <small>{ i18n.T(ctx, "guestbook.form.hide-website-2") }</small></label>
<br/>
<small>Use &gt; to make a quote.</small>
<small>@templ.Raw(i18n.T(ctx, "guestbook.form.quote-usage", i18n.M{"sign":">"}))</small>
</span>
<span class="captcha">
<input type="hidden" name="captcha_id" value={ captchaID }/>
<img src={ string(templ.URL(fmt.Sprintf("/api/captcha/%s/image", captchaID))) } alt="CAPTCHA" width="160" height="40"/>
<input type="text" name="captcha_answer" maxlength="6" placeholder="CAPTCHA" required/>
<small>Valid for <b>10</b> minutes.</small>
<small>@templ.Raw(i18n.T(ctx, "guestbook.form.captcha-validity", i18n.M{"valid":"<b>10</b>"}))</small>
</span>
<input type="submit" value="Send a post"/>
<input type="submit" value={ i18n.T(ctx, "guestbook.form.send-post") }/>
</form>
<section id="posts">
for _, entry := range entries {
<article>
<header>
{{ created_tz := util.ToClientTimezone(entry.Created, r).Format("Monday _2 January 2006 15:04:05 -07:00") }}
{{ created_tz := util.ToClientTimezone(entry.Created, r).Format("02.01.2006 15:04:05 -07:00") }}
{{ website := "" }}
if !entry.HideWebsite {
{{ website = entry.Website }}
}
{ strconv.FormatInt(entry.ID, 10) } by <span class="highlighted">{ entry.Name }</span> <em>{ website }</em> on <time datetime={ entry.Created.Format(time.RFC3339) }>{ created_tz }</time>
{ strconv.FormatInt(entry.ID, 10) } { i18n.T(ctx, "guestbook.post.by") } <span class="highlighted">{ entry.Name }</span> <em>{ website }</em> { i18n.T(ctx, "guestbook.post.on") } <time datetime={ entry.Created.Format(time.RFC3339) }>{ created_tz }</time>
</header>
for _, line := range strings.Split(entry.Message, "\n") {
<p
@ -50,8 +52,8 @@ templ Guestbook(captchaID, owner string, entries []*justguestbook.Entry, pageCou
if entry.Reply != nil {
<div class="reply">
<header>
{{ reply_created_tz := util.ToClientTimezone(entry.Reply.Created, r).Format("Monday _2 January 2006 15:04:05 -07:00") }}
Reply by <span class="highlighted">{ owner }</span> in <time datetime={ entry.Reply.Created.Format(time.RFC3339) }>{ reply_created_tz }</time>
{{ reply_created_tz := util.ToClientTimezone(entry.Reply.Created, r).Format("02.01.2006 15:04:05 -07:00") }}
{ i18n.T(ctx, "guestbook.post.reply") } <span class="highlighted">{ owner }</span> { i18n.T(ctx, "guestbook.post.on") } <time datetime={ entry.Reply.Created.Format(time.RFC3339) }>{ reply_created_tz }</time>
</header>
for _, line := range strings.Split(entry.Reply.Message, "\n") {
<p
@ -64,7 +66,7 @@ templ Guestbook(captchaID, owner string, entries []*justguestbook.Entry, pageCou
</article>
}
if len(entries) == 0 {
<p class="center">No posts.</p>
<p class="center">{ i18n.T(ctx, "guestbook.post.no-posts") }</p>
}
</section>
if pageCount > 1 {

View File

@ -5,5 +5,5 @@ import "net/http"
import "git.arav.su/Arav/justguestbook"
templ GuestbookAdmin(owner string, entries []*justguestbook.Entry, r *http.Request) {
@base("Guestbook Administration", "", "", "/guestbook/admin", nil)
@base("Guestbook Administration", "", "", "/guestbook/admin", r, nil)
}

View File

@ -1,7 +1,9 @@
package web
templ Index() {
@base("", "A homepage of a russian guy Alexander aka Arav. Not just homepage, but something more...", "/", "homepage, personal, blog, services, self-hosting", indexHead()) {
import "net/http"
templ Index(r *http.Request) {
@base("", "A homepage of a russian guy Alexander aka Arav. Not just homepage, but something more...", "homepage, personal, blog, services, self-hosting", "/", r, indexHead()) {
<section id="services">
<span>
<a href="https://arav.su">arav.su</a>.<a href="http://moq7aejnf4xk5k2bkaltli3ftkhusy2mbrd3pj23nrca343ku2mgk4yd.onion">onion</a>.<a href="http://[300:a98d:d6d0:8a08::f]">ygg</a>.<a href="http://arav.i2p">i2p</a><sup><a href="http://arav.i2p/?i2paddresshelper=5Kl-DiWbbk6wf7m0v6zBSNHYq3sXlnrWLIWVeGdpPbPyc9CBS~zrzDYpP43rv1fRiIkbVCD5hTEpY6joQGlk-dFkWWD6201qa6ecsDVQMaE3Q7UTYICd0VEBRoqDUSrvsM-P2y5oG4Z-77RmoGKpbcRgNuMVbQ7AGJNqVSGej-lSyscDWTIZT5dCT505lfRwprdD~emZqkwnn22X16Wpj-X4A4ifph4idrThGioz4UW6PrCpa-oebMCo217s0Zyl9VKaU-o9cx5eFUEwnshoUjqwh7VE-S45NDz854J08xldCATM3wwTRVXhc2NUypsJLKFKiV0z3EXN-ApCdxsV60C-eiXUTX5vYcHHH~imA79v8WKFybjnsyUBst5BBEPQIUifTceLUrTmQ9TUpaMV90EsD5SCshmCfOs8R5y2dK6EfQu8iyYAB5VFSH4M1CLiBZUsDTEFiOomn2JGMDnbPho8lMB8ss4SMuwZShb2LlGqLxJ38kRHlvC68VmJO7InBQAEAAcAAA==" title="Address helper">ah</a></sup>
@ -22,9 +24,12 @@ templ Index() {
</span>
</section>
<section>
<p>
Welcome, Anon. I'm Alexander aka Arav, I self-host some services for myself, friends and you. Not much I have to offer, but maybe you'll find something useful for yourself. :)
</p>
<p>Привет, Анон. Я Александр, хожу по интернету под ником Arav и его всякими вариациями. С 2017 года завел у себя домашний сервер в виде третьей малины, а чуть позже добавил ещё один в виде старого ноута, некоторые сервисы могут быть полезны и тебе, они по ссылкам выше.</p>
<p>Welcome, Anon. I'm Alexander aka Arav, I self-host some services for myself, friends and you. Not much I have to offer, but maybe you'll find something useful for yourself. :)</p>
</section>
<section>
<p>Изначально завел небольшой сайт на neocities, но быстро стало нехватать всякого (например, шаблонов, чтобы везде одно и то же не менять), потому переехал полностью на свой сервер, а там оставил только ссылки.</p>
<p>Initially I had a small website at neocities, but soon I met a need in an advanced stuff like templates, so not to be have to edit the same parts everywhere, so I moved out to my home server and left there just the links.</p>
</section>
}
}

50
web/locales/en/en.yaml Normal file
View File

@ -0,0 +1,50 @@
en:
base:
rss-feed: RSS
rss-feed-title: Stay up to date on what's going on.
copy-author: Alexander ❝Arav❞ Andreev
privacy-statements-link: Privacy statements
section:
home: Home
stuff: Stuff
mindflow: Mindflow
about: About
guestbook: Guestbook
privacy: Privacy
article:
go-back: Back to a list
guestbook:
description: This is my guestbook. Welcome.
form:
name: Name (Anonymous if left blank)
website: Website (optional)
message: Your message
hide-website-1: Hide website
hide-website-2: (only I can see if set)
quote-usage: Use %{sign} to make a quote.
captcha-validity: Valid for %{valid} minutes.
send-post: Send
post:
by: by
on: on
reply: Reply by
no-posts: No posts.
privacy:
description: Privacy statements for all of my services.
mindflow:
description: Updates on my infrastructure, my very important opinions and thoughts.
text: Updates on websites and servers, my very important thoughts and opinions no one asked for.
no-posts: Nothing? There must be some... Looks like database went down.
all: All
stuff:
description: Here I share my programs, scripts, articles, may be other stuff.
text: Here lies everything I've made that I'm willing to share.
article:
h: Articles
tabh-lu: Last Update
tabh-nm: Article
progs: Programs and scripts
music:
h: Music
text-1: There was a period in my life when I was playing with audio sequencers. I lost all project files and only 3 tracks survived in mp3 and they
text-2: can be found here

9
web/locales/locales.go Normal file
View File

@ -0,0 +1,9 @@
package locales
import (
"embed"
)
//go:embed en
//go:embed ru
var Content embed.FS

50
web/locales/ru/ru.yaml Normal file
View File

@ -0,0 +1,50 @@
ru:
base:
rss-feed: RSS
rss-feed-title: Будь в курсе происходящего.
copy-author: Александр «Arav» Андреев
privacy-statements-link: О приватности
section:
home: Домой
stuff: Всякое
mindflow: Блог
about: О...
guestbook: Гостевая
privacy: Приватность
article:
go-back: К списку
guestbook:
description: Моя гостевая. Добро пожаловать.
form:
name: Имя (Аноним если оставить пустым)
website: Веб-сайт (необязательно)
message: Твоё сообщение
hide-website-1: Скрыть веб-сайт
hide-website-2: (будет видно только мне)
quote-usage: Используй %{sign} для цитаты.
captcha-validity: Действительна %{valid} минут.
send-post: Отправить
post:
by: от
on: " "
reply: Ответ
no-posts: Нет постов.
privacy:
description: Заявление о приватности на моих сервисах.
mindflow:
description: Новости по работе сайта и серверов, мои нахрен никому не упёршиеся мнения и мысли.
text: Новости по работе сайтов и серверов, мои мысли и мнения, которые никому не упёрлись.
no-posts: Ничего? Как это?.. Видать, база накрылась.
all: Всё
stuff:
description: Здесь все программы, скрипты, статьи и прочее, чем хотел бы поделиться.
text: Здесь лежит всё, чем я хотел бы поделиться.
article:
h: Статьи
tabh-lu: Последнее обновление
tabh-nm: Статья
progs: Программы и скрипты
music:
h: Музыка
text-1: В моей жизни был период, когда я пытался в написание музыки в аудио секвенсорах. Я потерял проекты и сохранились лишь три mp3-шки, которые можно
text-2: взять здесь

View File

@ -4,15 +4,17 @@ import "net/http"
import "strings"
import "time"
import "github.com/invopop/ctxi18n/i18n"
import "git.arav.su/Arav/dwelling-home/pkg/mindflow"
import "git.arav.su/Arav/dwelling-home/pkg/util"
templ Mindflow(posts []mindflow.Post, categories []mindflow.Category, r *http.Request) {
@base("Mindflow", "Updates on my infrastructure, my very important opinions and thoughts.", "updates, thoughts, opinions, blog, diary", "/mindflow", mindflowHead()) {
<p class="center">Here I post updates on websites and infrastructure, my very important opinions and thoughts no one asked for. If you'd like to subscribe to this bullshittery then <a href="/rss.xml">RSS feed</a> at your service. :)</p>
@base(i18n.T(ctx, "base.section.mindflow"), i18n.T(ctx, "base.mindflow.description"), "updates, thoughts, opinions, blog, diary", "/mindflow", r, mindflowHead()) {
<p class="center">{ i18n.T(ctx, "mindflow.text") }</p>
<section>
<menu id="filter" class="hidden">
<button name="all">All</button>
<button name="all">{ i18n.T(ctx, "mindflow.all") }</button>
for _, category := range categories {
<button name={ strings.ToLower(category.Name) }>{ category.Name }</button>
}
@ -36,12 +38,13 @@ templ Mindflow(posts []mindflow.Post, categories []mindflow.Category, r *http.Re
} else {
<span></span>
}
<time datetime={ util.ToClientTimezone(post.Date, r).Format(time.RFC3339) }>{ util.ToClientTimezone(post.Date, r).Format(time.RFC1123) }</time>
{{ ctz := util.ToClientTimezone(post.Date, r) }}
<time datetime={ ctz.Format(time.RFC3339) }>{ ctz.Format("02.01.2006 15:04:05 -07:00") }</time>
</footer>
</article>
}
if len(posts) == 0 {
<p class="center">Nothing? There must be some... Looks like database went down.</p>
<p class="center">{ i18n.T(ctx, "mindflow.no-posts") }</p>
}
</section>
}

View File

@ -3,7 +3,78 @@ package web
import "net/http"
import "git.arav.su/Arav/dwelling-home/pkg/mindflow"
import "git.arav.su/Arav/dwelling-home/pkg/util"
import "strconv"
import "time"
templ MindflowAdmin(posts []mindflow.Post, categories []mindflow.Category, r *http.Request) {
@base("Mindflow Administration", "", "", "/mindflow/admin", nil)
@base("Mindflow Administration", "", "", "/mindflow/admin", r, mindflowAdminHead()) {
<section>
<h2>Manage categories</h2>
<form id="manage-categories">
<select name="category" required>
for _, c := range categories {
<option value={ strconv.FormatInt(c.ID, 10) }>{ c.Name }</option>
}
<option value="0">-- New category --</option>
</select>
<input type="text" name="name" placeholder="New category name"/>
<button type="submit" name="add">Add</button>
<button type="submit" name="edit">Edit</button>
<button type="submit" name="delete">Delete</button>
</form>
</section>
<section>
<h2>Create a new post</h2>
<form id="add" action="/api/mindflow" method="POST">
<select name="category" required>
for _, c := range categories {
<option value={ strconv.FormatInt(c.ID, 10) }>{ c.Name }</option>
}
</select>
<input type="text" name="title" placeholder="Title" required/>
<input type="text" name="url" placeholder="URL"/>
<textarea name="body" placeholder="Body post" required></textarea>
<button type="submit">Add</button>
</form>
</section>
<section>
for _, post := range posts {
<article id={ post.PostID() }>
<header>
<a href="#{ templ.SafeURL(post.PostID()) }"><h3>{ post.Category.Name }: { post.Title }</h3></a>
</header>
<form class="edit">
<select name="category" required>
for _, c := range categories {
if c.ID == post.Category.ID {
<option value={ strconv.FormatInt(c.ID, 10) } selected>{ c.Name }</option>
} else {
<option value={ strconv.FormatInt(c.ID, 10) }>{ c.Name }</option>
}
}
</select>
<input type="hidden" name="post-id" value={ strconv.FormatInt(post.ID, 10) }/>
<input type="text" name="title" placeholder="Title" required/>
<input type="text" name="url" placeholder="URL" value={ post.URL }>
<textarea name="body" placeholder="Body post" required>@templ.Raw(post.Body)</textarea>
<button name="edit-post">Edit</button>
<button name="delete-post">Delete</button>
</form>
<footer>
<time datetime={ util.ToClientTimezone(post.Date, r).Format(time.RFC3339) }>{ util.ToClientTimezone(post.Date, r).Format(time.RFC1123) }</time>
</footer>
</article>
}
if len(posts) == 0 {
<p class="center">Nothing? There must be some... Looks like database went down.</p>
}
</section>
}
}
templ mindflowAdminHead() {
<link rel="stylesheet" href="/assets/css/mindflow.css">
<link rel="stylesheet" href="/assets/css/mindflow_admin.css">
<script src="/assets/js/mindflow_admin.js" defer></script>
}

View File

@ -2,12 +2,36 @@ package web
import "net/http"
import "github.com/invopop/ctxi18n/i18n"
import "git.arav.su/Arav/dwelling-home/pkg/util"
templ Privacy(r *http.Request) {
@base("Privacy", "Privacy statements for all of my services.", "privacy statements", "/privacy", nil) {
@base(i18n.T(ctx, "base.section.privacy"), "Privacy statements for all of my services.", "privacy statements", "/privacy", r, nil) {
if c := i18n.GetLocale(ctx).Code(); c == "ru" {
<section id="privacy">
<h2>Заявление о приватности</h2>
<p>Все собираемые данные не передаются третьим лицам, исключением являются обращения представителей органов правопорядка.</p>
<h3>Общие данные</h3>
<p>На всех сайтах собираются следующие данные: дата посещения, IP-адрес, User-Agent, URL откуда был переход, запрошенный URL.</p>
<h3>Использование JavaScript</h3>
<p>JS используется на <a href="/">основном сайте</a> на странице гостевой книги для обновления CAPTCHA; на странице блога для фильтрации постов по категориям.</p>
<p><a href={ templ.URL(util.GetServiceByHost(r.Host, util.ServiceRadio)) }>Радио</a> использует JS для обновления данных о проигрываемом треке и списке последних песен, также о количестве слушателей.</p>
<p><a href={ templ.URL(util.GetServiceByHost(r.Host, util.ServiceFiles)) }>Файловая шара</a> использует JS для удобства навигации и просмотра.</p>
<h3>Данные специфичные для сервиса загрузки файлов</h3>
<p>Каждое действие (загрузка, скачивание и удаление) логгируются и включают следующие данные:</p>
<ol>
<li>имя файла с которым он был загружен/скачан;</li>
<li>SHA-256 хэш файла;</li>
<li>посоленый хеш кодированный base64 в формате сырого URL по которому осуществляется скачивание/удаление файла;</li>
<li>размер файла.</li>
</ol>
<p>Я себе не враг и буду содействовать органам правопорядка. Загружаемый контент должен соответствовать законам Российской Федерации как и заявлено на странице <a href={ templ.URL(util.GetServiceByHost(r.Host, util.ServiceUpload)) }>сервиса</a>. Таким образом, например, запрещен экстремисткий контент, все что связано с наркотиками и детским порно.</p>
</section>
} else {
<section id="privacy">
<h2>Privacy statements</h2>
<p>All data that is being collected is never being sent to third parties. Exception is the appeals of law enforcements.</p>
<h3>General data</h3>
<p>Across all of my Web-services following data is being collected: date of access, IP-address, User-Agent, referer URL, request URL.</p>
<h3>Use of JavaScript</h3>
@ -26,4 +50,5 @@ templ Privacy(r *http.Request) {
<p>As already stated at <a href={ templ.URL(util.GetServiceByHost(r.Host, util.ServiceUpload)) }>Upload service</a>'s page, file's content must comply with law of Russian Federation. Anything like extremist materials, CP, and so on is forbidden.</p>
</section>
}
}
}

View File

@ -14,14 +14,14 @@ templ RSS(host, author string, posts []mindflow.Post, r *http.Request) {
<title>Arav's dwelling</title>
<description>What's going on with me and my machines.</description>
<language>en-gb</language>
<link>{ host }</link>
<link>{ host }@templ.Raw("</link>")
for _, post := range posts {
<item>
<title>{ post.Title }</title>
<category>{ post.Category.Name }</category>
<guid>{ post.PostID() }</guid>
<pubDate>{ util.ToClientTimezone(post.Date, r).Format(time.RFC1123Z) }</pubDate>
<link>{ post.PostURL(r.Host, true) }</link>
<link>{ post.PostURL(r.Host, true) }@templ.Raw("</link>")
<author>{ author }</author>
<description>
@templ.Raw("<![CDATA[")

View File

@ -2,24 +2,26 @@ package web
import "net/http"
import "github.com/invopop/ctxi18n/i18n"
import "git.arav.su/Arav/dwelling-home/pkg/util"
templ Stuff(r *http.Request) {
{{ gitSite := util.GetServiceByHost(r.Host, util.ServiceGit) }}
@base("Stuff", "Here I share my programs, scripts, articles, may be other stuff.", "articles, programs, personal projects, own music", "/stuff", nil) {
<p class="center">Here lies everything I've made that I'm willing to share.</p>
@base(i18n.T(ctx, "base.section.stuff"), i18n.T(ctx, "stuff.description"), "articles, programs, personal projects, own music", "/stuff", r, nil) {
<p class="center">{ i18n.T(ctx, "stuff.text") }</p>
<section id="articles">
<h2>Articles</h2>
<h2>{ i18n.T(ctx, "stuff.article.h") }</h2>
<table>
<tr>
<th>Last Update</th>
<th>Article</th>
<th>{ i18n.T(ctx, "stuff.article.tabh-lu") }</th>
<th>{ i18n.T(ctx, "stuff.article.tabh-nm") }</th>
</tr>
for _, entry := range Metadata {
<tr>
<td>
<time datetime={ entry.Date.Format("2006-01-02") }>{ entry.Date.Format("02 January 2006") }</time>
<time datetime={ entry.Date.Format("2006-01-02") }>{ entry.Date.Format("02.01.2006") }</time>
</td>
<td>
<a href={ templ.URL(entry.URL) }>{ entry.Title }</a>
@ -29,144 +31,148 @@ templ Stuff(r *http.Request) {
</table>
</section>
<section id="programs-scripts">
<h2>Programs and scripts</h2>
<h2>{ i18n.T(ctx, "stuff.progs") }</h2>
<table>
<tr>
<td><b>mccl</b></td>
<td>0.1.2 (14 December 2023)</td>
<td>Go</td>
<td>GPLv3</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/mccl") }>source</a>
<a href={ templ.URL(gitSite + "/Arav/mccl/releases") }>releases</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>A console Minecraft launcher. Take a look at README.md for explanation.</p>
</td>
</tr>
<tr>
<td><b>httpr</b></td>
<td>0.3.2 (20 September 2023)</td>
<td>Go</td>
<td>MIT</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/httpr") }>source</a>
<a href={ templ.URL(gitSite + "/Arav/httpr/releases") }>releases</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>A simple HTTP router that supports having both regular and parametrised path's parts at the same level, like <code>/assets/*filepath</code> and <code>/:a/:b</code> with the same HTTP method.</p>
<p>Yeah, not as efficient as httprouter is, but in my case no performance loose was noticed (on a small amount of paths). Yet I gained prettiness because it allowed me, for example, to ditch <code>/f/</code> part and leave just <code>/:hash/:name</code> instead of <code>/f/:hash/:name</code> in a dwelling-upload service.</p>
</td>
</tr>
<tr>
<td><b>justguestbook</b></td>
<td>1.3.2 (22 May 2023)</td>
<td>Go</td>
<td>MIT</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/justguestbook") }>source</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>A simple guestbook with owner's replies implementation made into a library.</p>
</td>
</tr>
<tr>
<td><b>justcaptcha</b></td>
<td>2.1.0 (12 August 2023)</td>
<td>Go</td>
<td>MIT</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/justcaptcha") }>source</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>A simple CAPTCHA implementation.</p>
</td>
</tr>
<tr>
<td><b>kwh-cost</b></td>
<td>1.1.3 (21 May 2024)</td>
<td>C</td>
<td>MIT+NIGGER</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/kwh-cost") }>source</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>KWh cost calculator in C.</p>
</td>
</tr>
<tr>
<td><b>httpprocprobed</b></td>
<td>3.1.1 (13 January 2024)</td>
<td>Go</td>
<td>MIT+NIGGER</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/httpprocprobed") }>source</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>It returns a list of processes and if they are running in a JSON format via HTTP GET request on <code>/processes</code> endpoint. Under the hood it searches in a /proc/ directory. It is being used on about page to show wether service's running or not.</p>
</td>
</tr>
<tr>
<td><b>ScrapTheChan</b></td>
<td>0.5.0 (3 May 2021)</td>
<td>Python</td>
<td>MIT</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/ScrapTheChan") }>source</a>
<a href={ templ.URL(gitSite + "/Arav/ScrapTheChan/releases") }>releases</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>Imageboards file scraper using theirs JSON API. Currently supported: 4chan.org, lainchan.org, 2ch.hk and 8kun.top.</p>
</td>
</tr>
<tr>
<td><b>OpenNIC active domains extraction script</b></td>
<td>10 July 2020</td>
<td>Bash</td>
<td>MIT</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/opennic-extract-domains") }>source</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>Bash script for BIND9 that extracts domains from zone files of OpenNIC and forms a list of domains that have an IP-address.</p>
</td>
</tr>
<tr>
<td><b>PiggyBank</b></td>
<td>1.0.0 (8 July 2020)</td>
<td>Python</td>
<td>MIT</td>
<td>
<a href={ templ.URL(gitSite + "/Arav/PiggyBank") }>source</a>
<a href={ templ.URL(gitSite + "/Arav/PiggyBank/releases") }>releases</a>
</td>
</tr>
<tr>
<td colspan="5">
<p>A program to help you to keep track of your piggy bank. A simple script I once wrote that I rewrote and made into a package just to learn how to do it.</p>
</td>
</tr>
for _, prog := range programs {
<tr>
<td><b>{ prog.Name }</b></td>
<td>{ prog.Version }</td>
<td>{ prog.Lang }</td>
<td>{ prog.License }</td>
<td>
<a href={ templ.URL(gitSite + prog.SourceLink) }>source</a>
if prog.ReleasesLink != "" {
<a href={ templ.URL(gitSite + prog.ReleasesLink) }>releases</a>
}
</td>
</tr>
<tr>
<td colspan="5">
for _, line := range prog.Description[i18n.GetLocale(ctx).Code().String()] {
<p>@templ.Raw(line)</p>
}
</td>
</tr>
}
</table>
</section>
<section id="music">
<h2>Music</h2>
<p>There was a period in my life when I was playing with audio sequencers. I lost all project files and only 3 tracks survived in mp3 and they <a href={ templ.URL(util.GetServiceByHost(r.Host, util.ServiceFiles) + "/music/My%20tracks,%20that%20survived/") }>can be found here</a>.</p>
<h2>{ i18n.T(ctx, "stuff.music.h") }</h2>
<p>{ i18n.T(ctx, "stuff.music.text-1") } <a href={ templ.URL(util.GetServiceByHost(r.Host, util.ServiceFiles) + "/music/My%20tracks,%20that%20survived/") }>{ i18n.T(ctx, "stuff.music.text-2") }</a>.</p>
</section>
}
}
type program struct {
Name string
Version string
Lang string
License string
SourceLink string
ReleasesLink string
Description map[string][]string
}
var programs []program = []program{
{
Name: "mccl",
Version: "0.1.2 (14.12.2023)",
Lang: "Go",
License: "GPLv3",
SourceLink: "/Arav/mccl",
ReleasesLink: "/Arav/mccl/releases",
Description: map[string][]string{
"en": {"A console Minecraft launcher. Take a look at README.md for explanation."},
"ru": {"Консольный лаунчер Minecraft. За подробностями в README.md."}},
},
{
Name: "httpr",
Version: "0.3.2 (20.09.2023)",
Lang: "Go",
License: "MIT",
SourceLink: "/Arav/httpr",
ReleasesLink: "/Arav/httpr/releases",
Description: map[string][]string{
"en": {
"A simple HTTP router that supports having both regular and parametrised path's parts at the same level, like <code>/assets/*filepath</code> and <code>/:a/:b</code> with the same HTTP method."},
"ru": {
"Простой HTTP роутер, который позволяет иметь на одном уровне и параметризованные и обычные пути, например, <code>/assets/*filepath</code> и <code>/:a/:b</code>."}},
},
{
Name: "justguestbook",
Version: "1.3.2 (22.05.2023)",
Lang: "Go",
License: "MIT",
SourceLink: "/Arav/justguestbook",
ReleasesLink: "",
Description: map[string][]string{
"en": {"A simple guestbook with owner's replies implementation made into a library."},
"ru": {"Простая гостевая книга в виде библиотеки с возможностью владельцу отвечать на посты."}},
},
{
Name: "justcaptcha",
Version: "2.1.0 (12.08.2023)",
Lang: "Go",
License: "MIT",
SourceLink: "/Arav/justcaptcha",
ReleasesLink: "",
Description: map[string][]string{
"en": {"A simple CAPTCHA implementation."},
"ru": {"Простая CAPTCHA."}},
},
{
Name: "kwh-cost",
Version: "1.1.3 (21.05.2024)",
Lang: "C",
License: "MIT+NIGGER",
SourceLink: "/Arav/kwh-cost",
ReleasesLink: "",
Description: map[string][]string{
"en": {"KWh cost calculator in C."},
"ru": {"Калькулятор стоимости кВтч на C."}},
},
{
Name: "httpprocprobed",
Version: "3.2.0 (7.07.2024)",
Lang: "Go",
License: "MIT+NIGGER",
SourceLink: "/Arav/httpprocprobed",
ReleasesLink: "",
Description: map[string][]string{
"en": {"It returns a list of processes and if they are running in a JSON format via HTTP GET request on <code>/processes</code> endpoint. Under the hood it searches in a /proc/ directory. It is being used on about page to show wether service's running or not."},
"ru": {"Возвращает JSON список процессов и запущены ли они. Процессы ищет считывая директорию <code>/proc/</code>. Использую на странице О... для показа статуса сервиса."}},
},
{
Name: "ScrapTheChan",
Version: "0.5.0 (3.05.2021)",
Lang: "Python",
License: "MIT",
SourceLink: "/Arav/ScrapTheChan",
ReleasesLink: "/Arav/ScrapTheChan/releases",
Description: map[string][]string{
"en": {"Imageboards file scraper using theirs JSON API. Currently supported: 4chan.org, lainchan.org, 2ch.hk and 8kun.top."},
"ru": {"Граббер файлов с имиджборд используя их JSON API. Работает с: 4chan.org, lainchan.org, 2ch.hk and 8kun.top."}},
},
{
Name: "OpenNIC active domains extraction script",
Version: "10.07.2020",
Lang: "Bash",
License: "MIT",
SourceLink: "/Arav/opennic-extract-domains",
ReleasesLink: "",
Description: map[string][]string{
"en": {"Bash script for BIND9 that extracts domains from zone files of OpenNIC and forms a list of domains that have an IP-address."},
"ru": {"Баш-скрипт для BIND9 извлекает домены OpenNIC у которых прописан IP-адрес."}},
},
{
Name: "PiggyBank",
Version: "1.0.0 (8.07.2020)",
Lang: "Python",
License: "MIT",
SourceLink: "/Arav/PiggyBank",
ReleasesLink: "/Arav/PiggyBank/releases",
Description: map[string][]string{
"en": {"A program to help you to keep track of your piggy bank. A simple script I once wrote that I rewrote and made into a package just to learn how to do it."},
"ru": {"Это просто копилка."}},
},
}

View File

@ -1,246 +0,0 @@
extends base.pug
block meta_description
meta(name='description' content="About me and my home servers.")
block append head
link(href='/assets/css/about.css' rel='stylesheet')
link(rel='canonical' href='/about')
block nav
a(href='/') Home
a(href='/stuff') Stuff
a(href='/mindflow') Mindflow
a(href='/guestbook') Guestbook
h1 About
mixin isServiceUp(header, service)
if v, ok := services[service]; ok && v
h3.service-up= header
else
h3.service-down= header
block content
:go:func About(title, files_site string, services servicestat.ServiceList)
section#about-me
h2 Me
p #[span.highlighted Who am I?] My name is Alexander Andreev. I'm a russian guy of age 31 who likes tinkering with computers.
p #[span.highlighted Why am I doing all of this?] Machines are up 24/7 anyway, so why not?
p #[span.highlighted Why am I almost &ldquo;doxxing&rdquo; myself?] Yes, my real first and last names and age are here, and since I self-host you can get my city as well. And I simply don't see this as a problem. :|
p #[span.highlighted Why particularly that slogan?] I just wanted sort of a slogan that would fit under the logo and this was the first thing came on mind. I actually like it. Don't you think of your websites as of very special place of your own? Of course you do. :) And who we are if not the wanderers who are looking for something in the vastness of Intenet? xD And yes, it's a pain in the ass to make it fit under logo across different browsers. That was the moment when I found out that different browsers render text differently.
p #[span.highlighted Why English only?] I want this place to be accessible for a wide audience and English happen to be todays lingua franca, and to practice the language of course.
p Now a little break for...
section#my-cat
h2 My kot Boris :3
div.columns.figs
figure
a(href='/assets/img/photos/my_cat.webp')
img(src='/assets/img/photos/my_cat_thumb.webp' title=':3' alt='My cat. :3')
figure
a(href='/assets/img/photos/my_cat_2.webp')
img(src='/assets/img/photos/my_cat_2_thumb.webp' title='xDDDD' alt='xDDDD')
p And here we continue. :)
section#more-about-me
h3 Hobbies
p Video games (since 1997)
p Computers (since 11th November 2004)
p #[s Wasting my life on] Surfing the Internets (since February 2006)
p Mapping for Half-life 2, Counter-Strike: Source (since 2006, discontinued in 2009) (everything's fuarrkin' lost)
p Music writing (since 2007, last track was made in 2010)
p Programming (since 2007)
p #[s (LARP'ing as a system administrator)] Home servers (since 1st January 2017)
p Software Defined Radio (since June 2018)
h3 What I know
h4 Human languages
p #[span.highlighted English] is my main foreign language and I think that I know it quite well, but every time I reread what I wrote here I constantly catch cringe vibes. xD I have a nice pronunciation (my teacher once said so :)) and tend to British non-rhotic variant. Of course I end up with a mix of all the flavours of different dialects. What I struggle from is a lack of speaking practice and vocabulary is still a problem as well.
p #[span.highlighted Ukrainian (Українська)] is a special case. :) Russian and ukrainian are related languages, so are mutually understandable (at least must be), yet many russians are struggling to understand it, and I genuinely don't get why. It is just a matter of putting some little effort to negatiate it. I never learnt it, aside from reading it here and there, and looking up some words in a dictionary, and especially throughout past #[s 8] #[s 9] 10 years I saw enough material to learn it to a decent level of understanding and some speaking.
p Агась, нiколи спецiйно не вчив українську, користував перекладач тiльки як словник, за цi #[s вiсiм ] #[s вже дев'ять] десять рокiв було досить матерiалiв. :) P.S.: Слава Українi у складi Росiї! :)
p I like learning languages, but me being a lazy fuck won't let me learn something up to a reasonable level. I ended up with being able to +- read some languages, like norwegian, german, polish, french, japanese (hiragana + some yet not forgotten kanji). So, now I main only English.
h4 Computer languages
p #[span.highlighted For programming and scripting:] Python, Go, JavaScript, and Bash for now are most used by me. Later I used or tasted: Pascal, Delphi, C#, C, C++, Java, PHP. And wrote hello worlds in some others like LISP and Haskell.
p #[span.highlighted Markup and declarative:] SQL (SQLite3, MariaDB), HTML5, CSS3, LaTeX, Markdown, XML, and JSON.
p And I don't know what else to put here. :^)
h3 What I liked
h4 Anime
p Ghost in the Shell, Shaman King, Hellsing, Steins;Gate, Cowboy Beebop, Ergo Proxy, Jin-Rou, Black Lagoon, Jojo's Bizzare Adventures, Spice and Wolf, Konosuba, Demon Slayer: Kimetsu no Yaiba
h4 Films
p Paths of Glory (1957), Boss Nigger (The Black Bounty Killer) (1974), Movies with Jackie Chan, Blade Runner (1982), WarGames (1983), Robocop (1987), Talk Radio (1988), Stargate (1994), Hackers (1995), Johnny Mnemonic (1995), Contact (1997), Matrix (1999, 2003), Snatch (2000), Oldboy (2003), The Day After Tomorrow (2004), Alpha Dog (2005), Constantine (2005), The Gingerdead Man (2005), Lucky Number Slevin (2006), 99 francs (2007), I Am Legend (2007), Inglourious Basterds (2009), Valhalla Rising (2009), The Guard (2011), Filth (2013), Mandariinid (2013), Gingerdead Man vs. Evil Bong (2013), Gone Girl (2014), Who am I (2014), Arrival (2016), Contratiempo (2016), Wandering Earth (2019), Wandering Earth 2 (2019), Greyhound (2020), I Care A Lot (2020), The Greatest Beer Run Ever (2022), Everything Everywhere All at Once (2022), Dungeons & Dragons: Honor Among Thieves (2023)
h4 TV shows
p X-Files (1993&mdash;2002), Lost (2004&mdash;2010), Stargate: SG-1 (1997&mdash;2007), Stargate: Atlantis (2004&mdash;2009), The Shivering Truth (2018&mdash;2020), Два холма (Two Hills) (2022), Narcos (2015&mdash;2017)
h4 Games for SEGA Mega Drive
p Not a lot of games I have played.
p Bubba'n'Stix, Battletoads, Granada, Demolition Man, Road Rash, Doom Troopers - The Mutant Chronicles, The Lost Vikings, Ghostbusters, Mig-29 Fighter Pilot.
h4 Games for PC
p Grand Theft Auto: Vice City, Half-Life (all), StarCraft, Diablo 2, Far Cry (2004), Battlefield: Vietnam, Delta Force: Black Hawk Down, Silent Hunter 3, Grand Theft Auto: San Andreas, Boiling Point: Road to Hell, Portal, Freelancer, F.E.A.R., S.T.A.L.K.E.R., Grand Theft Auto 4, Lineage 2, The Elder Scrolls V: Skyrim, Battlefield 3, The Walking Dead, The Wolf Among Us, Payday 2, The Witcher (1st, 2nd, 3rd didn't finished yet), Minecraft, Terraria, Starbound, Euro Truck Simulator 2, Mount &amp; Blade: Warband, Papers, Please, Insurgency, Elite: Dangerous, theHunter: Call of the Wild, American Truck Simulator, Rocket League, Sea Of Thieves.
p I'm CMDR Arav in Elite: Dangerous. My <a href="https://www.edsm.net/en/user/profile/id/22541/cmdr/Arav" rel="noopener noreferrer">EDSM profile</a>.
p I play TruckersMP mod for Euro Truck Simulator 2 and American Truck Simulator. Nickname is Arav with a tag [RU64].
h4 Music
p You can see what I like in #[a(href=files_site+"/music") a file share].
section#servers-summary
h2 My servers
p I have two of them, the first one is a #[a(href='https://www.raspberrypi.org/products/raspberry-pi-3-model-b/' rel='nofollow noreferrer') Raspberry Pi 3 rev. B] single board computer and the second one is a laptop. Yeah, not quite impressive, but they do their work just fine.
p Laptop is Acer Packard Bell TE69CX that has a 2 core Intel Pentium 2117U 1.8GHz and 10GB RAM (2GB + 8GB), the system disk is a 120GB SSD and the other one is 2TB HDD where all the shit I have is stored. I've replaced my good old 500GB disk with 2TB one, since it became a little too tight, now it is a system disk for Raspberry Pi. Everything that have just a bit of importantance to me is backed up, encrypted and stored in the clouds. :)
p Also now I have a helper VPS with a 1 core 2.2GHz CPU and 512M RAM, and a 10GB disk I use as a slave DNS server for my domain and a postfix relay to send a mail.
section#servers-photos
div.columns.figs
figure
a(href='/assets/img/photos/raspi.webp')
img(src='/assets/img/photos/raspi_thumb.webp' alt='Raspberry Pi 3 rev. B')
figcaption Raspberry Pi 3 rev. B
figure
a(href='/assets/img/photos/acer.webp')
img(src='/assets/img/photos/acer_thumb.webp' title='Screen and keyboard are broken anyway.' alt='Laptop')
figcaption Acer Packard Bell TE69CX
section#servers-public-services
h2 Public services
p.center That are available for everyone.
div.columns
div
+isServiceUp("Internet-radio", "radio")
p
a(href='https://radio.arav.su') radio.arav.su
| .
a(href='http://wsmkgnmhmzqm7kyzv7jnzzafvgm7xlmlfvzhgorpapd5or2arnhuktqd.onion') onion
| .
a(href='http://radio.arav.i2p') i2p
| .
a(href='http://[300:a98d:d6d0:8a08::e]') ygg
p Runs using Ezstream through Icecast which goes through NGiNX. Ezstream fetches a playlist from a self-written solution. I broadcast almost everything I have. I'm too lazy to make some kind of broadcasting program to stream so I just randomise the playlist and throw new music there from time to time.
div
+isServiceUp("File share", "dwelling-files")
p
a(href='https://files.arav.su') files.arav.su
| .
a(href='http://qf5e43nlhvnrutmikuvbdfj3cmtthokpbaxtkm6mjlslttzvtgm4fxid.onion') onion
| .
a(href='http://files.arav.i2p') i2p
| .
a(href='http://[300:a98d:d6d0:8a08::d]') ygg
p There you'll find music, videos, films, animes, TV shows, books, games, programs, drivers (a very few), OS images (Winblows mainly). Go check it out!
div
+isServiceUp("File upload", "dwelling-upload")
p
a(href='https://upload.arav.su') upload.arav.su
| .
a(href='http://4usftbmjpfexkr2x5xbp5ukmygpmg4fgrnx2wbifsexqctooz5hmviyd.onion') onion
| .
a(href='http://upload.arav.i2p') i2p
| .
a(href='http://[300:a98d:d6d0:8a08::c]') ygg
p I've made a file upload service for ya with a limit of 128MiB per file, keeping it for 36 hours, and overall storage I dedicated for it is 100GiB.
div
+isServiceUp("Git", "git")
p
a(href='https://git.arav.su') git.arav.su
| .
a(href='http://qqitm7qlsbbubwmjos4cqzmvkqidg34rfnbyhuydhalep33fbvh22xyd.onion') onion
| .
a(href='http://git.arav.i2p') i2p
| .
a(href='http://[300:a98d:d6d0:8a08::b]') ygg
p Gitea. This is a place where I put source code of everything I ever wrote and consider useful and worth sharing.
div
h3 Tor relay
p #[a(href='https://metrics.torproject.org/rs.html#details/CEF2FD0E1973EA04D1444DDAEFF1B0BC3C0C39B1' rel='nofollow noreferrer') metrics.torproject.org]
p #[b Since 1st December 2021 Tor is blocked in Russia, so the relay is down.]
div
h3 I2P router
p I help the network using an official #[a(href='https://geti2p.net' rel='nofollow noreferrer') I2P router].
section#servers-private-services
h2 Private services
p.center That are available for a narrow circle of people.
div.columns
div
+isServiceUp("E-Mail server", "mail")
p Postfix, Dovecot (w/Sieve), rspamd, ClamAV.
div
+isServiceUp("Mumble", "mumble")
p #[a(href="mumble://arav.su") mumble://arav.su]
p Certificate is necessary. Only an entrance room is open for non-members.
div
+isServiceUp("TeamSpeak 3", "teamspeak3")
p #[a(href="ts3server://arav.su") ts3server://arav.su]
p Same as for Mumble. Your identifier should have a security level greater or equal to 29.
section#servers-games
h2 Game servers
div.columns
div
+isServiceUp("Minecraft", "game-minecraft")
p.highlighted arav.su:25565
p #[a(href='/minemap') Web map].
p Now run a version 1.20.4 with fabric. Here's a #[a(href='https://files.arav.su/file/games/minecraft/1.20.4-fabric-modpack.zip') modpack].
div
+isServiceUp("Avorion", "game-avorion")
p Server is listed in a server list as &ldquo;Arav's dwelling / Avorion&rdquo;. Whitelist is enabled. Bring your SteamID64 if you want to play here.
div
+isServiceUp("Starbound", "game-starbound")
p.highlighted arav.su:21065
p Server is using a Frackin' Universe mod.
p Don't forget to set &ldquo;Allow assets mismatch&rdquo; option that can be found on the first page of the &ldquo;Options&rdquo; menu.
p Access is restricted using accounts. Contact me if you want to play here, you would need to give me a nickname and a password.
div
+isServiceUp("Project Zomboid", "game-pzomboid")
p.highlighted arav.su:16261
p Server is listed as &ldquo;Arav's dwelling / Project Zomboid&rdquo;. Whitelist is enabled.
div
+isServiceUp("Don't Starve Together", "game-dontstarve")
p.highlighted arav.su:10899
p Server is listed as &ldquo;Arav's dwelling / Don't Starve Together&rdquo;.
section#servers-inner-services
h2 Inner services
p.center Services that maintains other services or used exclusively by me.
div.columns
div
h3 Web-server
p NGiNX FTW.
div
h3 Database
p #[s MariaDB managed with phpMyAdmin] was replaced by SQLite3 on my services.
div
h3 VPN
p #[s OpenVPN] Wireguard.
div
h3 Network file share
p Samba and NFSv4.
div
h3 Torrents
p Transmission-cli gets shit done.
p The only annoying thing is that it sometimes creates .part files for one of unchecked files.
div
h3 Printing
p CUPS with CCP (Canon CAPT printer).
p Holy shit, it finally works! #[s Wow, even after kernel update it doesn't require a reboot anymore!] #[s Actually, requires. :)] Sometimes do, sometimes not. xD
div
h3 DNS
p BIND9 via DNSCrypt-proxy.
p For LAN I use &ldquo;home.arpa&rdquo; special-use domain introduced by RFC 8375. And for uniqueness &ldquo;arav.home.arpa&rdquo; specifically.
p Now I serve my domain using a VPS as a slave.
section#contacts
h2 Contacts
span E-Mail:&nbsp;#[a(href="mailto:me@arav.su") me@arav.su]
br
span
| PGP&nbsp;key:&nbsp;#[a(href="/~arav/739850CD5051DE554368709225969B23DCB5CA34.asc") 7398 50CD 5051 DE55 4368 7092 2596 9B23 DCB5 CA34] (available through #[a(href="https://wiki.gnupg.org/WKD" rel="nofollow noreferrer") Web Key Directory])
section#donation
h2 Donation
a(href="monero:48namnfX17TX1kEGCpkXaRWhtw8p92cQjd5uQg7ivybgUuW4BTVaX8egxQhEi75JwuUGn3MDLKHYGNhu4eCfM6dRAAL2QAq") monero:
| 48namnfX17TX1kEGCpkXaRWhtw8p92cQjd5uQg7ivybgUuW4BTVaX8egxQhEi75JwuUGn3MDLKHYGNhu4eCfM6dRAAL2QAq
br
| #[a(href="https://www.donationalerts.com/r/arav") DonationAlerts]
| #[a(href="https://www.tinkoff.ru/rm/andreev.aleksandr1164/5nVjK98501") Tinkoff]
| #[a(href="https://www.tinkoff.ru/baf/5zRsqEQic6r") Tinkoff рефералка]
section#banners
h2 Banners
p In case you found my site anyhow useful and would like to add me to your links page here are the banners for you.
div.banners
figure
img(src="/assets/img/banners/8831l.gif" alt="Light banner 88x31")
figure
img(src="/assets/img/banners/8831d.gif" alt="Dark banner 88x31")
div.banners
figure
img(src="/assets/img/banners/24060l.gif" alt="Light banner 240x60")
figure
img(src="/assets/img/banners/24060d.gif" alt="Dark banner 240x60")

View File

@ -1,66 +0,0 @@
extends base.pug
block meta_description
meta(name='description' content='Here I will post updates on my infrastructure, my very important opinions and thoughts.')
block append head
link(href='/assets/css/mindflow.css' rel='stylesheet')
link(href='/assets/css/mindflow_admin.css' rel='stylesheet')
script(src='/assets/js/mindflow_admin.js' defer='')
block nav
a(href='/') Home
a(href='/stuff') Stuff
a(href='/mindflow') Mindflow
a(href='/about') About
a(href='/guestbook') Guestbook
h1 Mindflow Admin
block content
:go:func MindflowAdmin(title string, posts []mindflow.Post, categories []mindflow.Category, r *http.Request)
section
h2 Manage categories
form(id='manage-categories')
select(name='category' required='')
each category in categories
option(value=category.ID) #{category.Name}
option(value='0') -- New category --
input(type='text', placeholder='New category name' name='name')
button(type="submit" name="add") Add
button(type="submit" name="edit") Edit
button(type="submit" name="delete") Delete
section
h2 Create a new post
form(id='add' action='/api/mindflow', method='POST')
select(name='category' required='')
each category in categories
option(value=category.ID) #{category.Name}
input(type='text', placeholder='Title' name='title' required='')
input(type='text', placeholder='URL' name='url')
textarea(placeholder='Body post' name='body' required='')
button(type="submit") Add
section
if (len(posts) > 0)
each post in posts
article(id=post.PostID())
header
a(href=`#${post.PostID()}`)
h3= post.Category.Name + ": " + post.Title
form.edit
select(name='category' required='')
each category in categories
if (category.ID == post.Category.ID)
option(value=category.ID selected='') #{category.Name}
else
option(value=category.ID) #{category.Name}
input(type='hidden', name='post-id' value=post.ID)
input(type='text', placeholder='Title' name='title' value=post.Title required='')
input(type='text', placeholder='URL' name='url' value=post.URL)
textarea(placeholder='Body post' name='body' required='')!= post.Body
button(name='edit-post') Edit
button(name='delete-post') Delete
footer
time(datetime=util.ToClientTimezone(post.Date, r))= util.ToClientTimezone(post.Date, r).Format(time.RFC1123)
else
p.center Nothing? There must be some... Looks like database went down.