|
@@ -1,9 +1,12 @@
|
|
|
package db
|
|
|
|
|
|
import (
|
|
|
+ "notabug.org/apiote/amuse/tmdb"
|
|
|
"notabug.org/apiote/amuse/utils"
|
|
|
|
|
|
+ "crypto/rand"
|
|
|
"database/sql"
|
|
|
+ "encoding/hex"
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"os"
|
|
@@ -12,6 +15,15 @@ import (
|
|
|
_ "github.com/mattn/go-sqlite3"
|
|
|
)
|
|
|
|
|
|
+type ItemType string
|
|
|
+
|
|
|
+const (
|
|
|
+ ItemTypeBook ItemType = "book"
|
|
|
+ ItemTypeFilm = "film"
|
|
|
+ ItemTypeTvserie = "tvserie"
|
|
|
+ ItemTypeUnkown = "unknown"
|
|
|
+)
|
|
|
+
|
|
|
type EmptyError struct {
|
|
|
message string
|
|
|
}
|
|
@@ -28,12 +40,14 @@ type User struct {
|
|
|
AvatarSmall []byte
|
|
|
IsAdmin bool
|
|
|
RecoveryCodes string
|
|
|
+ Timezone string
|
|
|
}
|
|
|
|
|
|
type Session struct {
|
|
|
Id string
|
|
|
Username string
|
|
|
Expiry time.Time
|
|
|
+ IsLong bool
|
|
|
}
|
|
|
|
|
|
func Migrate() error {
|
|
@@ -48,15 +62,22 @@ func Migrate() error {
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- _, err = db.Exec(`create table users(username text primary key, password text, sfa text, avatar blob, avatar_small blob, is_admin bool, recovery_codes text)`)
|
|
|
+ _, err = db.Exec(`create table users(username text primary key, password text, sfa text, avatar blob, avatar_small blob, is_admin bool, recovery_codes text, timezone text)`)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- _, err = db.Exec(`create table sessions(id text primary key, username text, expiry datetime, foreign key(username) references users(username))`)
|
|
|
+ _, err = db.Exec(`create table sessions(id text primary key, username text, expiry datetime, is_long boolean, foreign key(username) references users(username))`)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ _, err = db.Exec(`create table wantlist(username text, item_type text, item_id text, primary key(username, item_type, item_id), foreign key(username) references users(username))`)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ _, err = db.Exec(`create table experiences(username text, item_type text, item_id text, time datetime, foreign key(username) references users(username))`)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
-
|
|
|
return nil
|
|
|
}
|
|
|
|
|
@@ -100,7 +121,7 @@ func GetUser(username string) (*User, error) {
|
|
|
return nil, err
|
|
|
}
|
|
|
defer db.Close()
|
|
|
- rows, err := db.Query(`select password, sfa, recovery_codes, is_admin, avatar, avatar_small from users where username = ?`, username)
|
|
|
+ rows, err := db.Query(`select password, sfa, recovery_codes, is_admin, avatar, avatar_small, timezone from users where username = ?`, username)
|
|
|
if err != nil {
|
|
|
fmt.Fprintf(os.Stderr, "Select err %v\n", err)
|
|
|
return nil, err
|
|
@@ -110,7 +131,7 @@ func GetUser(username string) (*User, error) {
|
|
|
return nil, EmptyError{message: "User does not exist"}
|
|
|
}
|
|
|
user := User{Username: username}
|
|
|
- err = rows.Scan(&user.PasswordHash, &user.Sfa, &user.RecoveryCodes, &user.IsAdmin, &user.Avatar, &user.AvatarSmall)
|
|
|
+ err = rows.Scan(&user.PasswordHash, &user.Sfa, &user.RecoveryCodes, &user.IsAdmin, &user.Avatar, &user.AvatarSmall, &user.Timezone)
|
|
|
if err != nil {
|
|
|
fmt.Fprintf(os.Stderr, "Scan err %v\n", err)
|
|
|
return nil, err
|
|
@@ -134,11 +155,15 @@ func UpdateRecoveryCodes(username, recoveryCodes string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func CreateSession(username, sessionId string, long bool) error {
|
|
|
+func CreateSession(username string, long bool) (Session, error) {
|
|
|
+ sessionIdRaw := make([]byte, 64)
|
|
|
+ rand.Read(sessionIdRaw)
|
|
|
+ sessionId := hex.EncodeToString(sessionIdRaw)
|
|
|
+
|
|
|
db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db")
|
|
|
if err != nil {
|
|
|
fmt.Fprintf(os.Stderr, "DB open err\n")
|
|
|
- return err
|
|
|
+ return Session{}, err
|
|
|
}
|
|
|
defer db.Close()
|
|
|
|
|
@@ -148,12 +173,12 @@ func CreateSession(username, sessionId string, long bool) error {
|
|
|
} else {
|
|
|
length = "1 hour"
|
|
|
}
|
|
|
- _, err = db.Exec(`insert into sessions values(?, ?, datetime('now', '`+length+`'))`, sessionId, username)
|
|
|
+ _, err = db.Exec(`insert into sessions values(?, ?, datetime('now', '`+length+`'), ?)`, sessionId, username, long)
|
|
|
if err != nil {
|
|
|
- return err
|
|
|
+ return Session{}, err
|
|
|
}
|
|
|
|
|
|
- return nil
|
|
|
+ return Session{Id: sessionId, Username: username, IsLong: long}, nil
|
|
|
}
|
|
|
|
|
|
func GetSession(token string) (*Session, error) {
|
|
@@ -164,7 +189,7 @@ func GetSession(token string) (*Session, error) {
|
|
|
}
|
|
|
defer db.Close()
|
|
|
|
|
|
- rows, err := db.Query(`select username, expiry from sessions where id = ?`, token)
|
|
|
+ rows, err := db.Query(`select username, expiry, is_long from sessions where id = ?`, token)
|
|
|
if err != nil {
|
|
|
fmt.Fprintf(os.Stderr, "Select err %v\n", err)
|
|
|
return nil, err
|
|
@@ -174,10 +199,145 @@ func GetSession(token string) (*Session, error) {
|
|
|
return nil, EmptyError{message: "Session does not exist"}
|
|
|
}
|
|
|
session := Session{Id: token}
|
|
|
- err = rows.Scan(&session.Username, &session.Expiry)
|
|
|
+ err = rows.Scan(&session.Username, &session.Expiry, &session.IsLong)
|
|
|
if err != nil {
|
|
|
fmt.Fprintf(os.Stderr, "Scan err %v\n", err)
|
|
|
return nil, err
|
|
|
}
|
|
|
return &session, nil
|
|
|
}
|
|
|
+
|
|
|
+func ClearSessions(username string) error {
|
|
|
+ db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db")
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "DB open err\n")
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ defer db.Close()
|
|
|
+
|
|
|
+ _, err = db.Exec(`delete from sessions where username = ? and expiry < datetime('now')`, username)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Delete err %v\n", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func GetItemExperiences(username, itemId string, itemType ItemType) (map[string][]time.Time, error) {
|
|
|
+ times := map[string][]time.Time{}
|
|
|
+ user, err := GetUser(username)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Get user err: %v\n", err)
|
|
|
+ return times, err
|
|
|
+ }
|
|
|
+ location, err := time.LoadLocation(user.Timezone)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Load location err: %v\n", err)
|
|
|
+ return times, err
|
|
|
+ }
|
|
|
+
|
|
|
+ db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db")
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "DB open err\n")
|
|
|
+ return times, err
|
|
|
+ }
|
|
|
+ defer db.Close()
|
|
|
+ rows, err := db.Query(`select time, item_id from experiences where username = ? and item_type = ? and (item_id = ? or item_id like ?)`, username, itemType, itemId, itemId+"/%")
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Select err %v\n", err)
|
|
|
+ return times, err
|
|
|
+ }
|
|
|
+ defer rows.Close()
|
|
|
+
|
|
|
+ for rows.Next() {
|
|
|
+ var (
|
|
|
+ t time.Time
|
|
|
+ id string
|
|
|
+ )
|
|
|
+ err := rows.Scan(&t, &id)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Scan err %v\n", err)
|
|
|
+ return times, err
|
|
|
+ }
|
|
|
+ t = t.In(location)
|
|
|
+ times[id] = append(times[id], t)
|
|
|
+ }
|
|
|
+ return times, nil
|
|
|
+}
|
|
|
+
|
|
|
+func AddToExperiences(username, itemId string, itemType ItemType, datetime time.Time) error {
|
|
|
+ db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db")
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "DB open err\n")
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ defer db.Close()
|
|
|
+
|
|
|
+ _, err = db.Exec(`insert into experiences values(?, ?, ?, ?)`, username, itemType, itemId, datetime)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Insert err %v\n", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ //todo if !datetime.IsZero() then delete all datetime that .IsZero() where itemId = itemId
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func AddToWantList(username, itemId string, itemType ItemType) error {
|
|
|
+ db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db")
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "DB open err\n")
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ defer db.Close()
|
|
|
+
|
|
|
+ _, err = db.Exec(`insert into wantlist values(?, ?, ?)`, username, itemType, itemId)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Insert err %v\n", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func RemoveFromWantList(username, itemId string, itemType ItemType) error {
|
|
|
+ db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db")
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "DB open err\n")
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ defer db.Close()
|
|
|
+
|
|
|
+ _, err = db.Exec(`delete from wantlist where username = ? and item_type = ? and item_id = ?`, username, itemType, itemId)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Insert err %v\n", err)
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func IsOnWantList(username, itemId string, itemType ItemType) (bool, error) {
|
|
|
+ db, err := sql.Open("sqlite3", utils.DataHome+"/amuse.db")
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "DB open err\n")
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+ defer db.Close()
|
|
|
+
|
|
|
+ rows, err := db.Query(`select 1 from wantlist where username = ? and item_id = ? and item_type = ?`, username, itemId, string(itemType))
|
|
|
+ if err != nil {
|
|
|
+ fmt.Fprintf(os.Stderr, "Select err: %v\n", err)
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+ return rows.Next(), nil
|
|
|
+}
|
|
|
+
|
|
|
+func GetItemTypeFromShow(show tmdb.Show) ItemType {
|
|
|
+ if _, ok := show.(*tmdb.Film); ok {
|
|
|
+ return ItemTypeFilm
|
|
|
+ } else if _, ok := show.(*tmdb.TvSerie); ok {
|
|
|
+ return ItemTypeTvserie
|
|
|
+ } else {
|
|
|
+ return ItemTypeUnkown
|
|
|
+ }
|
|
|
+}
|