You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
4.6 KiB
Go

package database
import (
// Standard
"encoding/json"
"errors"
"os"
"sync"
)
// Database
type database struct {
path string
mutex sync.Mutex
data databaseData
}
// Database Data
type databaseData struct {
IPv4Address string `json:"ipv4_address"`
IPv6Address string `json:"ipv6_address"`
DDNSEntries []DatabaseDataDDNSEntry `json:"ddns_entries"`
}
// Database Data DDNS Entry
type DatabaseDataDDNSEntry struct {
Record string `json:"record"`
Updated bool `json:"updated"`
Provider string `json:"provider"`
ProviderData interface{} `json:"provider_data"`
}
// Database Data DDNS Entry Provider Data Cloudflare
type DatabaseDataDDNSEntryProviderDataCloudflare struct {
APIToken string `json:"api_token"`
ZoneID string `json:"zone_id"`
}
// Save
func (db *database) save() error {
// Marshal Data
jsonData, err := json.MarshalIndent(db.data, "", " ")
// Handle Error
if err != nil {
return err
}
// Save Data
return os.WriteFile(db.path, jsonData, 0644)
}
// Load
func (db *database) load() error {
// Load Data
jsonData, err := os.ReadFile(db.path)
// Handle Error
if err != nil {
return err
}
// Unmarshal Data
err = json.Unmarshal(jsonData, &db.data)
// Handle Error
if err != nil {
return err
}
// Unmarshal DDNS Entries
for entryNumber, entry := range db.data.DDNSEntries {
switch entry.Provider {
// Cloudflare
case "Cloudflare":
// Entry Data
var entryData DatabaseDataDDNSEntryProviderDataCloudflare
// Marshal Entry Data
data, err := json.Marshal(entry.ProviderData)
// Handle Error
if err != nil {
return err
}
// Unmarshal Entry Data
err = json.Unmarshal(data, &entryData)
// Handle Error
if err != nil {
return err
}
// Set Provider Data
db.data.DDNSEntries[entryNumber].ProviderData = entryData
// Default
default:
return errors.New("unknown ddns entry provider")
}
}
// Success
return nil
}
// Create
func Create(path string) *database {
// Database
db := database{
path: path,
mutex: sync.Mutex{},
data: databaseData{},
}
// Check File
_, err := os.Stat(db.path)
// File Does Not Exist
if os.IsNotExist(err) {
// Create File
file, err := os.Create(db.path)
// Handle Error
if err != nil {
panic(err)
}
// Close File
file.Close()
// Save Database
err = db.save()
// Handle Error
if err != nil {
panic(err)
}
// Success
return &db
} else if err != nil {
// Handle Error
panic(err)
}
// Load
err = db.load()
// Handle Error
if err != nil {
panic(err)
}
// Success
return &db
}
// Set IPv4 Address
func (db *database) SetIPv4Address(ipv4Address string) error {
// Lock
db.mutex.Lock()
defer db.mutex.Unlock()
// Set IPv4 Address
db.data.IPv4Address = ipv4Address
// Reset Updated
for entryNumber := range db.data.DDNSEntries {
db.data.DDNSEntries[entryNumber].Updated = false
}
// Save
return db.save()
}
// Set IPv6 Address
func (db *database) SetIPv6Address(ipv6Address string) error {
// Lock
db.mutex.Lock()
defer db.mutex.Unlock()
// Set IPv6 Address
db.data.IPv6Address = ipv6Address
// Reset Updated
for entryNumber := range db.data.DDNSEntries {
db.data.DDNSEntries[entryNumber].Updated = false
}
// Save
return db.save()
}
// Get IPv4 Address
func (db *database) GetIPv4Address() string {
return db.data.IPv4Address
}
// Get IPv6 Address
func (db *database) GetIPv6Address() string {
return db.data.IPv6Address
}
// Add Entry
func (db *database) AddEntry(entry DatabaseDataDDNSEntry) error {
// Lock
db.mutex.Lock()
defer db.mutex.Unlock()
// Check Entry
for _, existingEntry := range db.data.DDNSEntries {
if entry.Record == existingEntry.Record {
return errors.New("entry exists")
}
}
// Add Entry
db.data.DDNSEntries = append(db.data.DDNSEntries, entry)
// Save
return db.save()
}
// Update Entry
func (db *database) UpdateEntry(record string) error {
// Lock
db.mutex.Lock()
defer db.mutex.Unlock()
// Update Entry
for entryNumber, entry := range db.data.DDNSEntries {
if entry.Record == record {
db.data.DDNSEntries[entryNumber].Updated = true
break
}
}
// Save
return db.save()
}
// Get Entries
func (db *database) GetEntries() []DatabaseDataDDNSEntry {
return db.data.DDNSEntries
}
// Delete Entry
func (db *database) DeleteEntry(record string) error {
// Lock
db.mutex.Lock()
defer db.mutex.Unlock()
// Delete Entry
for entryNumber, entry := range db.data.DDNSEntries {
if entry.Record == record {
db.data.DDNSEntries = append(db.data.DDNSEntries[:entryNumber], db.data.DDNSEntries[entryNumber+1:]...)
}
}
// Save
return db.save()
}