summaryrefslogtreecommitdiff
path: root/core/core.go
blob: afa20d0dc72fb71fa55156b537e4fc95c473146b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// 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"
	"os"
	"path/filepath"
	"sync"
)

// Global instance of FullData
var Data = FullData{
	FeedsMu: &sync.RWMutex{},
	PagesMu: &sync.RWMutex{},
	// Maps are created in init()
}

// 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 {
	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 := io.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)
	}
	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 = os.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
}