-
Notifications
You must be signed in to change notification settings - Fork 0
/
post_service.go
173 lines (142 loc) · 3.96 KB
/
post_service.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
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"path/filepath"
"github.com/spf13/afero"
"github.com/srvc/fail/v4"
"github.com/taxio/esa/log"
)
var ErrPostCacheAlreadyExists = errors.New("post cache already exists")
type postCachePath struct {
BaseDir string
Meta string
Body string
}
func newPostCachePath(cacheBaseDir string, postId int) *postCachePath {
baseDir := filepath.Join(cacheBaseDir, "posts", fmt.Sprintf("%d", postId))
return &postCachePath{
BaseDir: baseDir,
Meta: filepath.Join(baseDir, "meta.json"),
Body: filepath.Join(baseDir, "body.md"),
}
}
func NewPostService(fs afero.Fs, client *Client, cacheBaseDir string, editor Editor) *PostService {
return &PostService{
af: &afero.Afero{Fs: fs},
client: client,
cacheBaseDir: cacheBaseDir,
editor: editor,
}
}
type PostService struct {
af *afero.Afero
client *Client
cacheBaseDir string
editor Editor
}
func (s *PostService) EditPost(ctx context.Context, postId int) error {
// Get Post Detail
post, err := s.client.GetPost(ctx, postId)
if err != nil {
return fail.Wrap(err)
}
log.Printf("%#v\n", post)
// Write post data to cache file
cachePath, err := s.savePostTemporary(ctx, post)
if err != nil {
return fail.Wrap(err)
}
// open cache file by editor
if err := s.editor.Exec(ctx, cachePath.Body); err != nil {
return fail.Wrap(err)
}
// save post to esa.io
if err := s.updatePost(ctx, cachePath); err != nil {
return fail.Wrap(err)
}
// remove cache file
if err := s.af.RemoveAll(cachePath.BaseDir); err != nil {
return fail.Wrap(err)
}
return nil
}
func (s *PostService) EditPostFromCache(ctx context.Context, postId int) error {
cachePath := s.postCachePath(postId)
// open cache file by editor
if err := s.editor.Exec(ctx, cachePath.Body); err != nil {
return fail.Wrap(err)
}
// save post to esa.io
if err := s.updatePost(ctx, cachePath); err != nil {
return fail.Wrap(err)
}
// remove cache file
if err := s.af.RemoveAll(cachePath.BaseDir); err != nil {
return fail.Wrap(err)
}
return nil
}
func (s *PostService) DeletePostCache(ctx context.Context, postId int) error {
cachePath := s.postCachePath(postId)
if err := s.af.RemoveAll(cachePath.BaseDir); err != nil {
return fail.Wrap(err)
}
return nil
}
func (s *PostService) CacheDirPath(ctx context.Context, postId int) string {
cachePath := s.postCachePath(postId)
return cachePath.BaseDir
}
func (s *PostService) savePostTemporary(ctx context.Context, post *Post) (*postCachePath, error) {
cachePath := newPostCachePath(s.cacheBaseDir, post.Number)
// Check for the existence of a cache directory.
ok, err := s.af.DirExists(cachePath.BaseDir)
if err != nil {
return nil, fail.Wrap(err)
}
if ok {
return nil, fail.Wrap(ErrPostCacheAlreadyExists, fail.WithMessage(cachePath.BaseDir))
}
// Create a cache directory.
if err := s.af.MkdirAll(cachePath.BaseDir, 0755); err != nil {
return nil, fail.Wrap(err)
}
// Save meta of post
jsonBytes, err := json.Marshal(post)
if err != nil {
return nil, fail.Wrap(err)
}
if err := s.af.WriteFile(cachePath.Meta, jsonBytes, 0644); err != nil {
return nil, fail.Wrap(err)
}
// Save body markdown data
if err := s.af.WriteFile(cachePath.Body, []byte(post.OriginalRevision.BodyMd), 0644); err != nil {
return nil, fail.Wrap(err)
}
return cachePath, nil
}
func (s *PostService) updatePost(ctx context.Context, cachePath *postCachePath) error {
var post Post
metaBytes, err := s.af.ReadFile(cachePath.Meta)
if err != nil {
return fail.Wrap(err)
}
if err := json.Unmarshal(metaBytes, &post); err != nil {
return fail.Wrap(err)
}
bodyBytes, err := s.af.ReadFile(cachePath.Body)
if err != nil {
return fail.Wrap(err)
}
post.BodyMd = string(bodyBytes)
if err := s.client.UpdatePost(ctx, &post); err != nil {
return fail.Wrap(err)
}
return nil
}
func (s *PostService) postCachePath(postId int) *postCachePath {
return newPostCachePath(s.cacheBaseDir, postId)
}