118 lines
3.0 KiB
Go
118 lines
3.0 KiB
Go
// Copyright (C) 2021 nytpu
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
// For more license details, see LICENSE or <https://www.gnu.org/licenses/agpl-3.0.html>.
|
|
|
|
// This file incorporates code from makeworld's amfora:
|
|
// https://github.com/makeworld-the-better-one/amfora/blob/master/subscriptions/structs.go
|
|
// Original source is Copyright 2020 makeworld and is licensed under the
|
|
// terms of the GNU General Public License Version 3.0.
|
|
// https://www.gnu.org/licenses/gpl-3.0-standalone.html
|
|
|
|
// package core implements the structs and other necessary resources for storing
|
|
// and managing feeds and pages
|
|
package core
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
)
|
|
|
|
// Global instance of FullData
|
|
var Data = FullData{
|
|
FeedsMu: &sync.RWMutex{},
|
|
PagesMu: &sync.RWMutex{},
|
|
// Maps are created in init()
|
|
}
|
|
|
|
// the Header of feeds.gmi.
|
|
// set in Init, either to the contents of header.gmi or to the default string
|
|
var Header string
|
|
|
|
// Timeout for requests
|
|
var Timeout int
|
|
|
|
// have to do this instead of the automatically called init() because
|
|
// initialization stuff requires parsing of command line args first
|
|
func Init(dataPath string) error {
|
|
// initialize comitium.json & data maps
|
|
f, err := os.Open(filepath.Join(dataPath, "comitium.json"))
|
|
if err == nil {
|
|
// File exists and could be opened
|
|
fi, err := f.Stat()
|
|
if err == nil && fi.Size() > 0 {
|
|
// File is not empty
|
|
jsonBytes, err := ioutil.ReadAll(f)
|
|
f.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("read comitium.json error: %w", err)
|
|
}
|
|
err = json.Unmarshal(jsonBytes, &Data)
|
|
if err != nil {
|
|
return fmt.Errorf("comitium.json is corrupted: %w", err)
|
|
}
|
|
}
|
|
f.Close()
|
|
} else if !os.IsNotExist(err) {
|
|
// There's an error opening the file, but it's not bc is doesn't exist
|
|
return fmt.Errorf("open comitium.json error: %w", err)
|
|
}
|
|
|
|
if Data.Feeds == nil {
|
|
Data.Feeds = make(map[string]*Feed)
|
|
}
|
|
if Data.Pages == nil {
|
|
Data.Pages = make(map[string]*Page)
|
|
}
|
|
|
|
// initialize header.gmi
|
|
f, err = os.Open(filepath.Join(dataPath, "header.gmi"))
|
|
if err == nil {
|
|
fi, err := f.Stat()
|
|
if err == nil && fi.Size() > 0 {
|
|
headerBytes, err := ioutil.ReadAll(f)
|
|
f.Close()
|
|
if err != nil {
|
|
return fmt.Errorf("read header.gmi error: %w", err)
|
|
}
|
|
Header = string(headerBytes)
|
|
}
|
|
f.Close()
|
|
} else if !os.IsNotExist(err) {
|
|
return fmt.Errorf("open header.gmi error: %w", err)
|
|
}
|
|
|
|
if Header == "" {
|
|
Header = `# comitium subscriptions
|
|
|
|
`
|
|
}
|
|
|
|
Timeout = 10
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *FullData) WriteJSON(dataPath string) error {
|
|
// use .new so if there's a corruption when writing the old file is intact
|
|
path := filepath.Join(dataPath, "comitium.json.new")
|
|
|
|
d.RLock()
|
|
jsonBytes, err := json.MarshalIndent(&d, "", "\t")
|
|
d.RUnlock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ioutil.WriteFile(path, jsonBytes, 0666)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// if full write was successful then overwrite original
|
|
err = os.Rename(path, filepath.Join(dataPath, "comitium.json"))
|
|
return err
|
|
}
|