2020-03-04 17:22:58 +00:00
package jounce
import (
"database/sql"
"sync"
_ "github.com/mattn/go-sqlite3"
)
type User struct {
Username string
2020-03-11 18:09:32 +00:00
Password string // hashed
2020-03-04 17:22:58 +00:00
}
type Network struct {
ID int64
Addr string
Nick string
Username string
Realname string
}
type Channel struct {
ID int64
Name string
}
type DB struct {
2020-03-04 19:15:38 +00:00
lock sync . RWMutex
2020-03-04 17:22:58 +00:00
db * sql . DB
}
func OpenSQLDB ( driver , source string ) ( * DB , error ) {
db , err := sql . Open ( driver , source )
if err != nil {
return nil , err
}
return & DB { db : db } , nil
}
func ( db * DB ) Close ( ) error {
db . lock . Lock ( )
defer db . lock . Unlock ( )
return db . Close ( )
}
func ( db * DB ) ListUsers ( ) ( [ ] User , error ) {
2020-03-04 19:15:38 +00:00
db . lock . RLock ( )
defer db . lock . RUnlock ( )
2020-03-04 17:22:58 +00:00
rows , err := db . db . Query ( "SELECT username, password FROM User" )
if err != nil {
return nil , err
}
defer rows . Close ( )
var users [ ] User
for rows . Next ( ) {
var user User
var password * string
if err := rows . Scan ( & user . Username , & password ) ; err != nil {
return nil , err
}
if password != nil {
user . Password = * password
}
users = append ( users , user )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return users , nil
}
2020-03-11 18:01:03 +00:00
func ( db * DB ) CreateUser ( user * User ) error {
db . lock . Lock ( )
defer db . lock . Unlock ( )
var password * string
if user . Password != "" {
password = & user . Password
}
2020-03-12 17:33:03 +00:00
_ , err := db . db . Exec ( "INSERT INTO User(username, password) VALUES (?, ?)" , user . Username , password )
return err
2020-03-11 18:01:03 +00:00
}
2020-03-04 17:22:58 +00:00
func ( db * DB ) ListNetworks ( username string ) ( [ ] Network , error ) {
2020-03-04 19:15:38 +00:00
db . lock . RLock ( )
defer db . lock . RUnlock ( )
2020-03-04 17:22:58 +00:00
rows , err := db . db . Query ( "SELECT id, addr, nick, username, realname FROM Network WHERE user = ?" , username )
if err != nil {
return nil , err
}
defer rows . Close ( )
var networks [ ] Network
for rows . Next ( ) {
var net Network
var username , realname * string
if err := rows . Scan ( & net . ID , & net . Addr , & net . Nick , & username , & realname ) ; err != nil {
return nil , err
}
if username != nil {
net . Username = * username
}
if realname != nil {
net . Realname = * realname
}
networks = append ( networks , net )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return networks , nil
}
2020-03-12 18:17:06 +00:00
func ( db * DB ) StoreNetwork ( username string , network * Network ) error {
db . lock . Lock ( )
defer db . lock . Unlock ( )
var netUsername , netRealname * string
if network . Username != "" {
netUsername = & network . Username
}
if network . Realname != "" {
netRealname = & network . Realname
}
var err error
if network . ID != 0 {
_ , err = db . db . Exec ( "UPDATE Network SET addr = ?, nick = ?, username = ?, realname = ? WHERE id = ?" , network . Addr , network . Nick , netUsername , netRealname , network . ID )
} else {
var res sql . Result
res , err = db . db . Exec ( "INSERT INTO Network(user, addr, nick, username, realname) VALUES (?, ?, ?, ?, ?)" , username , network . Addr , network . Nick , netUsername , netRealname )
if err != nil {
return err
}
network . ID , err = res . LastInsertId ( )
}
return err
}
2020-03-04 17:22:58 +00:00
func ( db * DB ) ListChannels ( networkID int64 ) ( [ ] Channel , error ) {
2020-03-04 19:15:38 +00:00
db . lock . RLock ( )
defer db . lock . RUnlock ( )
2020-03-04 17:22:58 +00:00
rows , err := db . db . Query ( "SELECT id, name FROM Channel WHERE network = ?" , networkID )
if err != nil {
return nil , err
}
defer rows . Close ( )
var channels [ ] Channel
for rows . Next ( ) {
var ch Channel
if err := rows . Scan ( & ch . ID , & ch . Name ) ; err != nil {
return nil , err
}
channels = append ( channels , ch )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return channels , nil
}
2020-03-12 17:33:03 +00:00
func ( db * DB ) StoreChannel ( networkID int64 , ch * Channel ) error {
db . lock . Lock ( )
defer db . lock . Unlock ( )
_ , err := db . db . Exec ( "INSERT OR REPLACE INTO Channel(network, name) VALUES (?, ?)" , networkID , ch . Name )
return err
}
func ( db * DB ) DeleteChannel ( networkID int64 , name string ) error {
db . lock . Lock ( )
defer db . lock . Unlock ( )
_ , err := db . db . Exec ( "DELETE FROM Channel WHERE network = ? AND name = ?" , networkID , name )
return err
}