aboutsummaryrefslogblamecommitdiff
path: root/appservice/db.go
blob: e5b2d0273b6583fb0822916b3dcd303874262caf (plain) (tree)
1
2
3
4
5
6
7
8
9
10


                  
             
 
                                        



                                                    


                                                           











                                                         








                                                                                                                                

                  

































                                                                     
                               




                                                











































































































                                                                                                                              

















                                                                                 
package appservice

import (
	"fmt"

	log "github.com/sirupsen/logrus"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	_ "github.com/jinzhu/gorm/dialects/postgres"
	_ "github.com/jinzhu/gorm/dialects/sqlite"

	"git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib"
	"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
)

var db *gorm.DB

func InitDb() error {
	var err error

	db, err = gorm.Open(config.DbType, config.DbPath)
	if err != nil {
		return err
	}

	db.AutoMigrate(&DbUserMap{})
	db.Model(&DbUserMap{}).AddIndex("idx_protocol_user", "protocol", "user_id")

	db.AutoMigrate(&DbRoomMap{})
	db.Model(&DbRoomMap{}).AddIndex("idx_protocol_room", "protocol", "room_id")

	db.AutoMigrate(&DbPmRoomMap{})
	db.Model(&DbPmRoomMap{}).AddIndex("idx_protocol_user_account_user", "protocol", "user_id", "mx_user_id", "account_name")

	return nil
}

// User mapping between protocol user IDs and puppeted matrix ids
type DbUserMap struct {
	gorm.Model

	Protocol string
	UserID connector.UserID
	MxUserID string `gorm:"index:mxuserid"`
}

// Room mapping between Matrix rooms and outside rooms
type DbRoomMap struct {
	gorm.Model

	// Network protocol
	Protocol string

	// Room id on the bridged network
	RoomID connector.RoomID

	// Bridged room matrix id
	MxRoomID string `gorm:"index:mxroomid"`
}

// Room mapping between Matrix rooms and private messages
type DbPmRoomMap struct {
	gorm.Model

	// User id and account name of the local end viewed on Matrix
	MxUserID string
	Protocol string
	AccountName string

	// User id to reach them
	UserID connector.UserID

	// Bridged room for PMs
	MxRoomID string `gorm:"index:mxroomoid"`
}

// ----

func dbGetMxRoom(protocol string, roomId connector.RoomID) (string, error) {
	var room DbRoomMap

	// Check if room exists in our mapping,
	// If not create it
	must_create := db.First(&room, DbRoomMap{
		Protocol: protocol,
		RoomID: roomId,
	}).RecordNotFound()
	if must_create {
		alias := roomAlias(protocol, roomId)
		// Lookup alias
		mx_room_id, err := mxDirectoryRoom(fmt.Sprintf("#%s:%s", alias, config.MatrixDomain))

		// If no alias found, create room
		if err != nil {
			name := fmt.Sprintf("%s (%s)", roomId, protocol)

			mx_room_id, err = mxCreateRoom(name, alias, []string{})
			if err != nil {
				log.Printf("Could not create room for %s: %s", name, err)
				return "", err
			}
		}

		room = DbRoomMap{
			Protocol: protocol,
			RoomID: roomId,
			MxRoomID: mx_room_id,
		}
		db.Create(&room)
	}
	log.Printf("Got room id: %s", room.MxRoomID)

	return room.MxRoomID, nil
}

func dbGetMxPmRoom(protocol string, them connector.UserID, themMxId string, usMxId string, usAccount string) (string, error) {
	var room DbPmRoomMap

	must_create := db.First(&room, DbPmRoomMap{
		MxUserID: usMxId,
		Protocol: protocol,
		AccountName: usAccount,
		UserID: them,
	}).RecordNotFound()
	if must_create {
		name := fmt.Sprintf("%s (%s)", them, protocol)

		mx_room_id, err := mxCreateDirectRoomAs(name, []string{usMxId}, themMxId)
		if err != nil {
			log.Printf("Could not create room for %s: %s", name, err)
			return "", err
		}

		err = mxRoomJoinAs(mx_room_id, themMxId)
		if err != nil {
			log.Printf("Could not join %s as %s", mx_room_id, themMxId)
			return "", err
		}

		room = DbPmRoomMap{
			MxUserID: usMxId,
			Protocol: protocol,
			AccountName: usAccount,
			UserID: them,
			MxRoomID: mx_room_id,
		}
		db.Create(&room)
	}
	log.Printf("Got PM room id: %s", room.MxRoomID)

	return room.MxRoomID, nil
}

func dbGetMxUser(protocol string, userId connector.UserID) (string, error) {
	var user DbUserMap

	must_create := db.First(&user, DbUserMap{
		Protocol: protocol,
		UserID: userId,
	}).RecordNotFound()
	if must_create {
		username := userMxId(protocol, userId)

		err := mxRegisterUser(username)
		if err != nil {
			if mxE, ok := err.(*mxlib.MxError); !ok || mxE.ErrCode != "M_USER_IN_USE" {
				log.Printf("Could not register %s: %s", username, err)
				return "", err
			}
		}

		mxid := fmt.Sprintf("@%s:%s", username, config.MatrixDomain)
		mxProfileDisplayname(mxid, fmt.Sprintf("%s (%s)", userId, protocol))

		user = DbUserMap{
			Protocol: protocol,
			UserID: userId,
			MxUserID: mxid,
		}
		db.Create(&user)
	}

	return user.MxUserID, nil
}

func dbIsPmRoom(mxRoomId string) *DbPmRoomMap {
	var pm_room DbPmRoomMap
	if db.First(&pm_room, DbPmRoomMap{MxRoomID: mxRoomId}).RecordNotFound() {
		return nil
	} else {
		return &pm_room
	}
}

func dbIsPublicRoom(mxRoomId string) *DbRoomMap {
	var room DbRoomMap
	if db.First(&room, DbRoomMap{MxRoomID: mxRoomId}).RecordNotFound() {
		return nil
	} else {
		return &room
	}
}