/
handler-api-ext.go
152 lines (126 loc) · 3.92 KB
/
handler-api-ext.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
package webserver
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
fp "path/filepath"
"strconv"
"github.com/go-shiori/shiori/internal/core"
"github.com/go-shiori/shiori/internal/model"
"github.com/julienschmidt/httprouter"
)
// ApiInsertViaExtension is handler for POST /api/bookmarks/ext
func (h *Handler) ApiInsertViaExtension(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
ctx := r.Context()
// Make sure session still valid
err := h.validateSession(r)
checkError(err)
// Decode request
request := model.BookmarkDTO{}
err = json.NewDecoder(r.Body).Decode(&request)
checkError(err)
// Clean up bookmark URL
request.URL, err = core.RemoveUTMParams(request.URL)
if err != nil {
panic(fmt.Errorf("failed to clean URL: %v", err))
}
// Check if bookmark already exists.
book, exist, err := h.DB.GetBookmark(ctx, 0, request.URL)
if err != nil {
panic(fmt.Errorf("failed to get bookmark, URL: %v", err))
}
// If it already exists, we need to set ID and tags.
if exist {
book.HTML = request.HTML
mapOldTags := map[string]model.Tag{}
for _, oldTag := range book.Tags {
mapOldTags[oldTag.Name] = oldTag
}
for _, newTag := range request.Tags {
if _, tagExist := mapOldTags[newTag.Name]; !tagExist {
book.Tags = append(book.Tags, newTag)
}
}
} else if request.Title == "" {
request.Title = request.URL
}
// Since we are using extension, the extension might send the HTML content
// so no need to download it again here. However, if it's empty, it might be not HTML file
// so we download it here.
var contentType string
var contentBuffer io.Reader
if request.HTML == "" {
contentBuffer, contentType, _ = core.DownloadBookmark(request.URL)
} else {
contentType = "text/html; charset=UTF-8"
contentBuffer = bytes.NewBufferString(request.HTML)
}
// Save the bookmark with whatever we already have downloaded
// since we need the ID in order to download the archive
// Only when old bookmark is not exists.
if !exist {
books, err := h.DB.SaveBookmarks(ctx, true, request)
if err != nil {
log.Printf("error saving bookmark before downloading content: %s", err)
return
}
book = books[0]
}
// At this point the web page already downloaded.
// Time to process it.
if contentBuffer != nil {
book.CreateArchive = true
request := core.ProcessRequest{
DataDir: h.DataDir,
Bookmark: book,
Content: contentBuffer,
ContentType: contentType,
}
var isFatalErr bool
book, isFatalErr, err = core.ProcessBookmark(h.dependencies, request)
if tmp, ok := contentBuffer.(io.ReadCloser); ok {
tmp.Close()
}
// If we can't process or update the saved bookmark, just log it and continue on with the
// request.
if err != nil && isFatalErr {
log.Printf("failed to process bookmark: %v", err)
} else if _, err := h.DB.SaveBookmarks(ctx, false, book); err != nil {
log.Printf("error saving bookmark after downloading content: %s", err)
}
}
// Return the new bookmark
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(&book)
checkError(err)
}
// ApiDeleteViaExtension is handler for DELETE /api/bookmark/ext
func (h *Handler) ApiDeleteViaExtension(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
ctx := r.Context()
// Make sure session still valid
err := h.validateSession(r)
checkError(err)
// Decode request
request := model.BookmarkDTO{}
err = json.NewDecoder(r.Body).Decode(&request)
checkError(err)
// Check if bookmark already exists.
book, exist, err := h.DB.GetBookmark(ctx, 0, request.URL)
checkError(err)
if exist {
// Delete bookmarks
err = h.DB.DeleteBookmarks(ctx, book.ID)
checkError(err)
// Delete thumbnail image and archives from local disk
strID := strconv.Itoa(book.ID)
imgPath := fp.Join(h.DataDir, "thumb", strID)
archivePath := fp.Join(h.DataDir, "archive", strID)
os.Remove(imgPath)
os.Remove(archivePath)
}
fmt.Fprint(w, 1)
}