2024-09-11 06:53:12 -05:00
package main
import (
"context"
2024-09-11 15:02:36 -05:00
"errors"
2024-09-11 06:53:12 -05:00
"fmt"
2024-09-11 15:02:36 -05:00
"log"
2024-09-11 06:53:12 -05:00
"log/slog"
"net/http"
2024-09-11 15:02:36 -05:00
"time"
2024-09-11 06:53:12 -05:00
2024-09-11 15:02:36 -05:00
"github.com/gin-gonic/gin"
2024-09-11 06:53:12 -05:00
"github.com/jackc/pgx/v5"
2024-09-11 15:02:36 -05:00
"github.com/jackc/pgx/v5/pgxpool"
2024-09-11 06:53:12 -05:00
)
2024-09-11 15:02:36 -05:00
/* Variables */
var connPool * pgxpool . Pool
func Config ( ) ( * pgxpool . Config ) {
const defaultMaxConns = int32 ( 4 )
const defaultMinConns = int32 ( 0 )
const defaultMaxConnLifetime = time . Hour
const defaultMaxConnIdleTime = time . Minute * 30
const defaultHealthCheckPeriod = time . Minute
const defaultConnectTimeout = time . Second * 5
// Your own Database URL
const DATABASE_URL string = "postgres://tooloftheweek:b4lKAuHRz3Xho6WUQq4YUGnfiAQs5zNg@10.0.100.172:5432/tooloftheweek"
dbConfig , err := pgxpool . ParseConfig ( DATABASE_URL )
if err != nil {
log . Fatal ( "Failed to create a config, error: " , err )
}
dbConfig . MaxConns = defaultMaxConns
dbConfig . MinConns = defaultMinConns
dbConfig . MaxConnLifetime = defaultMaxConnLifetime
dbConfig . MaxConnIdleTime = defaultMaxConnIdleTime
dbConfig . HealthCheckPeriod = defaultHealthCheckPeriod
dbConfig . ConnConfig . ConnectTimeout = defaultConnectTimeout
dbConfig . BeforeAcquire = func ( ctx context . Context , c * pgx . Conn ) bool {
slog . Info ( "Before acquiring the connection pool to the database" )
return true
}
dbConfig . AfterRelease = func ( c * pgx . Conn ) bool {
slog . Info ( "After releasing the connection pool to the database" )
return true
}
dbConfig . BeforeClose = func ( c * pgx . Conn ) {
slog . Info ( "Closed the connection pool to the database" )
}
return dbConfig
}
/* Structs */
2024-09-11 06:53:12 -05:00
type tool struct {
2024-09-11 15:02:36 -05:00
Name string
Description string
Url string
Week_to_post int
2024-09-11 06:53:12 -05:00
}
2024-09-11 15:02:36 -05:00
/* Database Functions*/
2024-09-11 06:53:12 -05:00
func database_connection ( url string ) ( * pgx . Conn , error ) {
var err error
conn , err := pgx . Connect ( context . Background ( ) , url )
if err != nil {
slog . Error ( "Could not connect to database" )
}
return conn , err
}
2024-09-11 15:02:36 -05:00
func insertTool ( conn * pgx . Conn , new_tool tool ) error {
2024-09-11 06:53:12 -05:00
_ , err := conn . Exec ( context . Background ( ) , "INSERT INTO tool_tb(name,description) VALUES($1,$2)" , new_tool . Name , new_tool . Description )
if err != nil {
slog . Error ( "Could not insert new tool into database" )
if err . Error ( ) == ` ERROR: duplicate key value violates unique constraint "tool_tb_name_key" (SQLSTATE 23505) ` {
slog . Error ( "Tool already in database." )
} else {
fmt . Println ( err )
}
return err
}
return nil
}
2024-09-11 15:02:36 -05:00
func currentTool ( ) ( tool , error ) {
var currenttool tool
var currentweek int
//Calculate current week
2024-09-18 17:12:49 -05:00
currenttime := int ( time . Now ( ) . Unix ( ) ) + 259200
2024-09-18 17:08:17 -05:00
currentweek = currenttime / 604800
2024-09-11 15:02:36 -05:00
fmt . Println ( currentweek )
//Select current tool from database
2024-09-12 18:02:53 -05:00
rows , err := connPool . Query ( context . Background ( ) , "SELECT id,name,description,url,week_to_post FROM tool_tb WHERE week_to_post=$1" , currentweek )
2024-09-11 15:02:36 -05:00
if err != nil {
slog . Error ( "Could not query tools_tb" )
}
for rows . Next ( ) {
var id int
var name string
var description string
var url string
2024-09-12 18:02:53 -05:00
var week_to_post int
2024-09-11 15:02:36 -05:00
//var currenttoolinloop tool
2024-09-12 18:02:53 -05:00
rows . Scan ( & id , & name , & description , & url , & week_to_post )
2024-09-11 15:02:36 -05:00
if name == "" {
return currenttool , errors . New ( "Could not find tool for current week. Please update tool list." )
}
slog . Info ( "Found tool: " + name )
currenttool . Name = name
currenttool . Description = description
currenttool . Url = url
2024-09-12 18:02:53 -05:00
currenttool . Week_to_post = week_to_post
2024-09-11 15:02:36 -05:00
}
return currenttool , nil
}
func getTools ( ) ( [ ] tool , error ) {
var err error
var tools [ ] tool
rows , err := connPool . Query ( context . Background ( ) , "SELECT id,name,description,url,week_to_post FROM tool_tb" )
if err != nil {
slog . Error ( "Could not query tool_tb" )
return nil , err
}
for rows . Next ( ) {
var id int
var name string
var description string
var url string
var week_to_post int
var currenttoolinloop tool
err := rows . Scan ( & id , & name , & description , & url , & week_to_post )
if err != nil {
slog . Error ( "Could not scan query" )
return nil , err
}
currenttoolinloop . Name = name
currenttoolinloop . Description = description
currenttoolinloop . Url = url
currenttoolinloop . Week_to_post = week_to_post
tools = append ( tools , currenttoolinloop )
}
return tools , nil
}
/* Gin Functions */
func getToolsHandler ( c * gin . Context ) {
//var tools []tool
tools , err := getTools ( )
if err != nil {
fmt . Println ( err )
}
fmt . Println ( tools )
c . IndentedJSON ( http . StatusOK , tools )
}
func currentToolHandler ( c * gin . Context ) {
var currenttool tool
//var tools []tool
currenttool , err := currentTool ( )
if err != nil {
fmt . Println ( err )
}
fmt . Println ( currenttool )
c . IndentedJSON ( http . StatusOK , currenttool )
}
func insertToolHandler ( c * gin . Context ) {
var newTool tool
c . IndentedJSON ( http . StatusCreated , newTool )
}
func updateToolHandler ( c * gin . Context ) {
var updatedTool tool
c . IndentedJSON ( http . StatusOK , updatedTool )
}
func deleteToolHandler ( c * gin . Context ) {
var removedTool tool
c . IndentedJSON ( http . StatusOK , removedTool )
}
2024-09-11 06:53:12 -05:00
func main ( ) {
2024-09-11 15:02:36 -05:00
2024-09-11 06:53:12 -05:00
var err error
2024-09-11 15:02:36 -05:00
connPool , err = pgxpool . NewWithConfig ( context . Background ( ) , Config ( ) )
2024-09-11 06:53:12 -05:00
if err != nil {
2024-09-11 15:02:36 -05:00
log . Fatal ( "Error acquiring connection from database." )
2024-09-11 06:53:12 -05:00
}
2024-09-11 15:02:36 -05:00
conn , err := connPool . Acquire ( context . Background ( ) )
if err != nil {
log . Fatal ( "Error while acquiring connection from the database pool!!" )
}
defer conn . Release ( )
err = conn . Ping ( context . Background ( ) )
2024-09-11 06:53:12 -05:00
if err != nil {
2024-09-11 15:02:36 -05:00
log . Fatal ( "Could not ping database." )
2024-09-11 06:53:12 -05:00
}
2024-09-11 15:02:36 -05:00
slog . Info ( "Connection to database successful." )
2024-09-11 06:53:12 -05:00
2024-09-11 15:02:36 -05:00
_ , err = conn . Exec ( context . Background ( ) , "CREATE TABLE IF NOT EXISTS tool_tb (id SERIAL, name TEXT UNIQUE, url TEXT, description TEXT, time_created TIMESTAMP, week_to_post INT)" )
if err != nil {
slog . Error ( "Could not create tool table." )
}
router := gin . Default ( )
router . GET ( "/api/v0/tools" , getToolsHandler )
router . GET ( "/api/v0/tooloftheweek" , currentToolHandler )
router . POST ( "/api/v0/inserttool" , insertToolHandler )
router . POST ( "/api/v0/updatetool" , updateToolHandler )
router . POST ( "/api/v0/deletetool" , deleteToolHandler )
2024-09-11 06:53:12 -05:00
2024-09-12 18:05:53 -05:00
router . Run ( "0.0.0.0:8080" )
2024-09-11 06:53:12 -05:00
}