git-svn-id: svn://losandesgames.com/alfheim-website@50 15359d88-9307-4e75-a9c1-e5686e5897df
10
Makefile
@ -7,17 +7,15 @@ build:
|
||||
mkdir bin/static
|
||||
mkdir bin/ui
|
||||
go build -ldflags="-s -X main.version=$(svn_revision)" -o bin/alfheim-website ./cmd/web
|
||||
cp -r ui bin
|
||||
cp -r static bin
|
||||
cp favicon.ico bin
|
||||
cp -r ui/html bin
|
||||
cp -r ui/static bin
|
||||
cp Caddyfile bin
|
||||
mkdir bin/linux_amd64
|
||||
mkdir bin/linux_amd64/static
|
||||
mkdir bin/linux_amd64/ui
|
||||
GOOS=linux GOARCH=amd64 go build -ldflags="-s -X main.version=$(svn_revision)" -o bin/linux_amd64/alfheim-website ./cmd/web
|
||||
cp -r ui bin/linux_amd64
|
||||
cp -r static bin/linux_amd64
|
||||
cp favicon.ico bin/linux_amd64
|
||||
cp -r ui/html bin/linux_amd64
|
||||
cp -r ui/static bin/linux_amd64
|
||||
cp Caddyfile bin/linux_amd64
|
||||
|
||||
run:
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
{
|
||||
email vicenteferrarismith@gmail.com
|
||||
}
|
||||
|
||||
alfheimgame.com {
|
||||
reverse_proxy localhost:4000
|
||||
}
|
||||
@ -1,7 +0,0 @@
|
||||
{
|
||||
email vicenteferrarismith@gmail.com
|
||||
}
|
||||
|
||||
alfheimgame.com {
|
||||
reverse_proxy localhost:4000
|
||||
}
|
||||
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 25 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000"><path d="M480-120v-80h280v-560H480v-80h280q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H480Zm-80-160-55-58 102-102H120v-80h327L345-622l55-58 200 200-200 200Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 173 B |
@ -1,202 +0,0 @@
|
||||
html {
|
||||
/*background: no-repeat url(/static/image.png);
|
||||
background-size: cover;
|
||||
background-position: center;*/
|
||||
height: 100vh;
|
||||
background-color: black;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: #3475CB;
|
||||
font-family: "Vollkorn";
|
||||
color: white;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 900px;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
|
||||
}
|
||||
|
||||
nav {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.navbuttons a {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.maintitle {
|
||||
margin: 0px;
|
||||
font-size: 6rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
.maintitle {
|
||||
font-size: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.loginbutton {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
border: 12px solid;
|
||||
border-image-source: url("/static/panel-000.png");
|
||||
border-image-slice: 12 fill;
|
||||
padding-top: 15px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 15px;
|
||||
padding-left: 20px;
|
||||
color: black;
|
||||
/*box-shadow: 10px 10px 5px lightblue;*/
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 8px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100%;
|
||||
max-height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.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 {
|
||||
display: inline-block;
|
||||
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;
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.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 {
|
||||
/*margin-top: auto;*/
|
||||
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;
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="account-wrapper">
|
||||
<div>Username: {{.Account.Username}}</div>
|
||||
<div>First name: {{.Account.Firstname}}</div>
|
||||
<div>Last name: {{.Account.Lastname}}</div>
|
||||
<div>Color: {{.Account.Color}}</div>
|
||||
</div>
|
||||
|
||||
<div class="wrapper">
|
||||
<form action="/deleteaccount" method="post">
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Delete Account" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form method="POST" action="/managebilling">
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Manage Billing" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,48 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Alfheim</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="A handcrafted economy and politics MMO." />
|
||||
<meta name="author" content="Vicente Ferrari Smith" />
|
||||
<meta name="keywords" content="Alfheim, indie, video game, mmo, colony, colony simulator, vicente ferrari smith, game, economy, politics, alfheim" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Vollkorn";
|
||||
src: url(/static/Vollkorn-VariableFont_wght.ttf);
|
||||
}
|
||||
</style>
|
||||
<link href="/static/style.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/"><h1 class="maintitle">Alfheim</h1></a>
|
||||
<div class="navbuttons">
|
||||
{{if not .ActiveSubscription}}
|
||||
<a href="/subscribe"><div class="loginbutton"><strong>Subscribe</strong></div></a>
|
||||
{{end}}
|
||||
|
||||
{{if .AuthenticatedUser}}
|
||||
<a href="/account"><div class="loginbutton"><strong>Account</strong></div></a>
|
||||
<a href="/logout"><div class="loginbutton"><strong>Log out</strong></div></a>
|
||||
{{else}}
|
||||
<a href="/login"><div class="loginbutton"><strong>Log in</strong><img src="/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg" alt=""/></div></a>
|
||||
<a href="/register"><div class="loginbutton"><strong>Register</strong></div></a>
|
||||
{{end}}
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
{{template "body" .}}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
Alfheim © 2025, Vicente Ferrari Smith, Los Andes Games, Vienna, Austria. All rights reserved.
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,9 +0,0 @@
|
||||
{{define "body"}}
|
||||
<p>Alfheim is a game about humanity: our own will, and our place in the world at large.</p>
|
||||
<p>Alfheim is an MMO where you—the player—administer 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?</p>
|
||||
<br \>
|
||||
<video playsinline loop autoplay muted><source src="/static/video.mp4" type="video/mp4">Your browser does not support the video tag.</video>
|
||||
<br \>
|
||||
<img src="/static/image.png" alt="Alfheim" style="height: 100%; width: 100%; object-fit: contain">
|
||||
{{end}}
|
||||
@ -1,39 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="wrapper">
|
||||
<form method="POST">
|
||||
<h1>Log in</h1>
|
||||
|
||||
{{with .FormErrors.generic}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
{{with .FormErrors.username}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div {{if .FormErrors.username}}class="input-error"{{else}}class="input-box"{{end}}>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
{{with .FormErrors.password}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div {{if .FormErrors.password}}class="input-error"{{else}}class="input-box"{{end}}>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Log in" class="btn">
|
||||
</div>
|
||||
<br />
|
||||
<a href="/forgotten">Have you forgotten your password?</a>
|
||||
|
||||
<div class="register-link">
|
||||
<p>Don't have an account? <a href="/register">Register</a></p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,11 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="wrapper">
|
||||
<form method="POST">
|
||||
<h1>Log out</h1>
|
||||
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Log out" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,45 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="wrapper">
|
||||
<form method="POST">
|
||||
<h1>Register</h1>
|
||||
|
||||
{{with .FormErrors.username}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div class="input-box" {{with .FormErrors.username}}class="input-error"{{end}}>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
|
||||
<div class="input-box">
|
||||
<input type="email" id="email" name="email" placeholder="Email" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="input-box">
|
||||
<input type="text" id="firstname" name="firstname" placeholder="First Name" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="input-box">
|
||||
<input type="text" id="lastname" name="lastname" placeholder="Last Name" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
{{with .FormErrors.password}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div class="input-box" {{with .FormErrors.password}}class="input-error"{{end}}>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Register" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,8 +0,0 @@
|
||||
{{define "body"}}
|
||||
{{range .Prices}}
|
||||
<div class="wrapper">
|
||||
{{$price := divide .UnitAmountDecimal 100}}
|
||||
{{.Currency}} {{printf "%.2f" $price}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@ -1,5 +0,0 @@
|
||||
{{define "body"}}
|
||||
<script async src="https://js.stripe.com/v3/pricing-table.js"></script>
|
||||
<stripe-pricing-table pricing-table-id="prctbl_1PIaJpKUHKCjyTmcy1ONKQiT" publishable-key="pk_test_51PGebgKUHKCjyTmcyuhj7C5lfHfKFLCxRJ2opoqxL3mGEHSRaMvOHYKKgX4MdFfESW78dssjyunboUcFhg3LTwmn005PmzVIXw" customer-session-client-secret={{.ClientSecret}}>
|
||||
</stripe-pricing-table>
|
||||
{{end}}
|
||||
|
Before Width: | Height: | Size: 25 KiB |
@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000"><path d="M480-120v-80h280v-560H480v-80h280q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H480Zm-80-160-55-58 102-102H120v-80h327L345-622l55-58 200 200-200 200Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 173 B |
@ -1,202 +0,0 @@
|
||||
html {
|
||||
/*background: no-repeat url(/static/image.png);
|
||||
background-size: cover;
|
||||
background-position: center;*/
|
||||
height: 100vh;
|
||||
background-color: black;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
background-color: #3475CB;
|
||||
font-family: "Vollkorn";
|
||||
color: white;
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
max-width: 900px;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
|
||||
}
|
||||
|
||||
nav {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.navbuttons a {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.maintitle {
|
||||
margin: 0px;
|
||||
font-size: 6rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (max-width: 1080px) {
|
||||
.maintitle {
|
||||
font-size: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.loginbutton {
|
||||
align-self: center;
|
||||
display: flex;
|
||||
border: 12px solid;
|
||||
border-image-source: url("/static/panel-000.png");
|
||||
border-image-slice: 12 fill;
|
||||
padding-top: 15px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 15px;
|
||||
padding-left: 20px;
|
||||
color: black;
|
||||
/*box-shadow: 10px 10px 5px lightblue;*/
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 8px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100%;
|
||||
max-height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.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 {
|
||||
display: inline-block;
|
||||
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;
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.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 {
|
||||
/*margin-top: auto;*/
|
||||
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;
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="account-wrapper">
|
||||
<div>Username: {{.Account.Username}}</div>
|
||||
<div>First name: {{.Account.Firstname}}</div>
|
||||
<div>Last name: {{.Account.Lastname}}</div>
|
||||
<div>Color: {{.Account.Color}}</div>
|
||||
</div>
|
||||
|
||||
<div class="wrapper">
|
||||
<form action="/deleteaccount" method="post">
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Delete Account" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form method="POST" action="/managebilling">
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Manage Billing" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,48 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Alfheim</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="description" content="A handcrafted economy and politics MMO." />
|
||||
<meta name="author" content="Vicente Ferrari Smith" />
|
||||
<meta name="keywords" content="Alfheim, indie, video game, mmo, colony, colony simulator, vicente ferrari smith, game, economy, politics, alfheim" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Vollkorn";
|
||||
src: url(/static/Vollkorn-VariableFont_wght.ttf);
|
||||
}
|
||||
</style>
|
||||
<link href="/static/style.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<a href="/"><h1 class="maintitle">Alfheim</h1></a>
|
||||
<div class="navbuttons">
|
||||
{{if not .ActiveSubscription}}
|
||||
<a href="/subscribe"><div class="loginbutton"><strong>Subscribe</strong></div></a>
|
||||
{{end}}
|
||||
|
||||
{{if .AuthenticatedUser}}
|
||||
<a href="/account"><div class="loginbutton"><strong>Account</strong></div></a>
|
||||
<a href="/logout"><div class="loginbutton"><strong>Log out</strong></div></a>
|
||||
{{else}}
|
||||
<a href="/login"><div class="loginbutton"><strong>Log in</strong><img src="/static/login_24dp_FILL0_wght400_GRAD0_opsz24.svg" alt=""/></div></a>
|
||||
<a href="/register"><div class="loginbutton"><strong>Register</strong></div></a>
|
||||
{{end}}
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
{{template "body" .}}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
Alfheim © 2025, Vicente Ferrari Smith, Los Andes Games, Vienna, Austria. All rights reserved.
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,9 +0,0 @@
|
||||
{{define "body"}}
|
||||
<p>Alfheim is a game about humanity: our own will, and our place in the world at large.</p>
|
||||
<p>Alfheim is an MMO where you—the player—administer 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?</p>
|
||||
<br \>
|
||||
<video playsinline loop autoplay muted><source src="/static/video.mp4" type="video/mp4">Your browser does not support the video tag.</video>
|
||||
<br \>
|
||||
<img src="/static/image.png" alt="Alfheim" style="height: 100%; width: 100%; object-fit: contain">
|
||||
{{end}}
|
||||
@ -1,39 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="wrapper">
|
||||
<form method="POST">
|
||||
<h1>Log in</h1>
|
||||
|
||||
{{with .FormErrors.generic}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
{{with .FormErrors.username}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div {{if .FormErrors.username}}class="input-error"{{else}}class="input-box"{{end}}>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
{{with .FormErrors.password}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div {{if .FormErrors.password}}class="input-error"{{else}}class="input-box"{{end}}>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Log in" class="btn">
|
||||
</div>
|
||||
<br />
|
||||
<a href="/forgotten">Have you forgotten your password?</a>
|
||||
|
||||
<div class="register-link">
|
||||
<p>Don't have an account? <a href="/register">Register</a></p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,11 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="wrapper">
|
||||
<form method="POST">
|
||||
<h1>Log out</h1>
|
||||
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Log out" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,45 +0,0 @@
|
||||
{{define "body"}}
|
||||
<div class="wrapper">
|
||||
<form method="POST">
|
||||
<h1>Register</h1>
|
||||
|
||||
{{with .FormErrors.username}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div class="input-box" {{with .FormErrors.username}}class="input-error"{{end}}>
|
||||
<input type="text" id="username" name="username" placeholder="Username" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
|
||||
<div class="input-box">
|
||||
<input type="email" id="email" name="email" placeholder="Email" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="input-box">
|
||||
<input type="text" id="firstname" name="firstname" placeholder="First Name" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="input-box">
|
||||
<input type="text" id="lastname" name="lastname" placeholder="Last Name" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
{{with .FormErrors.password}}
|
||||
<label class="error">{{.}}</label>
|
||||
{{end}}
|
||||
|
||||
<div class="input-box" {{with .FormErrors.password}}class="input-error"{{end}}>
|
||||
<input type="password" id="password" name="password" placeholder="Password" required>
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="login-btn-wrapper">
|
||||
<input type="submit" value="Register" class="btn">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
@ -1,8 +0,0 @@
|
||||
{{define "body"}}
|
||||
{{range .Prices}}
|
||||
<div class="wrapper">
|
||||
{{$price := divide .UnitAmountDecimal 100}}
|
||||
{{.Currency}} {{printf "%.2f" $price}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@ -1,5 +0,0 @@
|
||||
{{define "body"}}
|
||||
<script async src="https://js.stripe.com/v3/pricing-table.js"></script>
|
||||
<stripe-pricing-table pricing-table-id="prctbl_1PIaJpKUHKCjyTmcy1ONKQiT" publishable-key="pk_test_51PGebgKUHKCjyTmcyuhj7C5lfHfKFLCxRJ2opoqxL3mGEHSRaMvOHYKKgX4MdFfESW78dssjyunboUcFhg3LTwmn005PmzVIXw" customer-session-client-secret={{.ClientSecret}}>
|
||||
</stripe-pricing-table>
|
||||
{{end}}
|
||||
@ -377,7 +377,7 @@ func subscribe(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func subscribe_stripe(w http.ResponseWriter, r *http.Request) {
|
||||
func subscribeStripe(w http.ResponseWriter, r *http.Request) {
|
||||
id := authenticatedUser(w, r)
|
||||
account, err := users.GetAccount(id)
|
||||
|
||||
@ -412,7 +412,7 @@ func subscribe_stripe(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func managebilling(w http.ResponseWriter, r *http.Request) {
|
||||
func manageBilling(w http.ResponseWriter, r *http.Request) {
|
||||
id := authenticatedUser(w, r)
|
||||
account, err := users.GetAccount(id)
|
||||
if err != nil {
|
||||
@ -510,11 +510,11 @@ func webhooks(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func handle_checkout_session_completed(checkoutsession stripe.CheckoutSession) error {
|
||||
func handle_checkout_session_completed(checkoutSession stripe.CheckoutSession) error {
|
||||
//toprint, _ := json.MarshalIndent(checkoutSession, "", " ")
|
||||
//log.Println(string(toprint))
|
||||
|
||||
subscription, err := subscription.Get(checkoutsession.Subscription.ID, nil)
|
||||
subscription, err := subscription.Get(checkoutSession.Subscription.ID, nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
@ -542,19 +542,19 @@ func handle_checkout_session_completed(checkoutsession stripe.CheckoutSession) e
|
||||
// status = paused
|
||||
//}
|
||||
|
||||
subscriptions.Insert(checkoutsession.Customer.ID, subscription.ID, checkoutsession.ID, subscription.Status)
|
||||
subscriptions.Insert(checkoutSession.Customer.ID, subscription.ID, checkoutSession.ID, subscription.Status)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func handle_payment_method_attached(paymentmethod stripe.PaymentMethod) error {
|
||||
func handlePaymentMethodAttached(paymentMethod stripe.PaymentMethod) error {
|
||||
//toprint, _ := json.MarshalIndent(setupintent, "", " ")
|
||||
//log.Println(string(toprint))
|
||||
|
||||
// make this the new customer's default payment method
|
||||
params := &stripe.CustomerParams{}
|
||||
params.DefaultSource = &paymentmethod.ID
|
||||
/*result*/ _, err := customer.Update(paymentmethod.Customer.ID, params)
|
||||
params.DefaultSource = &paymentMethod.ID
|
||||
/*result*/ _, err := customer.Update(paymentMethod.Customer.ID, params)
|
||||
//log.Println(result)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
|
||||
@ -98,8 +98,8 @@ func main() {
|
||||
mux.HandleFunc("/register", register)
|
||||
mux.HandleFunc("/account", requireAuthenticatedUser(account))
|
||||
mux.HandleFunc("/deleteaccount", requireAuthenticatedUser(deleteAccount))
|
||||
mux.HandleFunc("/subscribe", requireAuthenticatedUser(subscribe_stripe))
|
||||
mux.HandleFunc("/managebilling", requireAuthenticatedUser(managebilling))
|
||||
mux.HandleFunc("/subscribe", requireAuthenticatedUser(subscribeStripe))
|
||||
mux.HandleFunc("/managebilling", requireAuthenticatedUser(manageBilling))
|
||||
mux.HandleFunc("/webhook", webhooks)
|
||||
|
||||
if *production {
|
||||
|
||||
@ -7,7 +7,6 @@ package models
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
_ "github.com/lib/pq"
|
||||
)
|
||||
|
||||
var ErrNoRecord = errors.New("no matching record found")
|
||||
|
||||
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |