add hemtt support, major refactor

- no longer supports server events
- can now more easily build using hemtt
- extension vastly improved in both structure and functionality
- tested on listen server
- includes schema change
This commit is contained in:
2023-09-20 01:15:13 -07:00
parent f692b94c5c
commit 29228bd192
51 changed files with 5008 additions and 1466 deletions

View File

@@ -0,0 +1,62 @@
package db
import (
"fmt"
"github.com/indig0fox/a3go/a3interface"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var db *gorm.DB
var config ConfigStruct
type ConfigStruct struct {
MySQLHost string `json:"mysqlHost"`
MySQLPort int `json:"mysqlPort"`
MySQLUser string `json:"mysqlUser"`
MySQLPassword string `json:"mysqlPassword"`
MySQLDatabase string `json:"mysqlDatabase"`
}
func SetConfig(c ConfigStruct) {
config = c
}
func Client() *gorm.DB {
return db
}
func Connect() error {
// connect to database
var err error
dsn := fmt.Sprintf(
"%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True",
config.MySQLUser,
config.MySQLPassword,
config.MySQLHost,
config.MySQLPort,
config.MySQLDatabase,
)
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
return err
}
// try ping
sqlDB, err := db.DB()
if err != nil {
return err
}
err = sqlDB.Ping()
if err != nil {
return err
}
a3interface.WriteArmaCallback("connectDB", `["Database connected", "INFO"]`)
a3interface.WriteArmaCallback("connectDB", `["SUCCESS", "INFO"]`)
return nil
}

View File

@@ -0,0 +1,129 @@
package logger
import (
"fmt"
"strings"
"time"
"github.com/indig0fox/a3go/a3interface"
"github.com/rs/zerolog"
"gopkg.in/natefinch/lumberjack.v2"
)
var ll *lumberjack.Logger
var armaWriter *armaIoWriter
var Log, FileOnly, ArmaOnly zerolog.Logger
var ActiveOptions *LoggerOptionsType = &LoggerOptionsType{}
type LoggerOptionsType struct {
// LogPath is the path to the log file
Path string
// LogAddonName is the name of the addon that will be used to send log messages to arma
AddonName string
// LogExtensionName is the name of the extension that will be used to send log messages to arma
ExtensionName string
// ExtensionVersion is the version of this extension
ExtensionVersion string
// LogDebug determines if we should send Debug level messages to file & arma
Debug bool
// LogTrace is used to determine if file should receive trace level, regardless of debug
Trace bool
}
func RotateLogs() {
ll.Rotate()
}
// ArmaIoWriter is a custom type that implements the io.Writer interface and sends the output to Arma with the "log" callback
type armaIoWriter struct{}
func (w *armaIoWriter) Write(p []byte) (n int, err error) {
// write to arma log
a3interface.WriteArmaCallback(ActiveOptions.ExtensionName, ":LOG:", string(p))
return len(p), nil
}
// console writer
func InitLoggers(o *LoggerOptionsType) {
ActiveOptions = o
// create a new lumberjack file logger (adds log rotation and compression)
ll = &lumberjack.Logger{
Filename: ActiveOptions.Path,
MaxSize: 1,
MaxBackups: 5,
MaxAge: 14,
Compress: true,
LocalTime: true,
}
// create a new io writer using the a3go callback function
// this will be used to write to the arma log
armaWriter = new(armaIoWriter)
// create format functions for RPT log messages
armaLogFormatLevel := func(i interface{}) string {
return strings.ToUpper(
fmt.Sprintf(
"(%s)",
i,
))
}
armaLogFormatTimestamp := func(i interface{}) string {
return ""
}
FileOnly = zerolog.New(zerolog.ConsoleWriter{
Out: ll,
TimeFormat: time.RFC3339,
NoColor: true,
}).With().Timestamp().Caller().Logger()
if ActiveOptions.Trace {
FileOnly = FileOnly.Level(zerolog.TraceLevel)
} else if ActiveOptions.Debug {
FileOnly = FileOnly.Level(zerolog.DebugLevel)
} else {
FileOnly = FileOnly.Level(zerolog.InfoLevel)
}
ArmaOnly = zerolog.New(zerolog.ConsoleWriter{
Out: armaWriter,
TimeFormat: "",
NoColor: true,
FormatLevel: armaLogFormatLevel,
FormatTimestamp: armaLogFormatTimestamp,
}).With().Str("extension_version", ActiveOptions.ExtensionVersion).Logger()
if ActiveOptions.Debug {
ArmaOnly = ArmaOnly.Level(zerolog.DebugLevel)
} else {
ArmaOnly = ArmaOnly.Level(zerolog.InfoLevel)
}
// create something that can send the same message to both loggers
// this is used to send messages to the arma log
// and the file log
Log = zerolog.New(zerolog.MultiLevelWriter(
zerolog.ConsoleWriter{
Out: ll,
TimeFormat: time.RFC3339,
NoColor: true,
},
zerolog.ConsoleWriter{
Out: armaWriter,
TimeFormat: "",
NoColor: true,
FormatTimestamp: armaLogFormatTimestamp,
FormatLevel: armaLogFormatLevel,
},
)).With().Timestamp().Caller().Logger()
if ActiveOptions.Debug {
Log = Log.Level(zerolog.DebugLevel)
} else {
Log = Log.Level(zerolog.InfoLevel)
}
}

View File

@@ -0,0 +1,65 @@
package util
import (
"encoding/json"
"fmt"
"os"
"github.com/spf13/viper"
)
var ConfigJSON = viper.New()
func LoadConfig(modulePathDir string) (string, error) {
ConfigJSON.SetConfigName("AttendanceTracker.config")
ConfigJSON.SetConfigType("json")
ConfigJSON.AddConfigPath(".")
ConfigJSON.AddConfigPath(modulePathDir)
ConfigJSON.SetDefault("armaConfig.dbUpdateInterval", "90s")
ConfigJSON.SetDefault("armaConfig.debug", true)
ConfigJSON.SetDefault("sqlConfig", map[string]interface{}{
"mysqlHost": "localhost",
"mysqlPort": 3306,
"mysqlUser": "root",
"mysqlPassword": "password",
"mysqlDatabase": "a3attendance",
})
ConfigJSON.SetDefault("armaConfig", map[string]interface{}{
"debug": true,
"traceLogToFile": false,
"dbUpdateIntervalS": 60,
})
wd, err := os.Getwd()
if err != nil {
return "", err
}
if err := ConfigJSON.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found; ignore error if desired
return "", fmt.Errorf(
"config file not found, using defaults! searched in %s",
[]string{
ConfigJSON.ConfigFileUsed(),
modulePathDir,
wd,
},
)
} else {
// Config file was found but another error was produced
return "", err
}
}
return "Config loaded successfully!", nil
}
func ConfigArmaFormat() (string, error) {
armaConfig := ConfigJSON.GetStringMap("armaConfig")
bytes, err := json.Marshal(armaConfig)
if err != nil {
return "", err
}
return string(bytes), nil
}