hummingbard/client/create.go

397 lines
8.6 KiB
Go

package client
import (
"context"
"encoding/json"
"fmt"
"hummingbard/gomatrix"
"log"
"net/http"
"strings"
"time"
"github.com/unrolled/secure"
)
func (c *Client) CreateRoom() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
us := LoggedInUser(r)
type page struct {
BasePage
UserExists bool
}
nonce := secure.CSPNonce(r.Context())
t := &page{}
t.Nonce = nonce
t.LoggedInUser = us
c.Templates.ExecuteTemplate(w, "create", t)
}
}
func (c *Client) UsernameAvailable() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
user, err := c.GetTokenUser(token)
if err != nil || user == nil {
log.Println(err)
w.WriteHeader(http.StatusUnauthorized)
return
}
type payload struct {
Username string `json:"username"`
SubSpace bool `json:"sub_space"`
ParentRoomID string `json:"parent_room_id"`
}
var pay payload
if r.Body == nil {
log.Println(err)
http.Error(w, "Please send a request body", 400)
return
}
err = json.NewDecoder(r.Body).Decode(&pay)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 400)
return
}
log.Println("recieved payload ", pay)
type Response struct {
Available bool `json:"available"`
}
ff := Response{Available: false}
matrix, err := c.TempMatrixClient(user.UserID, user.MatrixAccessToken)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 400)
return
}
username := strings.ToLower(pay.Username)
if pay.SubSpace {
state, err := matrix.RoomState(pay.ParentRoomID)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 400)
return
}
alias := c.CanonicalAliasFromState(state)
alias = alias[1:]
s := strings.Split(alias, ":")
localPart := s[0]
username = fmt.Sprintf(`%s_%s`, localPart, strings.ToLower(pay.Username))
}
canon := fmt.Sprintf(`#%s:%s`, username, c.Config.Client.Domain)
if user.Federated {
canon = fmt.Sprintf(`#%s:%s`, username, user.HomeServer)
}
av, err := matrix.ResolveAlias(canon)
if av == nil {
ff.Available = true
}
js, err := json.Marshal(ff)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
}
func (c *Client) ValidateRoomCreation() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
user, err := c.GetTokenUser(token)
if err != nil || user == nil {
log.Println(err)
w.WriteHeader(http.StatusUnauthorized)
return
}
type payload struct {
Username string `json:"username"`
Title string `json:"title"`
About string `json:"about"`
Type string `json:"type"`
Private bool `json:"private"`
NSFW bool `json:"nsfw"`
SubSpace bool `json:"sub_space"`
ParentRoomID string `json:"parent_room_id"`
Page bool `json:"page"`
}
var pay payload
if r.Body == nil {
log.Println(err)
http.Error(w, "Please send a request body", 400)
return
}
err = json.NewDecoder(r.Body).Decode(&pay)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 400)
return
}
log.Println("recieved payload ", pay)
type NewRoom struct {
RoomID string `json:"room_id"`
Alias string `json:"alias"`
CanonicalAlias string `json:"canonical_alias"`
Path string `json:"path"`
}
type Response struct {
Created bool `json:"created"`
Room NewRoom `json:"room,omitempty"`
}
ff := Response{
Created: false,
}
matrix, err := c.TempMatrixClient(user.UserID, user.MatrixAccessToken)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 400)
return
}
canon := fmt.Sprintf(`#%s:%s`, strings.ToLower(pay.Username), c.Config.Client.Domain)
var state []*gomatrix.Event
alias := ""
if pay.SubSpace {
state, err = matrix.RoomState(pay.ParentRoomID)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), 400)
return
}
alias = c.CanonicalAliasFromState(state)
s := strings.Split(alias, ":")
localPart := s[0]
username := fmt.Sprintf(`%s_%s`, localPart, strings.ToLower(pay.Username))
canon = fmt.Sprintf(`#%s:%s`, username, c.Config.Client.Domain)
}
_, err = c.Matrix.ResolveAlias(canon)
if err != nil {
//create the room
pl := gomatrix.Event{
Type: "m.room.power_levels",
Content: map[string]interface{}{
"ban": 50,
"events": map[string]interface{}{
"m.room.name": 100,
"m.room.power_levels": 100,
},
"events_default": 0,
"invite": 50,
"kick": 50,
"notifications": map[string]interface{}{
"room": 20,
},
"redact": 50,
"state_default": 50,
"users": map[string]interface{}{
user.UserID: 100,
c.DefaultUser.UserID: 100,
},
"users_default": 0,
},
}
initState := []gomatrix.Event{
gomatrix.Event{
Type: "m.room.history_visibility",
Content: map[string]interface{}{
"history_visibility": "world_readable",
},
}, gomatrix.Event{
Type: "m.room.guest_access",
Content: map[string]interface{}{
"guest_access": "can_join",
},
}, gomatrix.Event{
Type: "com.hummingbard.room",
Content: map[string]interface{}{
"room_type": pay.Type,
},
}, gomatrix.Event{
Type: "m.room.type",
Content: map[string]interface{}{
"type": "m.space",
},
},
pl,
}
username := strings.ToLower(pay.Username)
path := ""
if pay.SubSpace {
alias = alias[1:]
s := strings.Split(alias, ":")
localPart := s[0]
username = fmt.Sprintf(`%s_%s`, localPart, strings.ToLower(pay.Username))
x := strings.Split(localPart, "_")
j := strings.Join(x, "/")
path = fmt.Sprintf(`%s/%s`, j, strings.ToLower(pay.Username))
content := map[string]interface{}{
"canonical_alias": fmt.Sprintf(`#%s:%s`, username, user.HomeServer),
"local_part": username,
"stripped": strings.ToLower(pay.Username),
"room_path": path,
"via": []string{c.Config.Client.Domain},
}
if pay.Page {
content["page"] = true
}
initState = append(initState, gomatrix.Event{
Type: fmt.Sprintf(`%s.parent`, c.Config.Spaces.Prefix),
StateKey: &pay.ParentRoomID,
Content: content,
})
}
if pay.NSFW {
initState = append(initState, gomatrix.Event{
Type: "com.hummingbard.room.nsfw",
Content: map[string]interface{}{
"nsfw": true,
},
})
}
req := &gomatrix.ReqCreateRoom{
Preset: "public_chat",
Visibility: "public",
RoomAliasName: strings.ToLower(pay.Username),
Name: pay.Title,
Topic: pay.About,
CreationContent: map[string]interface{}{
"m.federate": true,
},
InitialState: initState,
}
if pay.SubSpace {
req.RoomAliasName = username
}
if pay.Private {
req.Preset = "private_chat"
req.Visibility = "private"
}
crr, err := matrix.CreateRoom(req)
if err != nil || crr == nil {
log.Println(err)
log.Println(err)
http.Error(w, err.Error(), 400)
return
}
ff.Created = true
canon := fmt.Sprintf(`#%s:%s`, pay.Username, user.HomeServer)
ff.Room = NewRoom{
RoomID: crr.RoomID,
Alias: strings.ToLower(pay.Username),
CanonicalAlias: canon,
Path: path,
}
err = c.RefreshRoomsCache()
if err != nil {
log.Println(err)
}
err = c.UpdateJoinedRooms(matrix, r)
if err != nil {
log.Println(err)
}
ctx := context.Background()
ctx, _ = context.WithTimeout(ctx, 3*time.Second)
if !pay.Page {
alias := fmt.Sprintf(`#%s:%s`, strings.ToLower(username), user.HomeServer)
path := username
if strings.Contains(path, "_") {
s := strings.Split(path, "_")
path = strings.Join(s, "/")
}
c.Cache.Rooms.Set(crr.RoomID, alias, 1)
}
if crr != nil {
c.OperatorJoinRoom(crr.RoomID)
if pay.Type != "gallery" && pay.Type == "page" {
text, html := InitialMessage()
npe := gomatrix.CreatePostEvent{
RoomID: crr.RoomID,
Text: text,
FormattedText: html,
}
_, err := matrix.CreatePost(&npe)
if err != nil {
log.Println(err)
log.Println(err)
}
}
}
}
js, err := json.Marshal(ff)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
}