diff --git a/INSTALL.md b/INSTALL.md deleted file mode 100644 index e24d44e..0000000 --- a/INSTALL.md +++ /dev/null @@ -1,11 +0,0 @@ -# Installation - -```shell -$ git clone git://git.chaotic.ninja/yakumo_izuru/mai -$ cd mai -$ make -# make PREFIX=/usr/local install -``` -* Read the [mai.ini(5)](mai.ini.5) manual page -* Use any web server than is able to reverse proxy, like [Apache](https://httpd.apache.org), [h2o](https://h2o.examp1e.net), or [NGINX](https://www.nginx.com). - * Examples are provided on the repository diff --git a/INSTANCES.md b/INSTANCES.md deleted file mode 100644 index 65cefa3..0000000 --- a/INSTANCES.md +++ /dev/null @@ -1,6 +0,0 @@ -# List of known instances - -| Name | Cloudflare? | Country | URL | Engines supported | -|---------------------------------------------|-------------|---------|--------------------------|-------------------| -| Chaotic Ninja Communication Network Limited | No | Germany | https://tr.chaotic.ninja | Google, Reverso | -| | | | | | diff --git a/LEGAL.md b/LEGAL.md deleted file mode 100644 index 4c35c76..0000000 --- a/LEGAL.md +++ /dev/null @@ -1,9 +0,0 @@ -Mai does not host any content. All content shown on any Mai instances is from [Google Translate](https://translate.google.com), [Reverso](https://www.reverso.net/), and [LibreTranslate](https://libretranslate.com) - -Mai is not affiliated with none of the above, which this program relays. - -Trademarks belong to their respective owners. -Google Translate is a trademark of [Google LLC](https://www.google.com). Reverso is a trademark of Reverso, et cetera. - -The creators and maintainers of this repository assume no liability for the accuracy and timeliness of any information provided above. Trademark owner information was researched to the best of the author's knowledge at the time of curation and may be outdated or incorrect. - diff --git a/Makefile b/Makefile index 6297a7c..55e284a 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ +GO ?= go PREFIX ?= /usr/local -GOFLAGS ?= -v -ldflags "-w -X `go list`.Version=${VERSION} -X `go list`.Commit=${COMMIT}" -VERSION = `git describe --abbrev=0 --tags 2>/dev/null || echo "VERSION"` -COMMIT = `git rev-parse --short HEAD || echo "COMMIT"` +GOFLAGS ?= -v -ldflags "-w -X `${GO} list`.Version=${VERSION}" +VERSION ?= 2025.04.17 build: - go build ${GOFLAGS} ./cmd/mai + ${GO} build ${GOFLAGS} ./cmd/mai clean: rm -f mai install: diff --git a/cmd/mai/main.go b/cmd/mai/main.go index 247c933..9ea2f4c 100644 --- a/cmd/mai/main.go +++ b/cmd/mai/main.go @@ -12,8 +12,8 @@ import ( "strings" "syscall" - "marisa.chaotic.ninja/mai" - "marisa.chaotic.ninja/mai/engines" + "mahou-no-mori.yakumo.dev/mai" + "mahou-no-mori.yakumo.dev/mai/engines" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/favicon" @@ -24,36 +24,38 @@ import ( ) var ( configfile string - groupname string - username string + verbose bool ) var conf struct { - danmaku int + group string listen string - staticpath string - tmplpath string + requests int + static string + templates string + user string } func MaiSkipLimiter(c *fiber.Ctx) bool { // Paths listed here are not considered for rate limiting path := c.Path() - return strings.HasPrefix(path, "/static") || - strings.HasPrefix(path, "/docs") + return strings.HasPrefix(path, "/static") } func main() { parseFlags() + conf.listen = "127.0.0.1:5000" + conf.requests = 5 + conf.static = "./static" + conf.templates = "./views" + if configfile != "" { + if verbose { + log.Printf("Reading configuration from %s", configfile) + } readConf(configfile) } - // Default settings - conf.danmaku = 10 - conf.listen = "127.0.0.1:5000" - conf.staticpath = "./static" - conf.tmplpath = "./views" - - if username != "" { - uid, gid, err := usergroupids(username, groupname) + if conf.user != "" { + uid, gid, err := usergroupids(conf.user, conf.group) if err != nil { log.Fatal(err) } @@ -61,7 +63,7 @@ func main() { syscall.Setgid(gid) } - engine := html.New(conf.tmplpath, ".html") + engine := html.New(conf.templates, ".html") engine.AddFunc("inc", func(i int) int { return i + 1 }) server := fiber.New( @@ -85,7 +87,7 @@ func main() { server.Use(favicon.New( favicon.Config{ - File: conf.staticpath + "/favicon.ico", + File: conf.static + "/favicon.ico", }, )) @@ -100,7 +102,7 @@ func main() { server.Use(limiter.New(limiter.Config{ Next: MaiSkipLimiter, - Max: conf.danmaku, + Max: conf.requests, Expiration: 30 * time.Second, LimiterMiddleware: limiter.SlidingWindow{}, LimitReached: func(c *fiber.Ctx) error { @@ -296,7 +298,7 @@ func main() { }) server.Get("/toomanyrequests", func(c *fiber.Ctx) error { - return c.SendFile(conf.tmplpath + "/429.html") + return c.SendFile(conf.templates + "/429.html") return c.SendStatus(429) }) @@ -325,13 +327,10 @@ func main() { } return c.Redirect("/") }) - server.Static("/static", conf.staticpath, fiber.Static{ - Compress: true, + server.Static("/static", conf.static, fiber.Static{ ByteRange: true, Browse: true, }) - server.Static("/docs", "./docs", fiber.Static{}) - server.Listen(conf.listen) } diff --git a/cmd/mai/parseflags.go b/cmd/mai/parseflags.go index 4969f9e..bd57bc6 100644 --- a/cmd/mai/parseflags.go +++ b/cmd/mai/parseflags.go @@ -7,7 +7,6 @@ import ( func parseFlags() { flag.StringVar(&configfile, "f", "", "Configuration file") - flag.StringVar(&username, "u", "", "Sets the user to which privilege dropping is done") - flag.StringVar(&groupname, "g", "", "Sets the group to which privilege dropping is done") + flag.BoolVar(&verbose, "v", false, "Be verbose") flag.Parse() } diff --git a/cmd/mai/readconf.go b/cmd/mai/readconf.go index e7b03ba..94ae923 100644 --- a/cmd/mai/readconf.go +++ b/cmd/mai/readconf.go @@ -10,11 +10,13 @@ func readConf(file string) error { if err != nil { return err } - conf.danmaku, _ = cfg.Section("mai").Key("danmaku").Int() - conf.listen = cfg.Section("mai").Key("listen").String() - conf.staticpath = cfg.Section("mai").Key("static").String() - conf.tmplpath = cfg.Section("mai").Key("templates").String() + conf.group = cfg.Section("mai").Key("group").String() + conf.listen = cfg.Section("http").Key("listen").String() + conf.requests, _ = cfg.Section("http").Key("requests").Int() + conf.static = cfg.Section("paths").Key("static").String() + conf.templates = cfg.Section("paths").Key("templates").String() + conf.user = cfg.Section("mai").Key("user").String() return nil } diff --git a/docs/api/index.html b/docs/api/index.html deleted file mode 100644 index 4a96142..0000000 --- a/docs/api/index.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - API Documentation | Mai - - -

API documentation

- - - - - - - - - - - - - - - - - - - -
-

[GET] /api/translate

-

[POST] /api/translate

-

Description

-

Translation endpoint, input must be URL-encoded (e.g. multi-byte characters, words separated by space)

-

Arguments

-
    -
  • engine
  • -
  • from
  • -
  • text
  • -
  • to
  • -
-
-

[GET] /api/source_languages

-

[GET] /api/target_languages

-

Description

-

Get a JSON array of supported source and target languages for a particular engine

-

Arguments

-
    -
  • engine
  • -
-
-

[GET] /api/tts

-

Description

-

Obtain text-to-speech audio files from an engine, provided said engine supports them

-

Arguments

-
    -
  • engine
  • -
  • lang
  • -
  • text
  • -
-
-

[GET] /robots.txt

-
-

[POST] /switchlanguages

-

Description

-

Switch between source and target languages, as long as the source language isn't "auto"

-

Must only be called inside the form interface

-
-

[GET] /version

-

Description

-

Return the software version as a JSON array

-
- - diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 3dcb9b7..0000000 --- a/docs/index.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - Mai | Documentation - - - - - -
- - - - -
API
-
- - - - -
-

Welcome to Mai's documentation!

-

See the menu for the available entries

-

Anything else is covered by the man pages

-
-
- - - diff --git a/docs/style.css b/docs/style.css deleted file mode 100644 index 1b24e42..0000000 --- a/docs/style.css +++ /dev/null @@ -1,22 +0,0 @@ -body { - background-color: #f8cfd2; - color: rgb(206, 147, 191); -} - -a, a:visited { - color: rgb(206, 147, 191); -} - -@media screen and (prefers-color-scheme: dark) { - body { - background-color: #700000; - color: #ffffff; - } - a, a:visited { - color: #18c018; - } -} - -table { - border-color: white; -} diff --git a/example/mai.apache.conf b/example/mai.apache.conf new file mode 100644 index 0000000..2678e02 --- /dev/null +++ b/example/mai.apache.conf @@ -0,0 +1,19 @@ + + ServerName mai.example.com + ServerAlias mai.example.com + RewriteEngine on + RewriteCond %{SERVER_NAME} =mai.example.com + RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] + + + ServerName mai.example.com + ServerAlias mai.example.com + SSLEngine on + SSLCertificateFile /usr/pkg/etc/letsencrypt/live/example.com/fullchain.pem + SSLCertificateKeyFile /usr/pkg/etc/letsencrypt/live/example.com/privkey.pem + ProxyRequests off + ProxyPass / http://127.0.0.1:5000/ + ProxyPassReverse / http://127.0.0.1:5000/ + ProxyPreserveHost On + + diff --git a/example/mai.ini b/example/mai.ini index e697070..558c96b 100644 --- a/example/mai.ini +++ b/example/mai.ini @@ -1,4 +1,19 @@ +[http] +# TCP socket to listen on. +# Must not be already used by something else. +listen = 127.0.0.1:5000 +# How many requests per minute are allowed +# before a rate-limit happens. +requests = 10 [mai] -listen = "127.0.0.1:5000" -rootdir = "./static" -tmplpath = "./views" +# Drop privilege to the user and group specified. +# When only the user is specified, the default group of the user will +# be used. +# +# user = www +# group = www +[paths] +# Where to locate resources such as CSS, etc +static = ./static +# Where to locate the pages to be served +templates = ./views diff --git a/example/mai.nginx b/example/mai.nginx index 8df6a4d..2f5f3ad 100644 --- a/example/mai.nginx +++ b/example/mai.nginx @@ -1,7 +1,7 @@ server { listen 80; listen [::]:80; - server_name mai.example.com; + server_name mai.example.org; location / { return 301 https://$host$request_uri; @@ -11,7 +11,7 @@ server { server { listen 443 ssl; listen [::]:443 ssl; - server_name mai.example.com; + server_name mai.example.org; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; diff --git a/go.mod b/go.mod index dd72b4b..5bf8768 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module marisa.chaotic.ninja/mai +module mahou-no-mori.yakumo.dev/mai go 1.20 diff --git a/mai.ini.5 b/mai.ini.5 deleted file mode 100644 index 98d3066..0000000 --- a/mai.ini.5 +++ /dev/null @@ -1,40 +0,0 @@ -.Dd $Mdocdate$ -.Dt MAI.INI 5 -.Os -.Sh NAME -.Nm mai.ini -.Nd Configuration file for Mai -.Sh OPTIONS -.Ss [mai] section -.Bl -tag -width 11n -.It danmaku (int) -Control the maximum amount of requests -before a ratelimit happens -.It listen (string) -HTTP port for the server to listen. -Default is "localhost:5000" -.It static (string) -Directory where the static resources are located. -Default is "./static" -.It templates (string) -Directory where the templates are located. -Default is "./views" -.El -.Sh ENVIRONMENT -.Bl -tag -width 11n -.It Ev MAI_LIBRETRANSLATE_INSTANCE -LibreTranslate instance to use, it's required for the engine to work. -.It Ev MAI_LIBRETRANSLATE_API -LibreTranslate API key for the above setting, it may or -may not be required, depending on the instance. -.El -.Sh FILES -.Pa /usr/local/etc/mai/mai.ini -.Sh SEE ALSO -.Xr mai 1 -.Sh AUTHORS -.An fattalion -.An metalune -.An ManeraKai Lk https://manerakai.com -.Sh MAINTAINERS -.An Izuru Yakumo Aq Mt yakumo.izuru@chaotic.ninja diff --git a/rc.d/FreeBSD b/rc.d/FreeBSD index 05c4233..bcd58c5 100644 --- a/rc.d/FreeBSD +++ b/rc.d/FreeBSD @@ -1,5 +1,5 @@ #!/bin/sh -# $TheSupernovaDuo$ +# $YakumoLabs$ # # PROVIDE: mai # REQUIRE: DAEMON NETWORKING syslog diff --git a/rc.d/NetBSD b/rc.d/NetBSD index 8133c4e..d341966 100644 --- a/rc.d/NetBSD +++ b/rc.d/NetBSD @@ -1,21 +1,19 @@ #!/bin/sh -# $TheSupernovaDuo$ +# $YakumoLabs$ # # PROVIDE: mai # REQUIRE: NETWORKING DAEMON -# BEFORE: LOGIN -# KEYWORD: shutdown $_rc_subr_loaded . /etc/rc.subr name="mai" rcvar=$name -command="/usr/pkg/bin/mai" -command_args="-f /usr/pkg/etc/mai/mai.ini -u www -g www" +command="/usr/local/bin/mai" +command_args="-f /usr/local/etc/mai/mai.ini" pidfile="/var/run/${name}.pid" start_cmd="mai_start" -required_files="/usr/pkg/etc/mai/mai.ini" +required_files="/usr/local/etc/mai/mai.ini" mai_start() { $command $command_args diff --git a/rc.d/OpenBSD b/rc.d/OpenBSD index a223415..acbab3d 100644 --- a/rc.d/OpenBSD +++ b/rc.d/OpenBSD @@ -1,8 +1,8 @@ #!/bin/ksh -# $TheSupernovaDuo$ +# $YakumoLabs$ daemon="/usr/local/bin/mai" -daemon_flags="-f /usr/local/etc/mai/mai.ini -u www -g www" +daemon_flags="-f /usr/local/etc/mai/mai.ini" . /etc/rc.d/rc.subr diff --git a/rc.d/immortal.yml b/rc.d/immortal.yml index 9013888..5632d44 100644 --- a/rc.d/immortal.yml +++ b/rc.d/immortal.yml @@ -1,2 +1,3 @@ -cmd: /usr/local/bin/mai -f /usr/local/etc/mai/mai.ini -g www -u www +# $YakumoLabs$ +cmd: /usr/local/bin/mai -f /usr/local/etc/mai/mai.ini cwd: /usr/local/share/mai diff --git a/rc.d/mai.service b/rc.d/mai.service new file mode 100644 index 0000000..a360c58 --- /dev/null +++ b/rc.d/mai.service @@ -0,0 +1,13 @@ +# $YakumoLabs$ +[Unit] +Description=Mai +Documentation=https://suzunaan.yakumo.dev/mai + +[Service] +Type=simple +Restart=always +RestartSec=5 +ExecStart=/usr/local/bin/mai -f /usr/local/etc/mai/mai.ini + +[Install] +WantedBy=multi-user.target diff --git a/rc.d/mokou.conf b/rc.d/mokou.conf new file mode 100644 index 0000000..e114ed9 --- /dev/null +++ b/rc.d/mokou.conf @@ -0,0 +1,4 @@ +# $YakumoLabs$ +description=Mai +exec=/usr/bin/env daemonize -p /var/run/mai.pid /usr/local/bin/mai -f /usr/local/etc/mai.ini +pidfile=/var/run/mai.pid diff --git a/rc.d/s6 b/rc.d/s6 new file mode 100644 index 0000000..d0a09cd --- /dev/null +++ b/rc.d/s6 @@ -0,0 +1,4 @@ +#!/command/execlineb -P +# $YakumoLabs$ +/usr/local/bin/mai +-f /usr/local/etc/mai/mai.ini diff --git a/version.go b/version.go index 3605571..99803ba 100644 --- a/version.go +++ b/version.go @@ -7,12 +7,9 @@ import ( var ( // Version release version Version = "0.0.1" - - // Commit will be overwritten automatically by the build system - Commit = "HEAD" ) // FullVersion display the full version and build func FullVersion() string { - return fmt.Sprintf("%s@%s", Version, Commit) + return fmt.Sprintf("%s", Version) }