feat: set up project

This commit is contained in:
2023-07-19 11:47:46 +02:00
parent fac61db3f1
commit b426a36570
45 changed files with 2388 additions and 4 deletions

108
cmd/http/server/main.go Normal file
View File

@@ -0,0 +1,108 @@
package main
import (
"context"
"fmt"
"log"
"net/smtp"
"os"
"os/signal"
"strings"
"syscall"
"time"
"gitea.urkob.com/urko/btc-pay-checker/internal/api"
"gitea.urkob.com/urko/btc-pay-checker/internal/platform/mongodb/order"
"gitea.urkob.com/urko/btc-pay-checker/internal/services"
"gitea.urkob.com/urko/btc-pay-checker/internal/services/btc"
"gitea.urkob.com/urko/btc-pay-checker/internal/services/mail"
"gitea.urkob.com/urko/btc-pay-checker/internal/services/price"
"gitea.urkob.com/urko/btc-pay-checker/kit/cfg"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
envFile := ""
if os.Getenv("PAY_CHECKER_ENV") == "dev" {
envFile = ".env"
}
config := cfg.NewConfig(envFile)
log.SetFlags(log.Lmicroseconds)
if config.LogFile {
logFileName := fmt.Sprintf("%s.txt", time.Now().Format(strings.ReplaceAll(time.RFC1123Z, ":", "_")))
f, err := os.OpenFile(logFileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
log.SetOutput(f)
}
dbOpts := options.Client()
dbOpts.ApplyURI(config.DbAddress)
ctx, cancel := context.WithCancel(signalContext(context.Background()))
defer cancel()
client, err := mongo.Connect(ctx, dbOpts)
if err != nil {
panic(fmt.Errorf("mongo.NewClient: %w", err))
}
log.Println("mongodb client is connected")
ordersCollection := client.
Database(config.DbName).
Collection(config.OrdersCollection)
orderRepo := order.NewRepo(ordersCollection)
orderSrv := services.NewOrder(orderRepo)
priceSrv := price.NewPriceConversor(config.ConversorApi, config.ConversorApi)
btcSrv := btc.NewBitcoinService(config.RpcHost, config.RpcAuth, config.RpcZmq, config.WalletAddress).WithTestnet()
mailSrv := mail.NewMailService(
mail.MailServiceConfig{
Auth: smtp.PlainAuth("", config.MailUser, config.MailPassword, config.MailHost),
Host: config.MailHost,
Port: config.MailPort,
From: config.MailFrom,
TemplatesDir: config.MailTemplatesDir,
},
)
restServer := api.NewRestServer(config, orderSrv, btcSrv, priceSrv, mailSrv)
go func() {
if err = restServer.Start(ctx, config.ApiPort, config.Views); err != nil {
panic(fmt.Errorf("restServer.Start: %w", err))
}
}()
<-ctx.Done()
log.Println("on shutdown")
if restServer != nil {
if err := restServer.Shutdown(); err != nil {
panic(fmt.Errorf("restServer.Shutdown: %w", err))
}
}
log.Println("gracefully shutdown")
}
func signalContext(ctx context.Context) context.Context {
ctx, cancel := context.WithCancel(ctx)
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
log.Println("listening for shutdown signal")
<-sigs
log.Println("shutdown signal received")
signal.Stop(sigs)
close(sigs)
cancel()
}()
return ctx
}

52
cmd/http/views/error.hbs Normal file
View File

@@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}
.container {
width: 80%;
margin: auto;
overflow: hidden;
}
.alert {
padding: 20px;
background-color: #f9edbe;
color: #856404;
border: 1px solid #ffeeba;
border-radius: 5px;
margin: 20px 0;
}
.details {
background-color: #fff;
padding: 20px;
border-radius: 5px;
margin: 20px 0;
}
.details h2 {
margin-top: 0;
}
.details p {
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<div class="alert">
<p><strong>Unexpected error: {{message}}</strong></p>
</div>
</div>
</body>
</html>

104
cmd/http/views/order.hbs Normal file
View File

@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}
.container {
width: 80%;
margin: auto;
overflow: hidden;
}
.alert {
padding: 20px;
background-color: #f9edbe;
color: #856404;
border: 1px solid #ffeeba;
border-radius: 5px;
margin: 20px 0;
}
.details {
background-color: #fff;
padding: 20px;
border-radius: 5px;
margin: 20px 0;
}
.details h2 {
margin-top: 0;
}
.details p {
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<div class="alert">
<h1>Bitcoin Payment</h1>
<p>Please send the exact amount of Bitcoin to the provided wallet address. Your order will be processed once the
transaction is confirmed.</p>
</div>
<p id="countdown"><strong>Time Remaining:</strong></p>
<div class="details">
<h2>Order Details</h2>
<p><strong>Order ID:</strong> {{order_id}}</p>
<p><strong>Amount:</strong> {{amount}} BTC</p>
<p><strong>Wallet Address:</strong> {{wallet_address}}</p>
<p id="dueDate"><strong>Payment Due:</strong></p>
<p id="countdown"><strong>Time Remaining:</strong> </p>
</div>
</div>
<script>
// Get the expires_at time from your server and convert it to a JavaScript Date object
const dueDate = new Date("{{expires_at}}");
// Format the date and time
const formattedDate = dueDate.toLocaleDateString() + " " + dueDate.toLocaleTimeString();
// Display the result in the element with id="dueDate"
document.getElementById("dueDate").innerHTML = "<strong>Payment Due:</strong> " + formattedDate;
// Get the expires_at time from your server and convert it to a JavaScript Date object
const countDownDate = new Date("{{expires_at}}").getTime();
// Update the countdown every 1 second
const countdownInterval = setInterval(function () {
// Get today's date and time
const now = new Date().getTime();
// Find the distance between now and the count down date
const distance = countDownDate - now;
// Time calculations for days, hours, minutes and seconds
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
// Display the result in the element with id="countdown"
// document.getElementById("countdown").innerHTML = "<strong>Time Remaining:</strong> " + days + "d " + hours + "h " + minutes + "m " + seconds + "s ";
document.getElementById("countdown").innerHTML = "<strong>Time Remaining:</strong> " + minutes + "m " + seconds + "s ";
// If the countdown is finished, write some text
if (distance < 0) {
clearInterval(countdownInterval);
document.getElementById("countdown").innerHTML = "EXPIRED";
}
}, 1000);
</script>
</body>
</html>