Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
3e31f8822e
|
|||
|
6cff4247a8
|
|||
|
90ff1382a8
|
|||
|
1450357b91
|
|||
|
7a31c36c10
|
|||
|
5271c12525
|
|||
|
d278e4009d
|
|||
|
e3d80ffc2a
|
|||
|
30a8fbad4e
|
|||
|
e7bc625b6d
|
|||
|
2d71e7b0cb
|
|||
|
2297f87fa3
|
|||
|
271c7e5c13
|
|||
|
9fdea6b169
|
|||
|
38e20044e2
|
|||
|
830cbae17a
|
|||
|
51fee5bfe0
|
|||
|
e40fd2625f
|
|||
|
061ef9bdc9
|
|||
|
d478923ce0
|
|||
|
e4032069a5
|
|||
|
73da4f8dc5
|
|||
|
89ff2bf452
|
|||
|
d0f6d19a7e
|
|||
|
977b3e02e9
|
|||
|
a6d82c1f47
|
18
.drone.yml
Normal file
18
.drone.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: default
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: frontend-web
|
||||||
|
image: node:19
|
||||||
|
commands:
|
||||||
|
- cd web
|
||||||
|
- npm install
|
||||||
|
- npm run build
|
||||||
|
|
||||||
|
- name: release
|
||||||
|
image: plugins/gitea-release
|
||||||
|
settings:
|
||||||
|
api_key: da966507c259aa32ccc2d434e930af4a580de785
|
||||||
|
base_url: https://yongyuancv.cn/git/
|
||||||
|
files: build/*
|
||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -57,7 +57,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 18
|
node-version: 16
|
||||||
- name: Build web front end
|
- name: Build web front end
|
||||||
run: |
|
run: |
|
||||||
make web
|
make web
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"api": {
|
"api": {
|
||||||
"secret": "CHANGE_YOUR_SECRET_HERE",
|
"secret": "CHANGE_YOUR_SECRET_HERE",
|
||||||
"database_name": "music.sqlite3",
|
"database_name": "postgres://postgres:woshimima@localhost/postgres?sslmode=disable",
|
||||||
"single_thread": true,
|
"single_thread": true,
|
||||||
"addr": ":8080",
|
"addr": ":8080",
|
||||||
"ffmpeg_threads": 1,
|
"ffmpeg_threads": 1,
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -4,7 +4,7 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gorilla/sessions v1.2.1
|
github.com/gorilla/sessions v1.2.1
|
||||||
github.com/mattn/go-sqlite3 v1.14.14
|
github.com/lib/pq v1.10.7
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -2,7 +2,7 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC
|
|||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||||
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
|
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
|
||||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw=
|
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||||
github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ func NewAPI(config commonconfig.Config) (*API, error) {
|
|||||||
apiMux.HandleFunc("/get_file_info", api.HandleGetFileInfo)
|
apiMux.HandleFunc("/get_file_info", api.HandleGetFileInfo)
|
||||||
apiMux.HandleFunc("/get_file_ffprobe_info", api.HandleGetFileFfprobeInfo)
|
apiMux.HandleFunc("/get_file_ffprobe_info", api.HandleGetFileFfprobeInfo)
|
||||||
apiMux.HandleFunc("/get_file_stream_direct", api.HandleGetFileStreamDirect)
|
apiMux.HandleFunc("/get_file_stream_direct", api.HandleGetFileStreamDirect)
|
||||||
|
apiMux.HandleFunc("/get_file_avatar", api.HandelGetFileAvatar)
|
||||||
apiMux.HandleFunc("/prepare_file_stream_direct", api.HandlePrepareFileStreamDirect)
|
apiMux.HandleFunc("/prepare_file_stream_direct", api.HandlePrepareFileStreamDirect)
|
||||||
apiMux.HandleFunc("/delete_file", api.HandleDeleteFile)
|
apiMux.HandleFunc("/delete_file", api.HandleDeleteFile)
|
||||||
apiMux.HandleFunc("/update_filename", api.HandleUpdateFilename)
|
apiMux.HandleFunc("/update_filename", api.HandleUpdateFilename)
|
||||||
|
|||||||
108
pkg/api/handle_avatar.go
Normal file
108
pkg/api/handle_avatar.go
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"msw-open-music/pkg/database"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (api *API) HandelGetFileAvatar(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var err error
|
||||||
|
q := r.URL.Query()
|
||||||
|
ids := q["id"]
|
||||||
|
if len(ids) == 0 {
|
||||||
|
err = errors.New(`parameter "id" can't be empty`)
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id, err := strconv.Atoi(ids[0])
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file, err := api.Db.GetFile(int64(id))
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
path, err := file.Path()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("[api] Get avatar of file", path)
|
||||||
|
buff := make([]byte, 0)
|
||||||
|
cache := bytes.NewBuffer(buff)
|
||||||
|
cmd := exec.Command("ffmpeg", "-i", path, "-c:v", "libwebp_anim", "-update", "1", "-frames:v", "1", "-f", "image2pipe", "-")
|
||||||
|
cmd.Stdout = cache
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleGetAlternativeFileAvatar(w, r, file)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "image/webp")
|
||||||
|
io.Copy(w, cache)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *API) HandleGetAlternativeFileAvatar(w http.ResponseWriter, r *http.Request, f *database.File) {
|
||||||
|
var err error
|
||||||
|
dir, err := f.Dir()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("[api] Get alternative avatar in dir", dir)
|
||||||
|
files, err := os.ReadDir(dir)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
avatar, err := findAvatarFile(files)
|
||||||
|
avatarPath := path.Join(dir, avatar)
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd := exec.Command("ffmpeg", "-i", avatarPath, "-c:v", "libwebp_anim", "-f", "image2pipe", "-")
|
||||||
|
cmd.Stdout = w
|
||||||
|
w.Header().Set("Content-Type", "image/webp")
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
api.HandleError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findAvatarFile(files []os.DirEntry) (string, error) {
|
||||||
|
for _, file := range files {
|
||||||
|
if isAvatarType(file.Name()) {
|
||||||
|
return file.Name(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", errors.New("Cannot find avatar file")
|
||||||
|
}
|
||||||
|
|
||||||
|
var avatarFileTypes = []string{
|
||||||
|
".jpg",
|
||||||
|
".png",
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAvatarType(filename string) bool {
|
||||||
|
for _, t := range avatarFileTypes {
|
||||||
|
if strings.HasSuffix(strings.ToLower(filename), t) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"log"
|
||||||
"msw-open-music/pkg/database"
|
"msw-open-music/pkg/database"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
@@ -35,6 +36,12 @@ func (api *API) HandleRecordPlayback(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println("[api] Record playback history",
|
||||||
|
recordPlaybackRequest.Playback.UserID,
|
||||||
|
recordPlaybackRequest.Playback.FileID,
|
||||||
|
recordPlaybackRequest.Playback.Duration,
|
||||||
|
recordPlaybackRequest.Playback.Method)
|
||||||
|
|
||||||
err = api.Db.RecordPlayback(recordPlaybackRequest.Playback)
|
err = api.Db.RecordPlayback(recordPlaybackRequest.Playback)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
api.HandleError(w, r, err)
|
api.HandleError(w, r, err)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Database struct {
|
type Database struct {
|
||||||
@@ -41,7 +41,7 @@ func NewDatabase(dbName string, singleThread bool) (*Database, error) {
|
|||||||
var err error
|
var err error
|
||||||
|
|
||||||
// open database
|
// open database
|
||||||
sqlConn, err := sql.Open("sqlite3", dbName)
|
sqlConn, err := sql.Open("postgres", dbName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ func (database *Database) Walk(root string, pattern []string, tagIDs []int64, us
|
|||||||
insertFileStmt := tx.Stmt(database.stmt.insertFile)
|
insertFileStmt := tx.Stmt(database.stmt.insertFile)
|
||||||
putTagOnFileStmt := tx.Stmt(database.stmt.putTagOnFile)
|
putTagOnFileStmt := tx.Stmt(database.stmt.putTagOnFile)
|
||||||
findFolderStmt := tx.Stmt(database.stmt.findFolder)
|
findFolderStmt := tx.Stmt(database.stmt.findFolder)
|
||||||
|
findFileStmt := tx.Stmt(database.stmt.findFile)
|
||||||
|
|
||||||
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -194,23 +195,42 @@ func (database *Database) Walk(root string, pattern []string, tagIDs []int64, us
|
|||||||
folder, filename := filepath.Split(path)
|
folder, filename := filepath.Split(path)
|
||||||
err = findFolderStmt.QueryRow(folder).Scan(&folderID)
|
err = findFolderStmt.QueryRow(folder).Scan(&folderID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result, err := insertFolderStmt.Exec(folder, filepath.Base(folder))
|
result, err := insertFolderStmt.Query(folder, filepath.Base(folder))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
folderID, err = result.LastInsertId()
|
for result.Next() {
|
||||||
|
err = result.Scan(&folderID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result, err := insertFileStmt.Exec(folderID, filename, filename, info.Size())
|
}
|
||||||
|
|
||||||
|
// try find file id
|
||||||
|
var fileID int64
|
||||||
|
result, err := findFileStmt.Query(folderID, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fileID, err := result.LastInsertId()
|
for result.Next() {
|
||||||
|
err = result.Scan(&fileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert new file
|
||||||
|
result, err = insertFileStmt.Query(folderID, filename, filename, info.Size())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for result.Next() {
|
||||||
|
err = result.Scan(&fileID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
_, err := putTagOnFileStmt.Exec(tag.ID, fileID, userID)
|
_, err := putTagOnFileStmt.Exec(tag.ID, fileID, userID)
|
||||||
|
|||||||
@@ -6,11 +6,17 @@ func (database *Database) InsertTag(tag *Tag) (int64, error) {
|
|||||||
database.singleThreadLock.Lock()
|
database.singleThreadLock.Lock()
|
||||||
defer database.singleThreadLock.Unlock()
|
defer database.singleThreadLock.Unlock()
|
||||||
|
|
||||||
result, err := database.stmt.insertTag.Exec(tag.Name, tag.Description, tag.CreatedByUserId)
|
result, err := database.stmt.insertTag.Query(tag.Name, tag.Description, tag.CreatedByUserId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
id, err := result.LastInsertId()
|
var id int64
|
||||||
|
for result.Next() {
|
||||||
|
err = result.Scan(&id)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,22 +6,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var initFilesTableQuery = `CREATE TABLE IF NOT EXISTS files (
|
var initFilesTableQuery = `CREATE TABLE IF NOT EXISTS files (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
folder_id INTEGER NOT NULL,
|
folder_id INTEGER NOT NULL REFERENCES folders(id),
|
||||||
realname TEXT NOT NULL,
|
realname TEXT NOT NULL,
|
||||||
filename TEXT NOT NULL,
|
filename TEXT NOT NULL,
|
||||||
filesize INTEGER NOT NULL,
|
filesize INTEGER NOT NULL,
|
||||||
FOREIGN KEY(folder_id) REFERENCES folders(id)
|
UNIQUE (folder_id, realname)
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initFoldersTableQuery = `CREATE TABLE IF NOT EXISTS folders (
|
var initFoldersTableQuery = `CREATE TABLE IF NOT EXISTS folders (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
folder TEXT NOT NULL,
|
folder TEXT NOT NULL UNIQUE,
|
||||||
foldername TEXT NOT NULL
|
foldername TEXT NOT NULL
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initFeedbacksTableQuery = `CREATE TABLE IF NOT EXISTS feedbacks (
|
var initFeedbacksTableQuery = `CREATE TABLE IF NOT EXISTS feedbacks (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
time INTEGER NOT NULL,
|
time INTEGER NOT NULL,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
@@ -30,108 +30,101 @@ var initFeedbacksTableQuery = `CREATE TABLE IF NOT EXISTS feedbacks (
|
|||||||
|
|
||||||
// User table schema definition
|
// User table schema definition
|
||||||
// role: 0 - Anonymous User, 1 - Admin, 2 - User
|
// role: 0 - Anonymous User, 1 - Admin, 2 - User
|
||||||
|
// postgres avatar references problem
|
||||||
var initUsersTableQuery = `CREATE TABLE IF NOT EXISTS users (
|
var initUsersTableQuery = `CREATE TABLE IF NOT EXISTS users (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id SERIAL PRIMARY KEY,
|
||||||
username TEXT NOT NULL UNIQUE,
|
username TEXT NOT NULL UNIQUE,
|
||||||
password TEXT NOT NULL,
|
password TEXT NOT NULL,
|
||||||
role INTEGER NOT NULL,
|
role INTEGER NOT NULL,
|
||||||
active BOOLEAN NOT NULL,
|
active BOOLEAN NOT NULL,
|
||||||
avatar_id INTEGER NOT NULL,
|
avatar_id INTEGER NOT NULL DEFAULT 0
|
||||||
FOREIGN KEY(avatar_id) REFERENCES avatars(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initAvatarsTableQuery = `CREATE TABLE IF NOT EXISTS avatars (
|
var initAvatarsTableQuery = `CREATE TABLE IF NOT EXISTS avatars (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
avatarname TEXT NOT NULL,
|
avatarname TEXT NOT NULL,
|
||||||
avatar BLOB NOT NULL
|
avatar BYTEA NOT NULL
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initTagsTableQuery = `CREATE TABLE IF NOT EXISTS tags (
|
var initTagsTableQuery = `CREATE TABLE IF NOT EXISTS tags (
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id SERIAL PRIMARY KEY,
|
||||||
name TEXT NOT NULL UNIQUE,
|
name TEXT NOT NULL UNIQUE,
|
||||||
description TEXT NOT NULL,
|
description TEXT NOT NULL,
|
||||||
created_by_user_id INTEGER NOT NULL,
|
created_by_user_id INTEGER NOT NULL REFERENCES users(id)
|
||||||
FOREIGN KEY(created_by_user_id) REFERENCES users(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initFileHasTagTableQuery = `CREATE TABLE IF NOT EXISTS file_has_tag (
|
var initFileHasTagTableQuery = `CREATE TABLE IF NOT EXISTS file_has_tag (
|
||||||
file_id INTEGER NOT NULL,
|
file_id INTEGER NOT NULL REFERENCES files(id),
|
||||||
tag_id INTEGER NOT NULL,
|
tag_id INTEGER NOT NULL REFERENCES tags(id),
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
PRIMARY KEY (file_id, tag_id),
|
PRIMARY KEY (file_id, tag_id)
|
||||||
FOREIGN KEY(user_id) REFERENCES users(id)
|
|
||||||
FOREIGN KEY (file_id) REFERENCES files(id),
|
|
||||||
FOREIGN KEY (tag_id) REFERENCES tags(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initLikesTableQuery = `CREATE TABLE IF NOT EXISTS likes (
|
var initLikesTableQuery = `CREATE TABLE IF NOT EXISTS likes (
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
file_id INTEGER NOT NULL,
|
file_id INTEGER NOT NULL REFERENCES files(id),
|
||||||
PRIMARY KEY (user_id, file_id),
|
PRIMARY KEY (user_id, file_id)
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
||||||
FOREIGN KEY (file_id) REFERENCES files(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initReviewsTableQuery = `CREATE TABLE IF NOT EXISTS reviews (
|
var initReviewsTableQuery = `CREATE TABLE IF NOT EXISTS reviews (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
file_id INTEGER NOT NULL,
|
file_id INTEGER NOT NULL REFERENCES files(id),
|
||||||
created_at INTEGER NOT NULL,
|
created_at INTEGER NOT NULL,
|
||||||
updated_at INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
content TEXT NOT NULL,
|
content TEXT NOT NULL
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
||||||
FOREIGN KEY (file_id) REFERENCES files(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initPlaybacksTableQuery = `CREATE TABLE IF NOT EXISTS playbacks (
|
var initPlaybacksTableQuery = `CREATE TABLE IF NOT EXISTS playbacks (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
file_id INTEGER NOT NULL,
|
file_id INTEGER NOT NULL REFERENCES files(id),
|
||||||
time INTEGER NOT NULL,
|
time TIMESTAMP NOT NULL,
|
||||||
method INTEGER NOT NULL,
|
method INTEGER NOT NULL,
|
||||||
duration INTEGER NOT NULL,
|
duration INTERVAL NOT NULL
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
|
||||||
FOREIGN KEY (file_id) REFERENCES files(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initLogsTableQuery = `CREATE TABLE IF NOT EXISTS logs (
|
var initLogsTableQuery = `CREATE TABLE IF NOT EXISTS logs (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
time INTEGER NOT NULL,
|
time INTEGER NOT NULL,
|
||||||
message TEXT NOT NULL,
|
message TEXT NOT NULL,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL REFERENCES users(id)
|
||||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var initTmpfsTableQuery = `CREATE TABLE IF NOT EXISTS tmpfs (
|
var initTmpfsTableQuery = `CREATE TABLE IF NOT EXISTS tmpfs (
|
||||||
id INTEGER PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
path TEXT NOT NULL,
|
path TEXT NOT NULL,
|
||||||
size INTEGER NOT NULL,
|
size INTEGER NOT NULL,
|
||||||
file_id INTEGER NOT NULL,
|
file_id INTEGER NOT NULL REFERENCES files(id),
|
||||||
ffmpeg_config TEXT NOT NULL,
|
ffmpeg_config TEXT NOT NULL,
|
||||||
created_time INTEGER NOT NULL,
|
created_time INTEGER NOT NULL,
|
||||||
accessed_time INTEGER NOT NULL,
|
accessed_time INTEGER NOT NULL
|
||||||
FOREIGN KEY (file_id) REFERENCES files(id)
|
|
||||||
);`
|
);`
|
||||||
|
|
||||||
var insertFolderQuery = `INSERT INTO folders (folder, foldername)
|
var insertFolderQuery = `INSERT INTO folders (folder, foldername)
|
||||||
VALUES (?, ?);`
|
VALUES ($1, $2)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
RETURNING id;
|
||||||
|
;`
|
||||||
|
|
||||||
var findFolderQuery = `SELECT id FROM folders WHERE folder = ? LIMIT 1;`
|
var findFolderQuery = `SELECT id FROM folders WHERE folder = $1 LIMIT 1;`
|
||||||
|
|
||||||
var findFileQuery = `SELECT id FROM files WHERE folder_id = ? AND realname = ? LIMIT 1;`
|
var findFileQuery = `SELECT id FROM files WHERE folder_id = $1 AND realname = $2 LIMIT 1;`
|
||||||
|
|
||||||
var insertFileQuery = `INSERT INTO files (folder_id, realname, filename, filesize)
|
var insertFileQuery = `INSERT INTO files (folder_id, realname, filename, filesize)
|
||||||
VALUES (?, ?, ?, ?);`
|
VALUES ($1, $2, $3, $4)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
RETURNING id;`
|
||||||
|
|
||||||
var searchFilesQuery = `SELECT
|
var searchFilesQuery = `SELECT
|
||||||
files.id, files.folder_id, files.filename, folders.foldername, files.filesize
|
files.id, files.folder_id, files.filename, folders.foldername, files.filesize
|
||||||
FROM files
|
FROM files
|
||||||
JOIN folders ON files.folder_id = folders.id
|
JOIN folders ON files.folder_id = folders.id
|
||||||
WHERE filename LIKE ?
|
WHERE filename ILIKE $1
|
||||||
ORDER BY folders.foldername, files.filename
|
ORDER BY folders.foldername, files.filename
|
||||||
LIMIT ? OFFSET ?;`
|
LIMIT $2 OFFSET $3;`
|
||||||
|
|
||||||
var getFolderQuery = `SELECT folder FROM folders WHERE id = ? LIMIT 1;`
|
var getFolderQuery = `SELECT folder FROM folders WHERE id = $1 LIMIT 1;`
|
||||||
|
|
||||||
var dropFilesQuery = `DROP TABLE files;`
|
var dropFilesQuery = `DROP TABLE files;`
|
||||||
|
|
||||||
@@ -141,42 +134,42 @@ var getFileQuery = `SELECT
|
|||||||
files.id, files.folder_id, files.realname, files.filename, folders.foldername, files.filesize
|
files.id, files.folder_id, files.realname, files.filename, folders.foldername, files.filesize
|
||||||
FROM files
|
FROM files
|
||||||
JOIN folders ON files.folder_id = folders.id
|
JOIN folders ON files.folder_id = folders.id
|
||||||
WHERE files.id = ?
|
WHERE files.id = $1
|
||||||
LIMIT 1;`
|
LIMIT 1;`
|
||||||
|
|
||||||
var searchFoldersQuery = `SELECT
|
var searchFoldersQuery = `SELECT
|
||||||
id, folder, foldername
|
id, folder, foldername
|
||||||
FROM folders
|
FROM folders
|
||||||
WHERE foldername LIKE ?
|
WHERE foldername ILIKE $1
|
||||||
ORDER BY foldername
|
ORDER BY foldername
|
||||||
LIMIT ? OFFSET ?;`
|
LIMIT $2 OFFSET $3;`
|
||||||
|
|
||||||
var getFilesInFolderQuery = `SELECT
|
var getFilesInFolderQuery = `SELECT
|
||||||
files.id, files.filename, files.filesize, folders.foldername, folders.folder
|
files.id, files.filename, files.filesize, folders.foldername, folders.folder
|
||||||
FROM files
|
FROM files
|
||||||
JOIN folders ON files.folder_id = folders.id
|
JOIN folders ON files.folder_id = folders.id
|
||||||
WHERE folder_id = ?
|
WHERE folder_id = $1
|
||||||
ORDER BY files.filename
|
ORDER BY files.filename
|
||||||
LIMIT ? OFFSET ?;`
|
LIMIT $2 OFFSET $3;`
|
||||||
|
|
||||||
var getRandomFilesQuery = `SELECT
|
var getRandomFilesQuery = `SELECT
|
||||||
files.id, files.folder_id, files.filename, folders.foldername, files.filesize
|
files.id, files.folder_id, files.filename, folders.foldername, files.filesize
|
||||||
FROM files
|
FROM files
|
||||||
JOIN folders ON files.folder_id = folders.id
|
JOIN folders ON files.folder_id = folders.id
|
||||||
ORDER BY RANDOM()
|
ORDER BY RANDOM()
|
||||||
LIMIT ?;`
|
LIMIT $1;`
|
||||||
|
|
||||||
var getRandomFilesWithTagQuery = `SELECT
|
var getRandomFilesWithTagQuery = `SELECT
|
||||||
files.id, files.folder_id, files.filename, folders.foldername, files.filesize
|
files.id, files.folder_id, files.filename, folders.foldername, files.filesize
|
||||||
FROM file_has_tag
|
FROM file_has_tag
|
||||||
JOIN files ON file_has_tag.file_id = files.id
|
JOIN files ON file_has_tag.file_id = files.id
|
||||||
JOIN folders ON files.folder_id = folders.id
|
JOIN folders ON files.folder_id = folders.id
|
||||||
WHERE file_has_tag.tag_id = ?
|
WHERE file_has_tag.tag_id = $1
|
||||||
ORDER BY RANDOM()
|
ORDER BY RANDOM()
|
||||||
LIMIT ?;`
|
LIMIT $2;`
|
||||||
|
|
||||||
var insertFeedbackQuery = `INSERT INTO feedbacks (time, content, user_id, header)
|
var insertFeedbackQuery = `INSERT INTO feedbacks (time, content, user_id, header)
|
||||||
VALUES (?, ?, ?, ?);`
|
VALUES ($1, $2, $3, $4);`
|
||||||
|
|
||||||
var getFeedbacksQuery = `SELECT
|
var getFeedbacksQuery = `SELECT
|
||||||
feedbacks.id, feedbacks.time, feedbacks.content, feedbacks.header,
|
feedbacks.id, feedbacks.time, feedbacks.content, feedbacks.header,
|
||||||
@@ -186,39 +179,39 @@ JOIN users ON feedbacks.user_id = users.id
|
|||||||
ORDER BY feedbacks.time
|
ORDER BY feedbacks.time
|
||||||
;`
|
;`
|
||||||
|
|
||||||
var deleteFeedbackQuery = `DELETE FROM feedbacks WHERE id = ?;`
|
var deleteFeedbackQuery = `DELETE FROM feedbacks WHERE id = $1;`
|
||||||
|
|
||||||
var insertUserQuery = `INSERT INTO users (username, password, role, active, avatar_id)
|
var insertUserQuery = `INSERT INTO users (username, password, role, active, avatar_id)
|
||||||
VALUES (?, ?, ?, ?, ?);`
|
VALUES ($1, $2, $3, $4, $5);`
|
||||||
|
|
||||||
var countUserQuery = `SELECT count(*) FROM users;`
|
var countUserQuery = `SELECT count(*) FROM users;`
|
||||||
|
|
||||||
var countAdminQuery = `SELECT count(*) FROM users WHERE role= 1;`
|
var countAdminQuery = `SELECT count(*) FROM users WHERE role= 1;`
|
||||||
|
|
||||||
var getUserQuery = `SELECT id, username, password, role, active, avatar_id FROM users WHERE username = ? LIMIT 1;`
|
var getUserQuery = `SELECT id, username, password, role, active, avatar_id FROM users WHERE username = $1 LIMIT 1;`
|
||||||
|
|
||||||
var getUsersQuery = `SELECT id, username, role, active, avatar_id FROM users;`
|
var getUsersQuery = `SELECT id, username, role, active, avatar_id FROM users;`
|
||||||
|
|
||||||
var getUserByIdQuery = `SELECT id, username, role, active, avatar_id FROM users WHERE id = ? LIMIT 1;`
|
var getUserByIdQuery = `SELECT id, username, role, active, avatar_id FROM users WHERE id = $1 LIMIT 1;`
|
||||||
|
|
||||||
var updateUserActiveQuery = `UPDATE users SET active = ? WHERE id = ?;`
|
var updateUserActiveQuery = `UPDATE users SET active = $1 WHERE id = $2;`
|
||||||
|
|
||||||
var updateUsernameQuery = `UPDATE users SET username = ? WHERE id = ?;`
|
var updateUsernameQuery = `UPDATE users SET username = $1 WHERE id = $2;`
|
||||||
|
|
||||||
var updateUserPasswordQuery = `UPDATE users SET password = ? WHERE id = ?;`
|
var updateUserPasswordQuery = `UPDATE users SET password = $1 WHERE id = $2;`
|
||||||
|
|
||||||
var getAnonymousUserQuery = `SELECT id, username, role, avatar_id FROM users WHERE role = 0 LIMIT 1;`
|
var getAnonymousUserQuery = `SELECT id, username, role, avatar_id FROM users WHERE role = 0 LIMIT 1;`
|
||||||
|
|
||||||
var insertTagQuery = `INSERT INTO tags (name, description, created_by_user_id) VALUES (?, ?, ?);`
|
var insertTagQuery = `INSERT INTO tags (name, description, created_by_user_id) VALUES ($1, $2, $3) RETURNING id;`
|
||||||
|
|
||||||
var deleteTagQuery = `DELETE FROM tags WHERE id = ?;`
|
var deleteTagQuery = `DELETE FROM tags WHERE id = $1;`
|
||||||
|
|
||||||
var getTagQuery = `SELECT
|
var getTagQuery = `SELECT
|
||||||
tags.id, tags.name, tags.description,
|
tags.id, tags.name, tags.description,
|
||||||
users.id, users.username, users.role, users.avatar_id
|
users.id, users.username, users.role, users.avatar_id
|
||||||
FROM tags
|
FROM tags
|
||||||
JOIN users ON tags.created_by_user_id = users.id
|
JOIN users ON tags.created_by_user_id = users.id
|
||||||
WHERE tags.id = ? LIMIT 1;`
|
WHERE tags.id = $1 LIMIT 1;`
|
||||||
|
|
||||||
var getTagsQuery = `SELECT
|
var getTagsQuery = `SELECT
|
||||||
tags.id, tags.name, tags.description,
|
tags.id, tags.name, tags.description,
|
||||||
@@ -228,26 +221,27 @@ JOIN users ON tags.created_by_user_id = users.id
|
|||||||
ORDER BY tags.name
|
ORDER BY tags.name
|
||||||
;`
|
;`
|
||||||
|
|
||||||
var updateTagQuery = `UPDATE tags SET name = ?, description = ? WHERE id = ?;`
|
var updateTagQuery = `UPDATE tags SET name = $1, description = $2 WHERE id = $3;`
|
||||||
|
|
||||||
var putTagOnFileQuery = `INSERT OR IGNORE INTO file_has_tag (tag_id, file_id, user_id) VALUES (?, ?, ?);`
|
// postgres INSERT IGNORE
|
||||||
|
var putTagOnFileQuery = `INSERT INTO file_has_tag (tag_id, file_id, user_id) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING;`
|
||||||
|
|
||||||
var getTagsOnFileQuery = `SELECT
|
var getTagsOnFileQuery = `SELECT
|
||||||
tags.id, tags.name, tags.description, tags.created_by_user_id
|
tags.id, tags.name, tags.description, tags.created_by_user_id
|
||||||
FROM file_has_tag
|
FROM file_has_tag
|
||||||
JOIN tags ON file_has_tag.tag_id = tags.id
|
JOIN tags ON file_has_tag.tag_id = tags.id
|
||||||
WHERE file_has_tag.file_id = ?
|
WHERE file_has_tag.file_id = $1
|
||||||
ORDER BY tags.name
|
ORDER BY tags.name
|
||||||
;`
|
;`
|
||||||
|
|
||||||
var deleteTagOnFileQuery = `DELETE FROM file_has_tag WHERE tag_id = ? AND file_id = ?;`
|
var deleteTagOnFileQuery = `DELETE FROM file_has_tag WHERE tag_id = $1 AND file_id = $2;`
|
||||||
|
|
||||||
var deleteTagReferenceInFileHasTagQuery = `DELETE FROM file_has_tag WHERE tag_id = ?;`
|
var deleteTagReferenceInFileHasTagQuery = `DELETE FROM file_has_tag WHERE tag_id = $1;`
|
||||||
|
|
||||||
var updateFoldernameQuery = `UPDATE folders SET foldername = ? WHERE id = ?;`
|
var updateFoldernameQuery = `UPDATE folders SET foldername = $1 WHERE id = $2;`
|
||||||
|
|
||||||
var insertReviewQuery = `INSERT INTO reviews (user_id, file_id, created_at, content)
|
var insertReviewQuery = `INSERT INTO reviews (user_id, file_id, created_at, content)
|
||||||
VALUES (?, ?, ?, ?);`
|
VALUES ($1, $2, $3, $4);`
|
||||||
|
|
||||||
var getReviewsOnFileQuery = `SELECT
|
var getReviewsOnFileQuery = `SELECT
|
||||||
reviews.id, reviews.created_at, reviews.updated_at, reviews.content,
|
reviews.id, reviews.created_at, reviews.updated_at, reviews.content,
|
||||||
@@ -256,15 +250,15 @@ files.id, files.filename
|
|||||||
FROM reviews
|
FROM reviews
|
||||||
JOIN users ON reviews.user_id = users.id
|
JOIN users ON reviews.user_id = users.id
|
||||||
JOIN files ON reviews.file_id = files.id
|
JOIN files ON reviews.file_id = files.id
|
||||||
WHERE reviews.file_id = ?
|
WHERE reviews.file_id = $1
|
||||||
ORDER BY reviews.created_at
|
ORDER BY reviews.created_at
|
||||||
;`
|
;`
|
||||||
|
|
||||||
var getReviewQuery = `SELECT id, file_id, user_id, created_at, updated_at, content FROM reviews WHERE id = ? LIMIT 1;`
|
var getReviewQuery = `SELECT id, file_id, user_id, created_at, updated_at, content FROM reviews WHERE id = $1 LIMIT 1;`
|
||||||
|
|
||||||
var updateReviewQuery = `UPDATE reviews SET content = ?, updated_at = ? WHERE id = ?;`
|
var updateReviewQuery = `UPDATE reviews SET content = $1, updated_at = $2 WHERE id = $3;`
|
||||||
|
|
||||||
var deleteReviewQuery = `DELETE FROM reviews WHERE id = ?;`
|
var deleteReviewQuery = `DELETE FROM reviews WHERE id = $1;`
|
||||||
|
|
||||||
var getReviewsByUserQuery = `SELECT
|
var getReviewsByUserQuery = `SELECT
|
||||||
reviews.id, reviews.created_at, reviews.updated_at, reviews.content,
|
reviews.id, reviews.created_at, reviews.updated_at, reviews.content,
|
||||||
@@ -273,19 +267,19 @@ files.id, files.filename
|
|||||||
FROM reviews
|
FROM reviews
|
||||||
JOIN users ON reviews.user_id = users.id
|
JOIN users ON reviews.user_id = users.id
|
||||||
JOIN files ON reviews.file_id = files.id
|
JOIN files ON reviews.file_id = files.id
|
||||||
WHERE reviews.user_id = ?
|
WHERE reviews.user_id = $1
|
||||||
ORDER BY reviews.created_at
|
ORDER BY reviews.created_at
|
||||||
;`
|
;`
|
||||||
|
|
||||||
var deleteFileQuery = `DELETE FROM files WHERE id = ?;`
|
var deleteFileQuery = `DELETE FROM files WHERE id = $1;`
|
||||||
|
|
||||||
var deleteFileReferenceInFileHasTagQuery = `DELETE FROM file_has_tag WHERE file_id = ?;`
|
var deleteFileReferenceInFileHasTagQuery = `DELETE FROM file_has_tag WHERE file_id = $1;`
|
||||||
|
|
||||||
var deleteFileReferenceInReviewsQuery = `DELETE FROM reviews WHERE file_id = ?;`
|
var deleteFileReferenceInReviewsQuery = `DELETE FROM reviews WHERE file_id = $1;`
|
||||||
|
|
||||||
var updateFilenameQuery = `UPDATE files SET filename = ? WHERE id = ?;`
|
var updateFilenameQuery = `UPDATE files SET filename = $1 WHERE id = $2;`
|
||||||
|
|
||||||
var resetFilenameQuery = `UPDATE files SET filename = realname WHERE id = ?;`
|
var resetFilenameQuery = `UPDATE files SET filename = realname WHERE id = $1;`
|
||||||
|
|
||||||
var recordPlaybackQuery = `INSERT INTO playbacks (user_id, file_id, time, method, duration) VALUES ($1, $2, $3, $4, $5);`
|
var recordPlaybackQuery = `INSERT INTO playbacks (user_id, file_id, time, method, duration) VALUES ($1, $2, $3, $4, $5);`
|
||||||
|
|
||||||
@@ -357,26 +351,22 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
|||||||
|
|
||||||
stmt := &Stmt{}
|
stmt := &Stmt{}
|
||||||
|
|
||||||
// init files table
|
|
||||||
stmt.initFilesTable, err = sqlConn.Prepare(initFilesTableQuery)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// init folders table
|
// init folders table
|
||||||
stmt.initFoldersTable, err = sqlConn.Prepare(initFoldersTableQuery)
|
stmt.initFoldersTable, err = sqlConn.Prepare(initFoldersTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initFoldersTable.Exec()
|
||||||
// init feedbacks tables
|
|
||||||
stmt.initFeedbacksTable, err = sqlConn.Prepare(initFeedbacksTableQuery)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// init users table
|
// init files table
|
||||||
stmt.initUsersTable, err = sqlConn.Prepare(initUsersTableQuery)
|
stmt.initFilesTable, err = sqlConn.Prepare(initFilesTableQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = stmt.initFilesTable.Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -386,99 +376,103 @@ func NewPreparedStatement(sqlConn *sql.DB) (*Stmt, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initAvatarsTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init users table
|
||||||
|
stmt.initUsersTable, err = sqlConn.Prepare(initUsersTableQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = stmt.initUsersTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// init feedbacks tables
|
||||||
|
stmt.initFeedbacksTable, err = sqlConn.Prepare(initFeedbacksTableQuery)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
_, err = stmt.initFeedbacksTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init tags table
|
// init tags table
|
||||||
stmt.initTagsTable, err = sqlConn.Prepare(initTagsTableQuery)
|
stmt.initTagsTable, err = sqlConn.Prepare(initTagsTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initTagsTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init file_has_tag table
|
// init file_has_tag table
|
||||||
stmt.initFileHasTag, err = sqlConn.Prepare(initFileHasTagTableQuery)
|
stmt.initFileHasTag, err = sqlConn.Prepare(initFileHasTagTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initFileHasTag.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init likes table
|
// init likes table
|
||||||
stmt.initLikesTable, err = sqlConn.Prepare(initLikesTableQuery)
|
stmt.initLikesTable, err = sqlConn.Prepare(initLikesTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initLikesTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init reviews table
|
// init reviews table
|
||||||
stmt.initReviewsTable, err = sqlConn.Prepare(initReviewsTableQuery)
|
stmt.initReviewsTable, err = sqlConn.Prepare(initReviewsTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initReviewsTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init playbacks table
|
// init playbacks table
|
||||||
stmt.initPlaybacksTable, err = sqlConn.Prepare(initPlaybacksTableQuery)
|
stmt.initPlaybacksTable, err = sqlConn.Prepare(initPlaybacksTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initPlaybacksTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init logs table
|
// init logs table
|
||||||
stmt.initLogsTable, err = sqlConn.Prepare(initLogsTableQuery)
|
stmt.initLogsTable, err = sqlConn.Prepare(initLogsTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
_, err = stmt.initLogsTable.Exec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// init tmpfs table
|
// init tmpfs table
|
||||||
stmt.initTmpfsTable, err = sqlConn.Prepare(initTmpfsTableQuery)
|
stmt.initTmpfsTable, err = sqlConn.Prepare(initTmpfsTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// run init statement
|
|
||||||
_, err = stmt.initFilesTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initFoldersTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initFeedbacksTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initUsersTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initAvatarsTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initTagsTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initFileHasTag.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initLikesTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initReviewsTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initPlaybacksTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initLogsTable.Exec()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
_, err = stmt.initTmpfsTable.Exec()
|
_, err = stmt.initTmpfsTable.Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Println("Init tables finished")
|
||||||
|
|
||||||
// init insert folder statement
|
// init insert folder statement
|
||||||
stmt.insertFolder, err = sqlConn.Prepare(insertFolderQuery)
|
stmt.insertFolder, err = sqlConn.Prepare(insertFolderQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ type File struct {
|
|||||||
Realname string `json:"-"`
|
Realname string `json:"-"`
|
||||||
Filename string `json:"filename"`
|
Filename string `json:"filename"`
|
||||||
Filesize int64 `json:"filesize"`
|
Filesize int64 `json:"filesize"`
|
||||||
|
folderCache *Folder
|
||||||
}
|
}
|
||||||
|
|
||||||
type Folder struct {
|
type Folder struct {
|
||||||
@@ -75,9 +76,23 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (f *File) Path() (string, error) {
|
func (f *File) Path() (string, error) {
|
||||||
folder, err := f.Db.GetFolder(f.Folder_id)
|
var err error
|
||||||
|
if f.folderCache == nil {
|
||||||
|
f.folderCache, err = f.Db.GetFolder(f.Folder_id)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return filepath.Join(folder.Folder, f.Realname), nil
|
return filepath.Join(f.folderCache.Folder, f.Realname), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) Dir() (string, error) {
|
||||||
|
var err error
|
||||||
|
if f.folderCache == nil {
|
||||||
|
f.folderCache, err = f.Db.GetFolder(f.Folder_id)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return f.folderCache.Folder, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,19 @@ html {
|
|||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
margin-top: 1rem;
|
padding-top: 1rem;
|
||||||
|
max-width: unset;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
#root {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.base {
|
.base {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-row-gap: 1em;
|
grid-row-gap: 1em;
|
||||||
|
max-width: 800px;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
@@ -28,6 +28,27 @@ function App() {
|
|||||||
const [user, setUser] = useState({});
|
const [user, setUser] = useState({});
|
||||||
const [langCode, setLangCode] = useState("en_US");
|
const [langCode, setLangCode] = useState("en_US");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (playingFile.id === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const html = document.getElementsByTagName("html")[0];
|
||||||
|
const retStyle = html.style;
|
||||||
|
const bodyRetStyle = document.body.style
|
||||||
|
html.style = `
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
background-size: cover;
|
||||||
|
background-attachment: fixed;
|
||||||
|
background-position: center;
|
||||||
|
background-image: url("/api/v1/get_file_avatar?id=${playingFile.id}");
|
||||||
|
`;
|
||||||
|
document.body.style.opacity = 0.88;
|
||||||
|
return () => {
|
||||||
|
html.style = retStyle;
|
||||||
|
document.body.style = bodyRetStyle;
|
||||||
|
};
|
||||||
|
}, [playingFile.id]);
|
||||||
|
|
||||||
// select language
|
// select language
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const browserCode = window.navigator.language;
|
const browserCode = window.navigator.language;
|
||||||
@@ -41,7 +62,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fallback to english
|
// fallback to english
|
||||||
setLangCode('en-US');
|
setLangCode("en-US");
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -22,25 +22,50 @@ function AudioPlayer(props) {
|
|||||||
const [isPreparing, setIsPreparing] = useState(false);
|
const [isPreparing, setIsPreparing] = useState(false);
|
||||||
const [timerCount, setTimerCount] = useState(0);
|
const [timerCount, setTimerCount] = useState(0);
|
||||||
const [timerID, setTimerID] = useState(null);
|
const [timerID, setTimerID] = useState(null);
|
||||||
|
const [beginPlayTime, setBeginPlayTime] = useState(null);
|
||||||
|
const [lastID, setLastID] = useState(null);
|
||||||
|
|
||||||
|
const recordPlaybackHistory = async (file_id, method) => {
|
||||||
|
if (file_id === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const player = document.getElementById('dom-player')
|
||||||
|
const endPlayTime = new Date()
|
||||||
|
let duration = parseInt((endPlayTime - beginPlayTime) / 1000)
|
||||||
|
const maxDuration = parseInt(player.duration)
|
||||||
|
// treat 85% of duration as finished
|
||||||
|
if (duration / maxDuration >= 0.85) {
|
||||||
|
method = 1
|
||||||
|
}
|
||||||
|
duration = duration < maxDuration ? duration : maxDuration
|
||||||
|
setBeginPlayTime(endPlayTime)
|
||||||
|
await fetch('/api/v1/record_playback', {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
playback: {
|
||||||
|
file_id,
|
||||||
|
method,
|
||||||
|
duration,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// init mediaSession API
|
// init mediaSession API
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (navigator.mediaSession) {
|
||||||
navigator.mediaSession.setActionHandler("stop", () => {
|
navigator.mediaSession.setActionHandler("stop", () => {
|
||||||
props.setPlayingFile({});
|
props.setPlayingFile({});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
const updatePlayMode = () => {
|
||||||
// media session related staff
|
|
||||||
navigator.mediaSession.metadata = new window.MediaMetadata({
|
|
||||||
title: props.playingFile.filename,
|
|
||||||
album: props.playingFile.foldername,
|
|
||||||
artwork: [{ src: "/favicon.png", type: "image/png" }],
|
|
||||||
});
|
|
||||||
// no playing file
|
|
||||||
if (props.playingFile.id === undefined) {
|
if (props.playingFile.id === undefined) {
|
||||||
setPlayingURL("");
|
return
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (raw) {
|
if (raw) {
|
||||||
console.log("Play raw file");
|
console.log("Play raw file");
|
||||||
@@ -76,7 +101,39 @@ function AudioPlayer(props) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [props.playingFile.id, raw, prepare, selectedFfmpegConfig]);
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// media session related staff
|
||||||
|
if (navigator.mediaSession) {
|
||||||
|
navigator.mediaSession.metadata = new window.MediaMetadata({
|
||||||
|
title: props.playingFile.filename,
|
||||||
|
album: props.playingFile.foldername,
|
||||||
|
artwork: [{src: "/favicon.png", type: "image/png"}],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// no playing file
|
||||||
|
if (props.playingFile.id === undefined) {
|
||||||
|
// 3 music stopped
|
||||||
|
recordPlaybackHistory(lastID, 3)
|
||||||
|
setPlayingURL("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// crrently playing file, record interupt
|
||||||
|
if (playingURL) {
|
||||||
|
// 2 music changed
|
||||||
|
recordPlaybackHistory(lastID, 2)
|
||||||
|
}
|
||||||
|
setLastID(props.playingFile.id)
|
||||||
|
// have playingFile, record begin time
|
||||||
|
setBeginPlayTime(new Date())
|
||||||
|
updatePlayMode()
|
||||||
|
}, [props.playingFile.id]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updatePlayMode()
|
||||||
|
}, [raw, prepare, selectedFfmpegConfig])
|
||||||
|
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
|
||||||
@@ -192,9 +249,19 @@ function AudioPlayer(props) {
|
|||||||
id="dom-player"
|
id="dom-player"
|
||||||
controls
|
controls
|
||||||
autoPlay
|
autoPlay
|
||||||
loop={loop}
|
|
||||||
className="audio-player"
|
className="audio-player"
|
||||||
src={playingURL}
|
src={playingURL}
|
||||||
|
onEnded={async () => {
|
||||||
|
const player = document.getElementById('dom-player')
|
||||||
|
if (loop) {
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
// 1 music finished
|
||||||
|
recordPlaybackHistory(props.playingFile.id, 1)
|
||||||
|
}}
|
||||||
|
onPlay={async () => {
|
||||||
|
setBeginPlayTime(new Date());
|
||||||
|
}}
|
||||||
></audio>
|
></audio>
|
||||||
|
|
||||||
<FfmpegConfig
|
<FfmpegConfig
|
||||||
|
|||||||
Reference in New Issue
Block a user