easybridge/appservice/server.go

149 lines
3.6 KiB
Go
Raw Normal View History

2020-02-16 18:30:49 +00:00
package appservice
import (
"encoding/json"
"fmt"
"strings"
"net/http"
2020-02-17 08:41:08 +00:00
"github.com/gorilla/mux"
log "github.com/sirupsen/logrus"
2020-02-16 18:30:49 +00:00
"git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
2020-02-16 18:30:49 +00:00
)
type Config struct {
HttpBindAddr string
Server string
DbType string
DbPath string
2020-02-16 21:07:41 +00:00
MatrixDomain string
2020-02-16 18:30:49 +00:00
}
var registration *mxlib.Registration
var config *Config
func Start(r *mxlib.Registration, c *Config) (chan error, error) {
registration = r
config = c
err := InitDb()
if err != nil {
return nil, err
}
2020-02-17 14:30:01 +00:00
svc_mxid := fmt.Sprintf("@%s:%s", registration.SenderLocalpart, config.MatrixDomain)
err = mxRegisterUser(registration.SenderLocalpart)
if mxe, ok := err.(*mxlib.MxError); !ok || mxe.ErrCode != "M_USER_IN_USE" {
return nil, err
}
err = mxProfileDisplayname(svc_mxid, "Easybridge")
if err != nil {
return nil, err
}
2020-02-16 18:30:49 +00:00
router := mux.NewRouter()
router.HandleFunc("/_matrix/app/v1/transactions/{txnId}", handleTxn)
2020-02-16 21:07:41 +00:00
router.HandleFunc("/transactions/{txnId}", handleTxn)
2020-02-16 18:30:49 +00:00
errch := make(chan error)
go func() {
log.Printf("Starting HTTP server on %s", config.HttpBindAddr)
err := http.ListenAndServe(config.HttpBindAddr, checkTokenAndLog(router))
if err != nil {
errch <- err
}
}()
return errch, nil
}
func checkTokenAndLog(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
if strings.Join(r.Form["access_token"], "") != registration.HsToken {
http.Error(w, "Wrong or no token provided", http.StatusUnauthorized)
return
}
log.Printf("%s %s %s\n", r.RemoteAddr, r.Method, r.URL)
handler.ServeHTTP(w, r)
})
}
func handleTxn(w http.ResponseWriter, r *http.Request) {
2020-02-16 21:57:30 +00:00
if r.Method == "PUT" {
var txn mxlib.Transaction
err := json.NewDecoder(r.Body).Decode(&txn)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
log.Printf("JSON decode error: %s\n", err)
return
}
2020-02-16 18:30:49 +00:00
2020-02-16 21:57:30 +00:00
log.Printf("Got transaction %#v\n", txn)
for i := range txn.Events {
handleTxnEvent(&txn.Events[i])
}
2020-02-16 21:57:30 +00:00
fmt.Fprintf(w, "{}\n")
} else {
http.Error(w, "Expected PUT request", http.StatusBadRequest)
}
2020-02-16 18:30:49 +00:00
}
func handleTxnEvent(e *mxlib.Event) {
if e.Type == "m.room.message" {
ev := &connector.Event{
Type: connector.EVENT_MESSAGE,
Text: e.Content["body"].(string),
}
typ := e.Content["msgtype"].(string)
if typ == "m.emote" {
ev.Type = connector.EVENT_MESSAGE
}
// Look up if this is a private message room
2020-02-17 14:30:01 +00:00
if pm_room := dbIsPmRoom(e.RoomId); pm_room != nil {
acct := FindAccount(pm_room.MxUserID, pm_room.AccountName)
if acct != nil && e.Sender == pm_room.MxUserID {
ev.Author = acct.Conn.User()
ev.Recipient = pm_room.UserID
acct.Conn.Send(ev)
}
}
// Look up if this is a regular room
2020-02-17 14:30:01 +00:00
if room := dbIsPublicRoom(e.RoomId); room != nil {
acct := FindJoinedAccount(e.Sender, room.Protocol, room.RoomID)
if acct != nil {
ev.Author = acct.Conn.User()
ev.Room = room.RoomID
acct.Conn.Send(ev)
}
}
2020-02-17 14:30:01 +00:00
} else if e.Type == "m.room.member" {
ms := e.Content["membership"].(string)
if ms == "leave" {
// If leaving a PM room, we must delete it
if pm_room := dbIsPmRoom(e.RoomId); pm_room != nil {
them_mx := userMxId(pm_room.Protocol, pm_room.UserID)
mxRoomLeaveAs(e.RoomId, them_mx)
db.Delete(pm_room)
}
// If leaving a public room, leave from server as well
if room := dbIsPublicRoom(e.RoomId); room != nil {
acct := FindJoinedAccount(e.Sender, room.Protocol, room.RoomID)
if acct != nil {
acct.Conn.Leave(room.RoomID)
// TODO: manage autojoin list, remove this room
}
}
}
}
}