Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
kardolus
GitHub Repository: kardolus/chatgpt-cli
Path: blob/main/history/store.go
2649 views
1
package history
2
3
import (
4
"encoding/json"
5
"github.com/kardolus/chatgpt-cli/config"
6
"github.com/kardolus/chatgpt-cli/internal"
7
"os"
8
"path"
9
"path/filepath"
10
)
11
12
const jsonExtension = ".json"
13
14
type Store interface {
15
Read() ([]History, error)
16
ReadThread(string) ([]History, error)
17
Write([]History) error
18
SetThread(string)
19
GetThread() string
20
}
21
22
// Ensure FileIO implements the HistoryStore interface
23
var _ Store = &FileIO{}
24
25
type FileIO struct {
26
historyDir string
27
thread string
28
}
29
30
func New() (*FileIO, error) {
31
_ = migrate()
32
33
dir, err := internal.GetDataHome()
34
if err != nil {
35
return nil, err
36
}
37
38
chatGPTDir, err := internal.GetConfigHome()
39
if err != nil {
40
return nil, err
41
}
42
43
fileInfo, err := os.Stat(chatGPTDir)
44
if err == nil {
45
if fileInfo.IsDir() {
46
err = os.MkdirAll(dir, 0755)
47
}
48
}
49
50
return &FileIO{
51
historyDir: dir,
52
}, err
53
}
54
55
func (f *FileIO) GetThread() string {
56
return f.thread
57
}
58
59
func (f *FileIO) SetThread(thread string) {
60
f.thread = thread
61
}
62
63
func (f *FileIO) WithDirectory(historyDir string) *FileIO {
64
f.historyDir = historyDir
65
return f
66
}
67
68
func (f *FileIO) Read() ([]History, error) {
69
return parseFile(f.getPath(f.thread))
70
}
71
72
func (f *FileIO) ReadThread(thread string) ([]History, error) {
73
return parseFile(f.getPath(thread))
74
}
75
76
func (f *FileIO) Write(historyEntries []History) error {
77
data, err := json.Marshal(historyEntries)
78
if err != nil {
79
return err
80
}
81
82
return os.WriteFile(f.getPath(f.thread), data, 0644)
83
}
84
85
func (f *FileIO) getPath(thread string) string {
86
return filepath.Join(f.historyDir, thread+jsonExtension)
87
}
88
89
// migrate moves the legacy "history" file in ~/.chatgpt-cli to "history/default.json"
90
func migrate() error {
91
hiddenDir, err := internal.GetConfigHome()
92
if err != nil {
93
return err
94
}
95
96
historyFile, err := internal.GetDataHome()
97
if err != nil {
98
return err
99
}
100
101
fileInfo, err := os.Stat(historyFile)
102
if err != nil {
103
return err
104
}
105
106
if !fileInfo.IsDir() {
107
defaults := config.NewStore().ReadDefaults()
108
109
// move the legacy "history" file to "default.json"
110
if err := os.Rename(historyFile, path.Join(hiddenDir, defaults.Thread+jsonExtension)); err != nil {
111
return err
112
}
113
114
// create the "history" directory
115
if err := os.Mkdir(historyFile, 0755); err != nil {
116
return err
117
}
118
119
// move default.json to the "history" directory
120
if err := os.Rename(path.Join(hiddenDir, defaults.Thread+jsonExtension), path.Join(historyFile, defaults.Thread+jsonExtension)); err != nil {
121
return err
122
}
123
}
124
125
return nil
126
}
127
128
func parseFile(fileName string) ([]History, error) {
129
var result []History
130
131
buf, err := os.ReadFile(fileName)
132
if err != nil {
133
return nil, err
134
}
135
136
if err := json.Unmarshal(buf, &result); err != nil {
137
return nil, err
138
}
139
140
return result, nil
141
}
142
143