-
Notifications
You must be signed in to change notification settings - Fork 7
/
chat.go
154 lines (130 loc) · 3.37 KB
/
chat.go
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package main
import (
"context"
"errors"
"fmt"
"log/slog"
"strings"
"cloud.google.com/go/datastore"
)
const (
chatKey = "chat-%d"
chatKind = "rmapi-token"
)
type AccountType int
const (
_ AccountType = iota
AccountTypeRM
AccountTypeKindle
AccountTypeDropbox
)
func (at AccountType) String() string {
switch at {
default:
return fmt.Sprintf("<UNKNOWN-%d>", at)
case AccountTypeRM:
return "rm"
case AccountTypeKindle:
return "kindle"
case AccountTypeDropbox:
return "dropbox"
}
}
func (at AccountType) MarshalText() ([]byte, error) {
switch at {
default:
return nil, fmt.Errorf("unknown account type %d", at)
case AccountTypeRM:
fallthrough
case AccountTypeKindle:
fallthrough
case AccountTypeDropbox:
return []byte(at.String()), nil
}
}
func (at *AccountType) UnmarshalText(text []byte) error {
switch strings.ToLower(strings.TrimSpace(string(text))) {
default:
return fmt.Errorf("unknown account type %q", text)
case "":
// special default fallback for backward compatibility
fallthrough
case "rm":
*at = AccountTypeRM
case "kindle":
*at = AccountTypeKindle
case "dropbox":
*at = AccountTypeDropbox
}
return nil
}
// EntityChatToken is the entity rmapi token for a chat stored in datastore.
type EntityChatToken struct {
Chat int64 `datastore:"chat" json:"chat"`
Type AccountType `datastore:"type" json:"type"`
FitImage int `datastore:"fit_image" json:"fit_image"`
// reMarkable related fields
RMToken string `datastore:"token" json:"token"`
RMParentID string `datastore:"parent" json:"parent"`
RMFont string `datastore:"font" json:"font"`
// kindle related fields
KindleEmail string `datastore:"email" json:"email"`
// dropbox related fields
DropboxToken string `datastore:"dropbox_token" json:"dropbox_token"`
DropboxFolder string `datastore:"dropbox_folder" json:"dropbox_folder"`
}
func (e *EntityChatToken) getKey() string {
return fmt.Sprintf(chatKey, e.Chat)
}
func (e *EntityChatToken) datastoreKey() *datastore.Key {
return datastore.NameKey(chatKind, e.getKey(), nil)
}
// GetParentID returns the ParentID to use, after stripping prefix,
func (e *EntityChatToken) GetParentID() string {
return strings.TrimPrefix(e.RMParentID, dirIDPrefix)
}
// GetFont returns the Font to use, after stripping prefix,
func (e *EntityChatToken) GetFont() string {
return strings.TrimPrefix(e.RMFont, fontPrefix)
}
// SaveDatastore saves this entity into datastore.
func (e *EntityChatToken) SaveDatastore(ctx context.Context) error {
key := e.datastoreKey()
_, err := dsClient.Put(ctx, key, e)
return err
}
// Save saves this entity into datastore
func (e *EntityChatToken) Save(ctx context.Context) error {
return e.SaveDatastore(ctx)
}
// Delete deletes this entity from datastore.
func (e *EntityChatToken) Delete(ctx context.Context) {
key := e.datastoreKey()
if err := dsClient.Delete(ctx, key); err != nil {
slog.ErrorContext(
ctx,
"Failed to delete datastore key",
"err", err,
"key", key,
)
}
}
// GetChat gets an entity from db.
func GetChat(ctx context.Context, id int64) *EntityChatToken {
e := &EntityChatToken{
Chat: id,
}
key := e.datastoreKey()
if err := dsClient.Get(ctx, key, e); err != nil {
if !errors.Is(err, datastore.ErrNoSuchEntity) {
slog.ErrorContext(
ctx,
"Failed to get datastore key",
"err", err,
"key", key,
)
}
return nil
}
return e
}