/
model.go
336 lines (278 loc) · 5.74 KB
/
model.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
//
// model.go
// template model interfaces
//
package srnd
import (
"time"
)
// base model type
type BaseModel interface {
// set sfw flag
MarkSFW(sfw bool)
// site url prefix
Prefix() string
// impelements json.Marshaller
MarshalJSON() ([]byte, error)
// to json string
JSON() string
// inject I18N
I18N(i *I18N)
}
type ThumbInfo struct {
Width int
Height int
}
// for attachments
type AttachmentModel interface {
BaseModel
Thumbnail() string
Source() string
Filename() string
Hash() string
ThumbInfo() ThumbInfo
}
// for individual posts
type PostModel interface {
BaseModel
Brief() string
CSSClass() string
FrontendPubkey() string
MessageID() string
PostHash() string
ShortHash() string
PostURL() string
Frontend() string
Subject() string
Name() string
Date() string
OP() bool
Attachments() []AttachmentModel
NumAttachments() int
Board() string
Sage() bool
Pubkey() string
PubkeyHex() string
Reference() string
ReferenceHash() string
RenderBody() string
RenderPost() string
RenderBodyPre() string
// replaces Truncate().RenderBody()
RenderTruncatedBody() string
// replaces Truncate().RenderPost()
RenderTruncatedPost() string
// returns true if this post was truncated
IsTruncated() bool
// return true if this post is a mod message
IsCtl() bool
IsI2P() bool
IsTor() bool
IsClearnet() bool
// deprecated
// truncate body to a certain size
// return copy
Truncate() PostModel
// what is our position in this thread?
// 0 for OP, nonzero for reply
Index() int
// set post index
SetIndex(idx int)
// nntp id number
NNTPID() int
}
// interface for models that have a navbar
type NavbarModel interface {
Navbar() string
}
// for threads
type ThreadModel interface {
BaseModel
NavbarModel
SetAllowFiles(allow bool)
AllowFiles() bool
OP() PostModel
Replies() []PostModel
Board() string
BoardURL() string
// return a short version of the thread
// does not include all replies
Truncate() ThreadModel
// number of posts in this thread
PostCount() int
// number of images in this thread
ImageCount() int
// number of posts excluded during truncation
// returns 0 if not truncated
MissingPostCount() int
// number of images excluded during truncation
// returns 0 if not truncated
MissingImageCount() int
// returns true if this thread has truncated replies
HasOmittedReplies() bool
// returns true if this thread has truncated images
HasOmittedImages() bool
// update the thread's replies
Update(db Database)
// is this thread dirty and needing updating?
IsDirty() bool
// mark thread as dirty
MarkDirty()
// is the threa bumplocked?
BumpLock() bool
}
// board interface
// for 1 page on a board
type BoardModel interface {
BaseModel
NavbarModel
Frontend() string
Name() string
Threads() []ThreadModel
AllowFiles() bool
SetAllowFiles(files bool)
// JUST update this thread
// if we don't have it already loaded do nothing
UpdateThread(message_id string, db Database)
// get a thread model with this id
// returns nil if we don't have it
GetThread(message_id string) ThreadModel
// put a thread back after updating externally
PutThread(th ThreadModel)
// deprecated, use GetThread
HasThread(message_id string) bool
// update the board's contents
Update(db Database)
}
type CatalogModel interface {
BaseModel
NavbarModel
Frontend() string
Name() string
Threads() []CatalogItemModel
}
type CatalogItemModel interface {
OP() PostModel
ReplyCount() string
Page() string
MarkSFW(sfw bool)
}
type LinkModel interface {
Text() string
LinkURL() string
}
// newsgroup model
// every page on a newsgroup
type GroupModel []BoardModel
// TODO: optimize using 1 query?
// update every page
func (self *GroupModel) UpdateAll(db Database) {
m := *self
for _, page := range m {
page.Update(db)
}
}
// update a certain page
// does nothing if out of bounds
func (self *GroupModel) Update(page int, db Database) {
m := *self
if len(m) > page {
m[page].Update(db)
}
}
type boardPageRow struct {
Board string
Hour int64
Day int64
All int64
Hi int64
Lo int64
}
type boardPageRows []boardPageRow
func (self boardPageRows) Len() int {
return len(self)
}
func (self boardPageRows) Less(i, j int) bool {
i_val := self[i]
j_val := self[j]
return (i_val.Day + i_val.Hour*24) > (j_val.Day + j_val.Hour*24)
}
func (self boardPageRows) Swap(i, j int) {
self[i], self[j] = self[j], self[i]
}
type postsGraphRow struct {
day time.Time
Num int64
mag int64
}
func (p *postsGraphRow) GraphRune(r string) (s string) {
var num int64
if p.mag > 0 {
num = p.Num / p.mag
} else {
num = p.Num
}
for num > 0 {
s += r
num--
}
return
}
func (p postsGraphRow) Date() (s string) {
return p.day.Format(I18nProvider.Format("month_date_format"))
}
func (p postsGraphRow) Day() (s string) {
return p.day.Format(I18nProvider.Format("day_date_format"))
}
func (p postsGraphRow) RegularGraph() (s string) {
return p.GraphRune("=")
}
// :0========3 overcock :3 graph of data
func (p postsGraphRow) OvercockGraph() (s string) {
var num int64
if p.mag > 0 {
num = p.Num / p.mag
} else {
num = p.Num
}
if num > 0 {
s = ":0"
num -= 1
for num > 0 {
s += "="
num--
}
s += "3"
} else {
s = ":3"
}
return
}
type postsGraph []postsGraphRow
func (self postsGraph) Len() int {
return len(self)
}
func (self postsGraph) Less(i, j int) bool {
i_val := self[i]
j_val := self[j]
return i_val.day.Unix() > j_val.day.Unix()
}
func (self postsGraph) Swap(i, j int) {
self[i], self[j] = self[j], self[i]
}
func (self postsGraph) Scale() (graph postsGraph) {
// find max
max := int64(0)
for _, p := range self {
if p.Num > max {
max = p.Num
}
}
mag := max / 25
for _, p := range self {
p.mag = mag
graph = append(graph, p)
}
return
}
type overviewModel []PostModel