add feedback
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
@@ -471,6 +473,42 @@ func (api *API) HandleAddFfmpegConfig(w http.ResponseWriter, r *http.Request) {
|
|||||||
api.HandleOK(w, r)
|
api.HandleOK(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FeedbackRequest struct {
|
||||||
|
Feedback string `json:"feedback"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleFeedback(w http.ResponseWriter, r *http.Request) {
|
||||||
|
feedbackRequest := &FeedbackRequest{}
|
||||||
|
err :=json.NewDecoder(r.Body).Decode(feedbackRequest)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check empty feedback
|
||||||
|
if feedbackRequest.Feedback == "" {
|
||||||
|
api.HandleErrorString(w, r, `"feedback" can't be empty`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("[api] Feedback", feedbackRequest.Feedback)
|
||||||
|
|
||||||
|
headerBuff := &bytes.Buffer{}
|
||||||
|
err = r.Header.Write(headerBuff)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
header := headerBuff.String()
|
||||||
|
|
||||||
|
err = api.Db.InsertFeedback(time.Now().Unix(), feedbackRequest.Feedback, header)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
api.HandleOK(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
func NewAPIConfig() (APIConfig) {
|
func NewAPIConfig() (APIConfig) {
|
||||||
apiConfig := APIConfig{
|
apiConfig := APIConfig{
|
||||||
FfmpegConfigs: make(map[string]*FfmpegConfig),
|
FfmpegConfigs: make(map[string]*FfmpegConfig),
|
||||||
@@ -515,6 +553,7 @@ func NewAPI(apiConfig APIConfig) (*API, error) {
|
|||||||
apiMux.HandleFunc("/get_random_files", api.HandleGetRandomFiles)
|
apiMux.HandleFunc("/get_random_files", api.HandleGetRandomFiles)
|
||||||
apiMux.HandleFunc("/get_file_stream", api.HandleGetFileStream)
|
apiMux.HandleFunc("/get_file_stream", api.HandleGetFileStream)
|
||||||
apiMux.HandleFunc("/get_ffmpeg_config_list", api.HandleGetFfmpegConfigs)
|
apiMux.HandleFunc("/get_ffmpeg_config_list", api.HandleGetFfmpegConfigs)
|
||||||
|
apiMux.HandleFunc("/feedback", api.HandleFeedback)
|
||||||
// below needs token
|
// below needs token
|
||||||
apiMux.HandleFunc("/walk", api.HandleWalk)
|
apiMux.HandleFunc("/walk", api.HandleWalk)
|
||||||
apiMux.HandleFunc("/reset", api.HandleReset)
|
apiMux.HandleFunc("/reset", api.HandleReset)
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ var initFoldersTableQuery = `CREATE TABLE IF NOT EXISTS folders (
|
|||||||
folder TEXT NOT NULL,
|
folder TEXT NOT NULL,
|
||||||
foldername TEXT NOT NULL
|
foldername TEXT NOT NULL
|
||||||
);`
|
);`
|
||||||
|
var initFeedbacksTableQuery = `CREATE TABLE IF NOT EXISTS feedbacks (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
time INTEGER NOT NULL,
|
||||||
|
feedback TEXT NOT NULL,
|
||||||
|
header TEXT NOT NULL
|
||||||
|
);`
|
||||||
var insertFolderQuery = `INSERT INTO folders (folder, foldername) VALUES (?, ?);`
|
var insertFolderQuery = `INSERT INTO folders (folder, foldername) VALUES (?, ?);`
|
||||||
var findFolderQuery = `SELECT id FROM folders WHERE folder = ? LIMIT 1;`
|
var findFolderQuery = `SELECT id FROM folders WHERE folder = ? LIMIT 1;`
|
||||||
var insertFileQuery = `INSERT INTO files (folder_id, filename, filesize) VALUES (?, ?, ?);`
|
var insertFileQuery = `INSERT INTO files (folder_id, filename, filesize) VALUES (?, ?, ?);`
|
||||||
@@ -32,6 +38,7 @@ var getFileQuery = `SELECT files.id, files.folder_id, files.filename, folders.fo
|
|||||||
var searchFoldersQuery = `SELECT id, folder, foldername FROM folders WHERE foldername LIKE ? LIMIT ? OFFSET ?;`
|
var searchFoldersQuery = `SELECT id, folder, foldername FROM folders WHERE foldername LIKE ? LIMIT ? OFFSET ?;`
|
||||||
var getFilesInFolderQuery = `SELECT id, filename, filesize FROM files WHERE folder_id = ? LIMIT ? OFFSET ?;`
|
var getFilesInFolderQuery = `SELECT id, filename, filesize FROM files WHERE folder_id = ? LIMIT ? OFFSET ?;`
|
||||||
var getRandomFilesQuery = `SELECT files.id, files.folder_id, files.filename, folders.foldername, files.filesize FROM files JOIN folders on files.folder_id = folders.id ORDER BY RANDOM() LIMIT ?;`
|
var getRandomFilesQuery = `SELECT files.id, files.folder_id, files.filename, folders.foldername, files.filesize FROM files JOIN folders on files.folder_id = folders.id ORDER BY RANDOM() LIMIT ?;`
|
||||||
|
var insertFeedbackQuery = `INSERT INTO feedbacks (time, feedback, header) VALUES (?, ?, ?);`
|
||||||
|
|
||||||
type Database struct {
|
type Database struct {
|
||||||
sqlConn *sql.DB
|
sqlConn *sql.DB
|
||||||
@@ -41,6 +48,7 @@ type Database struct {
|
|||||||
type Stmt struct {
|
type Stmt struct {
|
||||||
initFilesTable *sql.Stmt
|
initFilesTable *sql.Stmt
|
||||||
initFoldersTable *sql.Stmt
|
initFoldersTable *sql.Stmt
|
||||||
|
initFeedbacksTable *sql.Stmt
|
||||||
insertFolder *sql.Stmt
|
insertFolder *sql.Stmt
|
||||||
insertFile *sql.Stmt
|
insertFile *sql.Stmt
|
||||||
findFolder *sql.Stmt
|
findFolder *sql.Stmt
|
||||||
@@ -52,6 +60,7 @@ type Stmt struct {
|
|||||||
searchFolders *sql.Stmt
|
searchFolders *sql.Stmt
|
||||||
getFilesInFolder *sql.Stmt
|
getFilesInFolder *sql.Stmt
|
||||||
getRandomFiles *sql.Stmt
|
getRandomFiles *sql.Stmt
|
||||||
|
insertFeedback *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
@@ -70,6 +79,14 @@ type Folder struct {
|
|||||||
Foldername string `json:"foldername"`
|
Foldername string `json:"foldername"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (database *Database) InsertFeedback(time int64, feedback string, header string) (error) {
|
||||||
|
_, err := database.stmt.insertFeedback.Exec(time, feedback, header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (database *Database) GetRandomFiles(limit int64) ([]File, error) {
|
func (database *Database) GetRandomFiles(limit int64) ([]File, error) {
|
||||||
rows, err := database.stmt.getRandomFiles.Query(limit)
|
rows, err := database.stmt.getRandomFiles.Query(limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -304,6 +321,12 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init feedbacks tables
|
||||||
|
stmt.initFeedbacksTable, err = sqlConn.Prepare(initFeedbacksTableQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// run init statement
|
// run init statement
|
||||||
_, err = stmt.initFilesTable.Exec()
|
_, err = stmt.initFilesTable.Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -313,6 +336,10 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initFeedbacksTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init insert folder statement
|
// init insert folder statement
|
||||||
stmt.insertFolder, err = sqlConn.Prepare(insertFolderQuery)
|
stmt.insertFolder, err = sqlConn.Prepare(insertFolderQuery)
|
||||||
@@ -380,6 +407,12 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init insertFeedback
|
||||||
|
stmt.insertFeedback, err = sqlConn.Prepare(insertFeedbackQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return stmt, err
|
return stmt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
web/index.js
27
web/index.js
@@ -149,6 +149,12 @@ const component_manage= {
|
|||||||
emits: ['set_token'],
|
emits: ['set_token'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
feedback: "",
|
||||||
|
feedback_status: "Submit",
|
||||||
|
feedback_placeholder: "feedback...",
|
||||||
|
submit_disabled: false,
|
||||||
|
is_err: false,
|
||||||
|
err_msg: "",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
@@ -156,10 +162,31 @@ const component_manage= {
|
|||||||
<h4>关于本站</h4>
|
<h4>关于本站</h4>
|
||||||
<p>本站是 MSW Project 的一个应用,希望以个人之力分享被隐藏在历史中的音乐。</p>
|
<p>本站是 MSW Project 的一个应用,希望以个人之力分享被隐藏在历史中的音乐。</p>
|
||||||
<p>自己是V家厨,喜欢的p主包括 wonder-k, buzzG, *luna 等,但却因为种种原因淹没在主流音乐APP的曲库中。本站的初衷是为了让那些知名度低的 VOCALOID / ACG / 东方曲,能够被更多有缘人听到,同时有一个跨平台的工具,能够在低网速的条件下享受硬盘中的无损音乐。</p>
|
<p>自己是V家厨,喜欢的p主包括 wonder-k, buzzG, *luna 等,但却因为种种原因淹没在主流音乐APP的曲库中。本站的初衷是为了让那些知名度低的 VOCALOID / ACG / 东方曲,能够被更多有缘人听到,同时有一个跨平台的工具,能够在低网速的条件下享受硬盘中的无损音乐。</p>
|
||||||
|
<p>站内音乐来自公开网络,仅供个人使用,如有侵权请联系提交反馈</p>
|
||||||
|
<input type="text" v-model="feedback" :disabled="submit_disabled" :placeholder="feedback_placeholder"/>
|
||||||
|
<button @click="submit_feedback" :disabled="submit_disabled">{{ feedback_status }}</button>
|
||||||
|
<label v-if="is_err">{{ err_msg }}</label>
|
||||||
<component-token :token="token" @set_token="$emit('set_token', $event)"></component-token>
|
<component-token :token="token" @set_token="$emit('set_token', $event)"></component-token>
|
||||||
<component-manage-database :token="token"></component-manage-database>
|
<component-manage-database :token="token"></component-manage-database>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
|
methods: {
|
||||||
|
submit_feedback() {
|
||||||
|
axios.post('/api/v1/feedback', {
|
||||||
|
feedback: this.feedback,
|
||||||
|
}).then((response) => {
|
||||||
|
this.submit_disabled = true
|
||||||
|
this.feedback = ""
|
||||||
|
this.feedback_status = "Success"
|
||||||
|
this.feedback_placeholder = "Thanks for your feedback!"
|
||||||
|
this.is_err = false
|
||||||
|
}).catch((err) => {
|
||||||
|
console.log(err)
|
||||||
|
this.is_err = true
|
||||||
|
this.err_msg = err.response.data.status
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const component_manage_database = {
|
const component_manage_database = {
|
||||||
props: ['token'],
|
props: ['token'],
|
||||||
|
|||||||
Reference in New Issue
Block a user