124 lines
2.9 KiB
Go
124 lines
2.9 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
|
||
|
"github.com/go-chi/chi/v5"
|
||
|
"github.com/go-chi/chi/v5/middleware"
|
||
|
"github.com/gorilla/handlers"
|
||
|
)
|
||
|
|
||
|
type mxError struct {
|
||
|
ErrCode string `json:"errcode"`
|
||
|
Error string `json:"error"`
|
||
|
}
|
||
|
|
||
|
var internalErrorBuf = []byte(`{"errcode":"M_UNKNOWN", "error": "Internal error"}`)
|
||
|
|
||
|
type RoomMapping struct {
|
||
|
RoomID string `json:"room_id"`
|
||
|
Servers []string `json:"servers"`
|
||
|
}
|
||
|
|
||
|
var KnownRooms = map[string]RoomMapping{}
|
||
|
|
||
|
func SendJSON(w http.ResponseWriter, obj any, status int) {
|
||
|
w.Header().Set("Content-Type", "application/json")
|
||
|
buf, err := json.Marshal(obj)
|
||
|
if err != nil {
|
||
|
log.Printf("Error marshaling JSON response: %v", err)
|
||
|
w.WriteHeader(500)
|
||
|
_, _ = w.Write(internalErrorBuf)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
w.WriteHeader(status)
|
||
|
_, _ = w.Write(buf)
|
||
|
}
|
||
|
|
||
|
func NotFound(w http.ResponseWriter, r *http.Request) {
|
||
|
SendJSON(w, mxError{"M_UNRECOGNIZED", "Unsupported Endpoint"}, 404)
|
||
|
}
|
||
|
|
||
|
func MethodNotAllowed(w http.ResponseWriter, r *http.Request) {
|
||
|
SendJSON(w, mxError{"M_UNRECOGNIZED", "Unrecognized Method"}, 405)
|
||
|
}
|
||
|
|
||
|
func Version(w http.ResponseWriter, r *http.Request) {
|
||
|
SendJSON(w, map[string]any{
|
||
|
"name": "Matrix-Vanity",
|
||
|
"version": "0.0",
|
||
|
}, 200)
|
||
|
}
|
||
|
|
||
|
func QueryDirectory(w http.ResponseWriter, r *http.Request) {
|
||
|
q := r.URL.Query()
|
||
|
roomAlias := q.Get("room_alias")
|
||
|
|
||
|
mapping, ok := KnownRooms[roomAlias]
|
||
|
if !ok {
|
||
|
log.Printf("Room '%s' not found", roomAlias)
|
||
|
SendJSON(w, mxError{"M_NOT_FOUND", "Room alias not found."}, 404)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
SendJSON(w, mapping, 200)
|
||
|
}
|
||
|
|
||
|
func Index(w http.ResponseWriter, r *http.Request) {
|
||
|
w.WriteHeader(200)
|
||
|
w.Write([]byte("This is a Matrix-Vanity server"))
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
useProxyIP := os.Getenv("MXV_USE_PROXY_HEADERS") != ""
|
||
|
|
||
|
configFile := os.Getenv("MXV_ROOMS_FILE")
|
||
|
if configFile == "" {
|
||
|
configFile = "/etc/matrix-vanity-rooms.json"
|
||
|
}
|
||
|
log.Printf("Loading room list from %s", configFile)
|
||
|
|
||
|
listenAddr := os.Getenv("MXV_LISTEN")
|
||
|
if listenAddr == "" {
|
||
|
listenAddr = ":3333"
|
||
|
}
|
||
|
|
||
|
buf, err := os.ReadFile(configFile)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Error reading room file: %v", err)
|
||
|
}
|
||
|
|
||
|
if err := json.Unmarshal(buf, &KnownRooms); err != nil {
|
||
|
log.Fatalf("Error parsing room file: %v", err)
|
||
|
}
|
||
|
|
||
|
log.Print("Defined Rooms:")
|
||
|
for alias, info := range KnownRooms {
|
||
|
log.Printf(" - '%s', ID: '%s', Servers: %v", alias, info.RoomID, info.Servers)
|
||
|
}
|
||
|
if len(KnownRooms) == 0 {
|
||
|
log.Printf("⚠️ No rooms defined. That doesn't seem very useful ")
|
||
|
}
|
||
|
log.Print("")
|
||
|
|
||
|
r := chi.NewRouter()
|
||
|
if useProxyIP {
|
||
|
log.Print("X-Forwarded-For header intepretation enabled; it is assumed you are running this service behind a proxy")
|
||
|
r.Use(handlers.ProxyHeaders)
|
||
|
}
|
||
|
r.Use(middleware.Logger)
|
||
|
r.Use(middleware.Recoverer)
|
||
|
|
||
|
r.NotFound(NotFound)
|
||
|
r.MethodNotAllowed(MethodNotAllowed)
|
||
|
r.Get("/", Index)
|
||
|
r.Get("/_matrix/federation/v1/version", Version)
|
||
|
r.Get("/_matrix/federation/v1/query/directory", QueryDirectory)
|
||
|
log.Printf("Listening on %q", listenAddr)
|
||
|
http.ListenAndServe(listenAddr, r)
|
||
|
}
|