Initial bot functionality
* The bot now properly joins the management room * The management room is persisted in the database * Welcome/help messages are sent in the management room
This commit is contained in:
@@ -15,6 +15,10 @@ type Database struct {
|
||||
*sql.DB
|
||||
log log.Logger
|
||||
dialect string
|
||||
|
||||
User *UserQuery
|
||||
Portal *PortalQuery
|
||||
Puppet *PuppetQuery
|
||||
}
|
||||
|
||||
func New(dbType, uri string, maxOpenConns, maxIdleConns int, baseLog log.Logger) (*Database, error) {
|
||||
@@ -42,5 +46,20 @@ func New(dbType, uri string, maxOpenConns, maxIdleConns int, baseLog log.Logger)
|
||||
dialect: dbType,
|
||||
}
|
||||
|
||||
db.User = &UserQuery{
|
||||
db: db,
|
||||
log: db.log.Sub("User"),
|
||||
}
|
||||
|
||||
db.Portal = &PortalQuery{
|
||||
db: db,
|
||||
log: db.log.Sub("Portal"),
|
||||
}
|
||||
|
||||
db.Puppet = &PuppetQuery{
|
||||
db: db,
|
||||
log: db.log.Sub("Puppet"),
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
CREATE TABLE IF NOT EXISTS portal (
|
||||
did text,
|
||||
receiver text,
|
||||
mxid text UNIQUE,
|
||||
id TEXT,
|
||||
receiver TEXT,
|
||||
mxid TEXT UNIQUE,
|
||||
|
||||
name text NOT NULL,
|
||||
topic text NOT NULL,
|
||||
avatar text NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
topic TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (did, receiver)
|
||||
avatar TEXT NOT NULL,
|
||||
avatar_url TEXT NOT NULL,
|
||||
|
||||
PRIMARY KEY (id, receiver)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS puppet (
|
||||
id TEXT PRIMARY KEY,
|
||||
displayname TEXT,
|
||||
|
||||
avatar TEXT,
|
||||
avatar_url TEXT,
|
||||
|
||||
enable_presence BOOLEAN NOT NULL DEFAULT true
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS user (
|
||||
mxid TEXT PRIMARY KEY,
|
||||
id TEXT UNIQUE,
|
||||
|
||||
management_room TEXT,
|
||||
|
||||
token TEXT
|
||||
);
|
||||
|
||||
53
database/portal.go
Normal file
53
database/portal.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
log "maunium.net/go/maulogger/v2"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
type Portal struct {
|
||||
db *Database
|
||||
log log.Logger
|
||||
|
||||
Key PortalKey
|
||||
MXID id.RoomID
|
||||
|
||||
Name string
|
||||
Topic string
|
||||
|
||||
Avatar string
|
||||
AvatarURL id.ContentURI
|
||||
}
|
||||
|
||||
func (p *Portal) Scan(row Scannable) *Portal {
|
||||
var mxid, avatarURL sql.NullString
|
||||
|
||||
err := row.Scan(&p.Key.ID, &p.Key.Receiver, &mxid, &p.Name, &p.Topic, &p.Avatar, &avatarURL)
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
p.log.Errorln("Database scan failed:", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
p.MXID = id.RoomID(mxid.String)
|
||||
p.AvatarURL, _ = id.ParseContentURI(avatarURL.String)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Portal) Insert() {
|
||||
query := "INSERT INTO portal" +
|
||||
" (id, receiver, mxid, name, topic, avatar, avatar_url)" +
|
||||
" VALUES ($1, $2, $3, $4, $5, $6, $7)"
|
||||
|
||||
_, err := p.db.Exec(query, p.Key.ID, p.Key.Receiver, p.MXID,
|
||||
p.Name, p.Topic, p.Avatar, p.AvatarURL.String())
|
||||
|
||||
if err != nil {
|
||||
p.log.Warnfln("Failed to insert %s: %v", p.Key, err)
|
||||
}
|
||||
}
|
||||
13
database/portalkey.go
Normal file
13
database/portalkey.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package database
|
||||
|
||||
type PortalKey struct {
|
||||
ID string
|
||||
Receiver string
|
||||
}
|
||||
|
||||
func (key PortalKey) String() string {
|
||||
if key.Receiver == key.ID {
|
||||
return key.ID
|
||||
}
|
||||
return key.ID + "-" + key.Receiver
|
||||
}
|
||||
58
database/portalquery.go
Normal file
58
database/portalquery.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
log "maunium.net/go/maulogger/v2"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
type PortalQuery struct {
|
||||
db *Database
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (pq *PortalQuery) New() *Portal {
|
||||
return &Portal{
|
||||
db: pq.db,
|
||||
log: pq.log,
|
||||
}
|
||||
}
|
||||
|
||||
func (pq *PortalQuery) GetAll() []*Portal {
|
||||
return pq.getAll("SELECT * FROM portal")
|
||||
}
|
||||
|
||||
func (pq *PortalQuery) GetByDID(key PortalKey) *Portal {
|
||||
return pq.get("SELECT * FROM portal WHERE did=$1 AND receiver=$2", key.ID, key.Receiver)
|
||||
}
|
||||
|
||||
func (pq *PortalQuery) GetByMXID(mxid id.RoomID) *Portal {
|
||||
return pq.get("SELECT * FROM portal WHERE mxid=$1", mxid)
|
||||
}
|
||||
|
||||
func (pq *PortalQuery) GetAllByDID(did string) []*Portal {
|
||||
return pq.getAll("SELECT * FROM portal WHERE did=$1", did)
|
||||
}
|
||||
|
||||
func (pq *PortalQuery) getAll(query string, args ...interface{}) []*Portal {
|
||||
rows, err := pq.db.Query(query, args...)
|
||||
if err != nil || rows == nil {
|
||||
return nil
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
portals := []*Portal{}
|
||||
for rows.Next() {
|
||||
portals = append(portals, pq.New().Scan(rows))
|
||||
}
|
||||
|
||||
return portals
|
||||
}
|
||||
|
||||
func (pq *PortalQuery) get(query string, args ...interface{}) *Portal {
|
||||
row := pq.db.QueryRow(query, args...)
|
||||
if row == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return pq.New().Scan(row)
|
||||
}
|
||||
56
database/puppet.go
Normal file
56
database/puppet.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
log "maunium.net/go/maulogger/v2"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
type Puppet struct {
|
||||
db *Database
|
||||
log log.Logger
|
||||
|
||||
ID string
|
||||
DisplayName string
|
||||
|
||||
Avatar string
|
||||
AvatarURL id.ContentURI
|
||||
|
||||
EnablePresence bool
|
||||
}
|
||||
|
||||
func (p *Puppet) Scan(row Scannable) *Puppet {
|
||||
var did, displayName, avatar, avatarURL sql.NullString
|
||||
var enablePresence sql.NullBool
|
||||
|
||||
err := row.Scan(&did, &displayName, &avatar, &avatarURL, &enablePresence)
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
p.log.Errorln("Database scan failed:", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
p.ID = did.String
|
||||
p.DisplayName = displayName.String
|
||||
p.Avatar = avatar.String
|
||||
p.AvatarURL, _ = id.ParseContentURI(avatarURL.String)
|
||||
p.EnablePresence = enablePresence.Bool
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Puppet) Insert() {
|
||||
query := "INSERT INTO puppet" +
|
||||
" (id, display_name, avatar, avatar_url, enable_presence)" +
|
||||
" VALUES ($1, $2, $3, $4, $5)"
|
||||
|
||||
_, err := p.db.Exec(query, p.ID, p.DisplayName, p.Avatar,
|
||||
p.AvatarURL.String(), p.EnablePresence)
|
||||
|
||||
if err != nil {
|
||||
p.log.Warnfln("Failed to insert %s: %v", p.ID, err)
|
||||
}
|
||||
}
|
||||
28
database/puppetquery.go
Normal file
28
database/puppetquery.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
log "maunium.net/go/maulogger/v2"
|
||||
)
|
||||
|
||||
type PuppetQuery struct {
|
||||
db *Database
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (pq *PuppetQuery) New() *Puppet {
|
||||
return &Puppet{
|
||||
db: pq.db,
|
||||
log: pq.log,
|
||||
|
||||
EnablePresence: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (pq *PuppetQuery) Get(id string) *Puppet {
|
||||
row := pq.db.QueryRow("SELECT id, displayname, avatar, avatar_url, enable_presence FROM puppet WHERE id=$1", id)
|
||||
if row == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return pq.New().Scan(row)
|
||||
}
|
||||
5
database/scannable.go
Normal file
5
database/scannable.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package database
|
||||
|
||||
type Scannable interface {
|
||||
Scan(...interface{}) error
|
||||
}
|
||||
83
database/user.go
Normal file
83
database/user.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/bwmarrin/discordgo"
|
||||
|
||||
log "maunium.net/go/maulogger/v2"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
db *Database
|
||||
log log.Logger
|
||||
|
||||
MXID id.UserID
|
||||
ID string
|
||||
|
||||
ManagementRoom id.RoomID
|
||||
|
||||
Session *discordgo.Session
|
||||
}
|
||||
|
||||
func (u *User) Scan(row Scannable) *User {
|
||||
var token sql.NullString
|
||||
|
||||
err := row.Scan(&u.MXID, &u.ID, &u.ManagementRoom, &token)
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
u.log.Errorln("Database scan failed:", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if token.Valid {
|
||||
session, err := discordgo.New("Bearer " + token.String)
|
||||
if err != nil {
|
||||
u.log.Errorln("Failed to create discord session:", err)
|
||||
} else {
|
||||
u.Session = session
|
||||
}
|
||||
}
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
func (u *User) sessionNonptr() discordgo.Session {
|
||||
if u.Session != nil {
|
||||
return *u.Session
|
||||
}
|
||||
|
||||
return discordgo.Session{}
|
||||
}
|
||||
|
||||
func (u *User) Insert() {
|
||||
session := u.sessionNonptr()
|
||||
|
||||
query := "INSERT INTO user" +
|
||||
" (mxid, id, management_room, token)" +
|
||||
" VALUES ($1, $2, $3, $4);"
|
||||
|
||||
_, err := u.db.Exec(query, u.MXID, u.ID, u.ManagementRoom,
|
||||
session.Identify.Token)
|
||||
|
||||
if err != nil {
|
||||
u.log.Warnfln("Failed to insert %s: %v", u.MXID, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (u *User) Update() {
|
||||
session := u.sessionNonptr()
|
||||
|
||||
query := "UPDATE user SET" +
|
||||
" id=$1, management_room=$2, token=$3" +
|
||||
" WHERE mxid=$4;"
|
||||
|
||||
_, err := u.db.Exec(query, u.ID, u.ManagementRoom, session.Identify.Token, u.MXID)
|
||||
|
||||
if err != nil {
|
||||
u.log.Warnfln("Failed to update %q: %v", u.MXID, err)
|
||||
}
|
||||
}
|
||||
27
database/userquery.go
Normal file
27
database/userquery.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
log "maunium.net/go/maulogger/v2"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
type UserQuery struct {
|
||||
db *Database
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func (uq *UserQuery) New() *User {
|
||||
return &User{
|
||||
db: uq.db,
|
||||
log: uq.log,
|
||||
}
|
||||
}
|
||||
|
||||
func (uq *UserQuery) GetByMXID(userID id.UserID) *User {
|
||||
row := uq.db.QueryRow("SELECT mxid, id, management_room, token FROM user where mxid=$1", userID)
|
||||
if row == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return uq.New().Scan(row)
|
||||
}
|
||||
Reference in New Issue
Block a user