diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4facb3e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,19 @@
+build:
+ @echo "Building the website..."
+ go build -o bin/alfheimgame
+ cp -r ui bin
+ cp -r static bin
+ cp favicon.ico bin
+ GOOS=linux GOARCH=amd64 go build -o bin/linux_amd64/alfheimgame
+ cp -r ui bin/linux_amd64
+ cp -r static bin/linux_amd64
+ cp favicon.ico bin/linux_amd64
+
+.PHONY: deploy
+deploy:
+ rsync -rP --delete bin/linux_amd64 alfheim@alfheimgame.com:~
+
+.PHONY: service
+service:
+ rsync -P alfheimgame.service alfheim@alfheimgame.com:~
+ ssh -t alfheim@alfheimgame.com 'sudo mv ~/alfheimgame.service /etc/systemd/system && sudo systemctl enable alfheimgame && sudo systemctl restart alfheimgame'
diff --git a/alfheimgame.service b/alfheimgame.service
new file mode 100644
index 0000000..4034817
--- /dev/null
+++ b/alfheimgame.service
@@ -0,0 +1,24 @@
+[Unit]
+Description=alfheimgame.com website service
+
+After=network-online.target
+Wants=network-online.target
+
+StartLimitIntervalSec=600
+StartLimitBurst=5
+
+[Service]
+Type=exec
+User=alfheim
+Group=alfheim
+CapabilityBoundingSet=CAP_NET_BIND_SERVICE
+AmbientCapabilities=CAP_NET_BIND_SERVICE
+EnvironmentFile=/etc/environment
+WorkingDirectory=/home/alfheim/linux_amd64
+ExecStart=/home/alfheim/linux_amd64/alfheimgame -addr ':8080'
+
+Restart=on-failure
+RestartSec=5
+
+[Install]
+WantedBy=multi-user.target
diff --git a/bin/alfheimgame b/bin/alfheimgame
new file mode 100755
index 0000000..0dae38d
Binary files /dev/null and b/bin/alfheimgame differ
diff --git a/bin/favicon.ico b/bin/favicon.ico
new file mode 100755
index 0000000..fd13ee6
Binary files /dev/null and b/bin/favicon.ico differ
diff --git a/bin/linux_amd64/alfheimgame b/bin/linux_amd64/alfheimgame
new file mode 100755
index 0000000..0dae38d
Binary files /dev/null and b/bin/linux_amd64/alfheimgame differ
diff --git a/bin/linux_amd64/favicon.ico b/bin/linux_amd64/favicon.ico
new file mode 100755
index 0000000..fd13ee6
Binary files /dev/null and b/bin/linux_amd64/favicon.ico differ
diff --git a/bin/linux_amd64/static/Vollkorn-VariableFont_wght.ttf b/bin/linux_amd64/static/Vollkorn-VariableFont_wght.ttf
new file mode 100644
index 0000000..188fd06
Binary files /dev/null and b/bin/linux_amd64/static/Vollkorn-VariableFont_wght.ttf differ
diff --git a/bin/linux_amd64/static/image.png b/bin/linux_amd64/static/image.png
new file mode 100644
index 0000000..0475eda
Binary files /dev/null and b/bin/linux_amd64/static/image.png differ
diff --git a/bin/linux_amd64/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg b/bin/linux_amd64/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg
new file mode 100644
index 0000000..1163dcb
--- /dev/null
+++ b/bin/linux_amd64/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg
@@ -0,0 +1 @@
+
diff --git a/bin/linux_amd64/static/style.css b/bin/linux_amd64/static/style.css
new file mode 100644
index 0000000..5f20b0e
--- /dev/null
+++ b/bin/linux_amd64/static/style.css
@@ -0,0 +1,194 @@
+html {
+ height: 100%;
+ padding: 8px;
+ /*background: no-repeat url(/static/image.png);
+ background-size: cover;
+ background-position: center;*/
+ background-color: black;
+ box-sizing: border-box;
+}
+
+body {
+ background-color: #3475CB;
+ font-family: "Vollkorn";
+ color: white;
+ margin-top: 0px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 0px;
+ min-height: 100%;
+ max-width: 900px;
+}
+
+header {
+ max-width: 100%;
+}
+
+h1 {
+ font-size: 6rem;
+ margin: 0px;
+}
+
+nav {
+ padding-left: 8px;
+ padding-right: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.navbuttons a {
+ display: inline-block;
+}
+
+.maintitle {
+ color: white;
+}
+
+.loginbutton {
+ align-self: center;
+ display: flex;
+ background-color: ;
+ padding-top: 15px;
+ padding-right: 20px;
+ padding-bottom: 15px;
+ padding-left: 20px;
+ border-radius: 5px;
+ color: black;
+ /*box-shadow: 10px 10px 5px lightblue;*/
+}
+
+main {
+ margin: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: start;
+ align-content: center;
+ min-height: 100%;
+ max-height: 100%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+p {
+ text-align: center;
+}
+
+.account-wrapper {
+ background: transparent;
+ border: 2px solid white;
+ backdrop-filter: blur(20px);
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ border-radius: 15px;
+ padding: 30px 40px;
+ font-size: 1.5rem;
+}
+
+.wrapper {
+ background: transparent;
+ border: 2px solid white;
+ backdrop-filter: blur(20px);
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ border-radius: 15px;
+ padding: 30px 40px;
+
+}
+
+.wrapper h1 {
+ font-size: 1.5rem;
+ text-align: center;
+}
+
+.wrapper .input-box {
+ width: 100%;
+}
+
+.input-box input {
+ box-sizing: border-box;
+ background: transparent;
+ width: 100%;
+ height: 100%;
+ outline: none;
+ border: 2px solid rgba(255, 255, 255, .2);
+ border-radius: 25px;
+ padding: 10px 45px 10px 20px
+}
+
+.input-box input::placeholder {
+ color: white;
+}
+
+.wrapper .input-error {
+ width: 100%;
+}
+
+.error {
+ color: rgba(240, 0, 0, .8);
+}
+
+.input-error input {
+ box-sizing: border-box;
+ background: transparent;
+ width: 100%;
+ height: 100%;
+ outline: none;
+ border: 2px solid rgba(255, 0, 0, .2);
+ border-radius: 25px;
+ padding: 10px 45px 10px 20px
+}
+
+.input-error input::placeholder {
+ color: red;
+}
+
+.login-btn-wrapper {
+ display: flex;
+ justify-content: center;
+}
+
+.wrapper .btn {
+ width: 100%;
+ outline: none;
+ border: none;
+ border-radius: 20px;
+}
+
+.wrapper .register-link {
+ display: flex;
+ justify-content: center;
+}
+
+input {
+ font-family: inherit;
+}
+
+footer {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ background-color: #132123;
+ color: white;
+ text-align: center;
+}
+
+a:link {
+ text-decoration: none;
+}
+
+.wrapper a:link {
+ text-decoration: none;
+}
+
+.wrapper a:visited {
+ text-decoration: none;
+}
+
+.wrapper a:hover {
+ text-decoration: underline;
+}
+
+video {
+ width: 100%;
+ height: auto;
+}
diff --git a/bin/linux_amd64/static/video.mp4 b/bin/linux_amd64/static/video.mp4
new file mode 100644
index 0000000..a9f4427
Binary files /dev/null and b/bin/linux_amd64/static/video.mp4 differ
diff --git a/bin/linux_amd64/ui/account.html b/bin/linux_amd64/ui/account.html
new file mode 100644
index 0000000..6d7f407
--- /dev/null
+++ b/bin/linux_amd64/ui/account.html
@@ -0,0 +1,22 @@
+{{define "body"}}
+
+
Username: {{.Account.Username}}
+
First name: {{.Account.Firstname}}
+
Last name: {{.Account.Lastname}}
+
Color: {{.Account.Color}}
+
+
+
+{{end}}
diff --git a/bin/linux_amd64/ui/base.html b/bin/linux_amd64/ui/base.html
new file mode 100644
index 0000000..4e2b9b8
--- /dev/null
+++ b/bin/linux_amd64/ui/base.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+ Alfheim
+
+
+
+
+
+
+
+
+
+
+
+
+ {{template "body" .}}
+
+
+
+ Alfheim © 2024, Vicente Ferrari Smith, Los Andes Studios, Vienna, Austria. All rights reserved.
+
+
+
diff --git a/bin/linux_amd64/ui/index.html b/bin/linux_amd64/ui/index.html
new file mode 100644
index 0000000..bc7e800
--- /dev/null
+++ b/bin/linux_amd64/ui/index.html
@@ -0,0 +1,9 @@
+{{define "body"}}
+Alfheim is a game about humanity: our own will, and our place in the world at large.
+Alfheim is an MMO where you—the player—administers a medieval settlement of elves.
+In an infinite world, and with thousands of other players, you will have to design an efficient command economy, if you wish to be able to compete with your enemies... Or your friends?
+
+Your browser does not support the video tag.
+
+
+{{end}}
diff --git a/bin/linux_amd64/ui/login.html b/bin/linux_amd64/ui/login.html
new file mode 100644
index 0000000..ed38137
--- /dev/null
+++ b/bin/linux_amd64/ui/login.html
@@ -0,0 +1,39 @@
+{{define "body"}}
+
+{{end}}
diff --git a/bin/linux_amd64/ui/logout.html b/bin/linux_amd64/ui/logout.html
new file mode 100644
index 0000000..690d0bc
--- /dev/null
+++ b/bin/linux_amd64/ui/logout.html
@@ -0,0 +1,11 @@
+{{define "body"}}
+
+{{end}}
diff --git a/bin/linux_amd64/ui/register.html b/bin/linux_amd64/ui/register.html
new file mode 100644
index 0000000..66777f5
--- /dev/null
+++ b/bin/linux_amd64/ui/register.html
@@ -0,0 +1,45 @@
+{{define "body"}}
+
+{{end}}
diff --git a/bin/linux_amd64/ui/subscribe.html b/bin/linux_amd64/ui/subscribe.html
new file mode 100644
index 0000000..fb1f4a2
--- /dev/null
+++ b/bin/linux_amd64/ui/subscribe.html
@@ -0,0 +1,8 @@
+{{define "body"}}
+{{range .Prices}}
+
+ {{$price := divide .UnitAmountDecimal 100}}
+ {{.Currency}} {{printf "%.2f" $price}}
+
+{{end}}
+{{end}}
diff --git a/bin/linux_amd64/ui/subscribe_stripe.html b/bin/linux_amd64/ui/subscribe_stripe.html
new file mode 100644
index 0000000..bbdf87e
--- /dev/null
+++ b/bin/linux_amd64/ui/subscribe_stripe.html
@@ -0,0 +1,5 @@
+{{define "body"}}
+
+
+
+{{end}}
diff --git a/bin/static/Vollkorn-VariableFont_wght.ttf b/bin/static/Vollkorn-VariableFont_wght.ttf
new file mode 100644
index 0000000..188fd06
Binary files /dev/null and b/bin/static/Vollkorn-VariableFont_wght.ttf differ
diff --git a/bin/static/image.png b/bin/static/image.png
new file mode 100644
index 0000000..0475eda
Binary files /dev/null and b/bin/static/image.png differ
diff --git a/bin/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg b/bin/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg
new file mode 100644
index 0000000..1163dcb
--- /dev/null
+++ b/bin/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg
@@ -0,0 +1 @@
+
diff --git a/bin/static/style.css b/bin/static/style.css
new file mode 100644
index 0000000..5f20b0e
--- /dev/null
+++ b/bin/static/style.css
@@ -0,0 +1,194 @@
+html {
+ height: 100%;
+ padding: 8px;
+ /*background: no-repeat url(/static/image.png);
+ background-size: cover;
+ background-position: center;*/
+ background-color: black;
+ box-sizing: border-box;
+}
+
+body {
+ background-color: #3475CB;
+ font-family: "Vollkorn";
+ color: white;
+ margin-top: 0px;
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 0px;
+ min-height: 100%;
+ max-width: 900px;
+}
+
+header {
+ max-width: 100%;
+}
+
+h1 {
+ font-size: 6rem;
+ margin: 0px;
+}
+
+nav {
+ padding-left: 8px;
+ padding-right: 8px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.navbuttons a {
+ display: inline-block;
+}
+
+.maintitle {
+ color: white;
+}
+
+.loginbutton {
+ align-self: center;
+ display: flex;
+ background-color: ;
+ padding-top: 15px;
+ padding-right: 20px;
+ padding-bottom: 15px;
+ padding-left: 20px;
+ border-radius: 5px;
+ color: black;
+ /*box-shadow: 10px 10px 5px lightblue;*/
+}
+
+main {
+ margin: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: start;
+ align-content: center;
+ min-height: 100%;
+ max-height: 100%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+p {
+ text-align: center;
+}
+
+.account-wrapper {
+ background: transparent;
+ border: 2px solid white;
+ backdrop-filter: blur(20px);
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ border-radius: 15px;
+ padding: 30px 40px;
+ font-size: 1.5rem;
+}
+
+.wrapper {
+ background: transparent;
+ border: 2px solid white;
+ backdrop-filter: blur(20px);
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ border-radius: 15px;
+ padding: 30px 40px;
+
+}
+
+.wrapper h1 {
+ font-size: 1.5rem;
+ text-align: center;
+}
+
+.wrapper .input-box {
+ width: 100%;
+}
+
+.input-box input {
+ box-sizing: border-box;
+ background: transparent;
+ width: 100%;
+ height: 100%;
+ outline: none;
+ border: 2px solid rgba(255, 255, 255, .2);
+ border-radius: 25px;
+ padding: 10px 45px 10px 20px
+}
+
+.input-box input::placeholder {
+ color: white;
+}
+
+.wrapper .input-error {
+ width: 100%;
+}
+
+.error {
+ color: rgba(240, 0, 0, .8);
+}
+
+.input-error input {
+ box-sizing: border-box;
+ background: transparent;
+ width: 100%;
+ height: 100%;
+ outline: none;
+ border: 2px solid rgba(255, 0, 0, .2);
+ border-radius: 25px;
+ padding: 10px 45px 10px 20px
+}
+
+.input-error input::placeholder {
+ color: red;
+}
+
+.login-btn-wrapper {
+ display: flex;
+ justify-content: center;
+}
+
+.wrapper .btn {
+ width: 100%;
+ outline: none;
+ border: none;
+ border-radius: 20px;
+}
+
+.wrapper .register-link {
+ display: flex;
+ justify-content: center;
+}
+
+input {
+ font-family: inherit;
+}
+
+footer {
+ position: fixed;
+ left: 0;
+ bottom: 0;
+ width: 100%;
+ background-color: #132123;
+ color: white;
+ text-align: center;
+}
+
+a:link {
+ text-decoration: none;
+}
+
+.wrapper a:link {
+ text-decoration: none;
+}
+
+.wrapper a:visited {
+ text-decoration: none;
+}
+
+.wrapper a:hover {
+ text-decoration: underline;
+}
+
+video {
+ width: 100%;
+ height: auto;
+}
diff --git a/bin/static/video.mp4 b/bin/static/video.mp4
new file mode 100644
index 0000000..a9f4427
Binary files /dev/null and b/bin/static/video.mp4 differ
diff --git a/bin/ui/account.html b/bin/ui/account.html
new file mode 100644
index 0000000..6d7f407
--- /dev/null
+++ b/bin/ui/account.html
@@ -0,0 +1,22 @@
+{{define "body"}}
+
+
Username: {{.Account.Username}}
+
First name: {{.Account.Firstname}}
+
Last name: {{.Account.Lastname}}
+
Color: {{.Account.Color}}
+
+
+
+{{end}}
diff --git a/bin/ui/base.html b/bin/ui/base.html
new file mode 100644
index 0000000..4e2b9b8
--- /dev/null
+++ b/bin/ui/base.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+ Alfheim
+
+
+
+
+
+
+
+
+
+
+
+
+ {{template "body" .}}
+
+
+
+ Alfheim © 2024, Vicente Ferrari Smith, Los Andes Studios, Vienna, Austria. All rights reserved.
+
+
+
diff --git a/bin/ui/index.html b/bin/ui/index.html
new file mode 100644
index 0000000..bc7e800
--- /dev/null
+++ b/bin/ui/index.html
@@ -0,0 +1,9 @@
+{{define "body"}}
+Alfheim is a game about humanity: our own will, and our place in the world at large.
+Alfheim is an MMO where you—the player—administers a medieval settlement of elves.
+In an infinite world, and with thousands of other players, you will have to design an efficient command economy, if you wish to be able to compete with your enemies... Or your friends?
+
+Your browser does not support the video tag.
+
+
+{{end}}
diff --git a/bin/ui/login.html b/bin/ui/login.html
new file mode 100644
index 0000000..ed38137
--- /dev/null
+++ b/bin/ui/login.html
@@ -0,0 +1,39 @@
+{{define "body"}}
+
+{{end}}
diff --git a/bin/ui/logout.html b/bin/ui/logout.html
new file mode 100644
index 0000000..690d0bc
--- /dev/null
+++ b/bin/ui/logout.html
@@ -0,0 +1,11 @@
+{{define "body"}}
+
+{{end}}
diff --git a/bin/ui/register.html b/bin/ui/register.html
new file mode 100644
index 0000000..66777f5
--- /dev/null
+++ b/bin/ui/register.html
@@ -0,0 +1,45 @@
+{{define "body"}}
+
+{{end}}
diff --git a/bin/ui/subscribe.html b/bin/ui/subscribe.html
new file mode 100644
index 0000000..fb1f4a2
--- /dev/null
+++ b/bin/ui/subscribe.html
@@ -0,0 +1,8 @@
+{{define "body"}}
+{{range .Prices}}
+
+ {{$price := divide .UnitAmountDecimal 100}}
+ {{.Currency}} {{printf "%.2f" $price}}
+
+{{end}}
+{{end}}
diff --git a/bin/ui/subscribe_stripe.html b/bin/ui/subscribe_stripe.html
new file mode 100644
index 0000000..bbdf87e
--- /dev/null
+++ b/bin/ui/subscribe_stripe.html
@@ -0,0 +1,5 @@
+{{define "body"}}
+
+
+
+{{end}}
diff --git a/go.mod b/go.mod
index 2266997..1b1f312 100644
--- a/go.mod
+++ b/go.mod
@@ -12,5 +12,7 @@ require (
require (
github.com/gorilla/securecookie v1.1.2 // indirect
+ golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.20.0 // indirect
+ golang.org/x/text v0.15.0 // indirect
)
diff --git a/main.go b/main.go
index 36cc7cd..dfd1345 100644
--- a/main.go
+++ b/main.go
@@ -12,10 +12,10 @@ import _ "github.com/lib/pq"
import "database/sql"
import "github.com/gorilla/sessions"
import "regexp"
-//import "golang.org/x/crypto/bcrypt"
+import "golang.org/x/crypto/acme/autocert"
+import "crypto/tls"
import "github.com/stripe/stripe-go/v78"
-//import "github.com/stripe/stripe-go/v78/customer"
var users *Usermodel
var subscriptions *SubscriptionModel
@@ -27,6 +27,7 @@ var emailrx = regexp.MustCompile("/^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-
func main() {
addr := flag.String("addr", ":80", "HTTP network addr")
+ _ = addr
flag.Parse()
fmt.Println("Hello, Sailor!")
@@ -83,6 +84,19 @@ func main() {
//mux.HandleFunc("/managebilling", require_authenticated_user(managebilling))
//mux.HandleFunc("/webhook", webhooks)
+ cert := &autocert.Manager{
+ Prompt: autocert.AcceptTOS,
+ HostPolicy: autocert.HostWhitelist("alfheimgame.com", "www.alfheimgame.com"),
+ Cache: autocert.DirCache("certs"),
+ }
- log.Fatal(http.ListenAndServe(*addr, secure_headers(mux)))
+ server := &http.Server{
+ Addr: ":443",
+ Handler: secure_headers(mux),
+ TLSConfig: &tls.Config{GetCertificate: cert.GetCertificate},
+ }
+
+ go http.ListenAndServe(":http", cert.HTTPHandler(nil))
+
+ log.Fatal(server.ListenAndServeTLS("", ""))
}
diff --git a/ui/index.html b/ui/index.html
index 5bb087d..bc7e800 100644
--- a/ui/index.html
+++ b/ui/index.html
@@ -3,7 +3,7 @@
Alfheim is an MMO where you—the player—administers a medieval settlement of elves.
In an infinite world, and with thousands of other players, you will have to design an efficient command economy, if you wish to be able to compete with your enemies... Or your friends?
-Your browser does not support the video tag.
+Your browser does not support the video tag.
{{end}}