-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontent.go
220 lines (175 loc) · 4.7 KB
/
content.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
package main
import (
"errors"
"github.com/mitchellh/mapstructure"
)
/** @TODOs:
- Limit content size to e.g. 1kb
*/
// IPFSData is be embedded to Post and Comment and only filled when
// loaded from IPFS. It extends Post and Comment with information like
// hash, which is not known beforehand. Do not mistake with IPFSObj,
// which is the general abstraction for blobs in IPFS.
type IPFSData struct {
Hash string
Key string
}
// Post defines the data structure used by our application to handle
// posts and also provides the model for database
type Post struct {
// Alias is authors display name
Alias string
Title string
Content string
// Note that we are using string and not
// int64, because int64 will be converted to
// floats when marshalling from interface{}
Timestamp string
IPFSData
UserData PostUserData
}
// Comment defines the data structure used by our application to
// handle comments and also provides the model for database
type Comment struct {
// Post refers to the posts this comment is submitted to
Post string
// Parent refers to the item (can be post or comment) to which
// this comment is replying to
Parent string
// Alias is authors display name
Alias string
Content string
// Note that we are using string and not
// int64, because int64 will be converted to
// floats when marshalling from interface{}
Timestamp string
IPFSData
UserData CommentUserData
}
// NewPost constructs a new posts and adds it to the IPFS network
func (n *Node) NewPost(user *User, title, content string) (*IPFSObj, error) {
data := Post{
Alias: user.Alias,
Title: title,
Content: content,
Timestamp: Now(),
}
obj, err := NewIPFSObj(n, user, data)
if err != nil {
return nil, err
}
data.Hash = obj.Hash
err = n.AddHostingNode(obj.Hash, n.ID)
if err != nil {
return nil, err
}
MyCurator.OnPostAdded(&data, true)
return obj, nil
}
// NewComment constructs a new comment and adds it to the IPFS
// network. Note that parent == post for comments replying to posts
func (n *Node) NewComment(user *User, postID, parent, content string) (*IPFSObj, error) {
if parent == "" || postID == "" {
// @TODO check if postID and parent are valid
return nil, errors.New("Parent and/or Post not defined")
}
if content == "" {
return nil, errors.New("Content cannot be empty")
}
data := Comment{
Post: postID,
Parent: parent,
Alias: user.Alias,
Content: content,
Timestamp: Now(),
}
obj, err := NewIPFSObj(MyNode, user, data)
if err != nil {
return nil, err
}
data.Hash = obj.Hash
isAccepted := MyCurator.OnCommentAdded(&data, true)
if !isAccepted {
return nil, errors.New("Curation rejected the content")
}
err = n.AssociateCommentWithPost(obj.Hash, postID)
if err != nil {
return nil, err
}
return obj, nil
}
func (n *Node) GetPost(postID string) (*Post, error) {
// @TODO maybe only need to get POST if we haven't retrieved it yet
obj, err := GetIPFSObj(postID)
if err != nil {
return nil, err
}
post := &Post{}
mapstructure.Decode(obj.Data, post)
post.Hash = obj.Hash
post.Key = obj.Key
userData := n.GetPostUserData(postID)
post.UserData = userData
return post, nil
}
func (n *Node) GetComment(commentID string) (*Comment, error) {
obj, err := GetIPFSObj(commentID)
if err != nil {
return nil, err
}
comment := &Comment{}
mapstructure.Decode(obj.Data, comment)
comment.Hash = obj.Hash
comment.Key = obj.Key
userData := n.GetCommentUserData(commentID)
comment.UserData = userData
return comment, nil
}
func (n *Node) GetComments(postID string) ([]Comment, error) {
commentHashes, err := n.GetPostComments(postID)
if err != nil {
return nil, err
}
// @TODO @PERFORMANCE can do this concurrently
var comments []Comment
for _, h := range commentHashes {
comment, err := n.GetComment(h)
if err != nil {
Warning.Println("Could not retrieve comment with id", h)
continue
}
comments = append(comments, *comment)
}
return comments, nil
}
func (n *Node) GetContentPosts() ([]Post, error) {
postHashes := MyCurator.GetContent(make(map[string]interface{}))
// @TODO @PERFORMANCE can do this concurrently
posts := []Post{}
for _, h := range postHashes {
post, err := n.GetPost(h)
if err != nil {
Warning.Println("Could not retrieve post with id", h)
continue
}
posts = append(posts, *post)
}
return posts, nil
}
func (n *Node) GetAllPosts() ([]Post, error) {
postHashes, err := n.GetPosts()
if err != nil {
return nil, err
}
// @TODO @PERFORMANCE can do this concurrently
var posts []Post
for _, h := range postHashes {
post, err := n.GetPost(h)
if err != nil {
Warning.Println("Could not retrieve post with id", h)
continue
}
posts = append(posts, *post)
}
return posts, nil
}