142
commands.go
142
commands.go
@@ -32,6 +32,7 @@ import (
|
|||||||
|
|
||||||
"maunium.net/go/mautrix"
|
"maunium.net/go/mautrix"
|
||||||
"maunium.net/go/mautrix/appservice"
|
"maunium.net/go/mautrix/appservice"
|
||||||
|
"maunium.net/go/mautrix/bridge/bridgeconfig"
|
||||||
"maunium.net/go/mautrix/bridge/commands"
|
"maunium.net/go/mautrix/bridge/commands"
|
||||||
"maunium.net/go/mautrix/event"
|
"maunium.net/go/mautrix/event"
|
||||||
"maunium.net/go/mautrix/id"
|
"maunium.net/go/mautrix/id"
|
||||||
@@ -58,6 +59,9 @@ func (br *DiscordBridge) RegisterCommands() {
|
|||||||
cmdPing,
|
cmdPing,
|
||||||
cmdReconnect,
|
cmdReconnect,
|
||||||
cmdDisconnect,
|
cmdDisconnect,
|
||||||
|
cmdBridge,
|
||||||
|
cmdUnbridge,
|
||||||
|
cmdDeletePortal,
|
||||||
cmdSetRelay,
|
cmdSetRelay,
|
||||||
cmdUnsetRelay,
|
cmdUnsetRelay,
|
||||||
cmdGuilds,
|
cmdGuilds,
|
||||||
@@ -406,6 +410,7 @@ func fnSetRelay(ce *WrappedCommandEvent) {
|
|||||||
ce.Reply("Portal with room ID %s not found", ce.Args[0])
|
ce.Reply("Portal with room ID %s not found", ce.Args[0])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if ce.User.PermissionLevel < bridgeconfig.PermissionLevelAdmin {
|
||||||
levels, err := portal.MainIntent().PowerLevels(ce.RoomID)
|
levels, err := portal.MainIntent().PowerLevels(ce.RoomID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ce.ZLog.Warn().Err(err).Msg("Failed to check room power levels")
|
ce.ZLog.Warn().Err(err).Msg("Failed to check room power levels")
|
||||||
@@ -415,6 +420,7 @@ func fnSetRelay(ce *WrappedCommandEvent) {
|
|||||||
ce.Reply("You don't have admin rights in that room")
|
ce.Reply("You don't have admin rights in that room")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ce.Args = ce.Args[1:]
|
ce.Args = ce.Args[1:]
|
||||||
} else if portal == nil {
|
} else if portal == nil {
|
||||||
ce.Reply("You must either run the command in a portal, or specify an internal room ID as the first parameter")
|
ce.Reply("You must either run the command in a portal, or specify an internal room ID as the first parameter")
|
||||||
@@ -640,6 +646,142 @@ func fnGuildBridgingMode(ce *WrappedCommandEvent) {
|
|||||||
ce.Reply("Set guild bridging mode to %s", mode.Description())
|
ce.Reply("Set guild bridging mode to %s", mode.Description())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cmdBridge = &commands.FullHandler{
|
||||||
|
Func: wrapCommand(fnBridge),
|
||||||
|
Name: "bridge",
|
||||||
|
Help: commands.HelpMeta{
|
||||||
|
Section: HelpSectionPortalManagement,
|
||||||
|
Description: "Bridge this room to a specific Discord channel",
|
||||||
|
Args: "[--replace[=delete]] <_channel ID_>",
|
||||||
|
},
|
||||||
|
RequiresEventLevel: roomModerator,
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNumber(str string) bool {
|
||||||
|
for _, chr := range str {
|
||||||
|
if chr < '0' || chr > '9' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func fnBridge(ce *WrappedCommandEvent) {
|
||||||
|
if ce.Portal != nil {
|
||||||
|
ce.Reply("This is already a portal room. Unbridge with `$cmdprefix unbridge` first if you want to link it to a different channel.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var channelID string
|
||||||
|
var unbridgeOld, deleteOld bool
|
||||||
|
fail := true
|
||||||
|
for _, arg := range ce.Args {
|
||||||
|
arg = strings.ToLower(arg)
|
||||||
|
if arg == "--replace" {
|
||||||
|
unbridgeOld = true
|
||||||
|
} else if arg == "--replace=delete" {
|
||||||
|
unbridgeOld = true
|
||||||
|
deleteOld = true
|
||||||
|
} else if channelID == "" && isNumber(arg) {
|
||||||
|
channelID = arg
|
||||||
|
fail = false
|
||||||
|
} else {
|
||||||
|
fail = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fail {
|
||||||
|
ce.Reply("**Usage**: `$cmdprefix bridge [--replace[=delete]] <channel ID>`")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
portal := ce.User.GetExistingPortalByID(channelID)
|
||||||
|
if portal == nil {
|
||||||
|
ce.Reply("Channel not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
portal.roomCreateLock.Lock()
|
||||||
|
defer portal.roomCreateLock.Lock()
|
||||||
|
if portal.MXID != "" {
|
||||||
|
hasUnbridgePermission := ce.User.PermissionLevel >= bridgeconfig.PermissionLevelAdmin
|
||||||
|
if !hasUnbridgePermission {
|
||||||
|
levels, err := portal.MainIntent().PowerLevels(portal.MXID)
|
||||||
|
if errors.Is(err, mautrix.MNotFound) {
|
||||||
|
ce.ZLog.Debug().Err(err).Msg("Got M_NOT_FOUND trying to get power levels to check if user can unbridge it, assuming the room is gone")
|
||||||
|
hasUnbridgePermission = true
|
||||||
|
} else if err != nil {
|
||||||
|
ce.ZLog.Warn().Err(err).Msg("Failed to check room power levels")
|
||||||
|
ce.Reply("Failed to get power levels in old room to see if you're allowed to unbridge it")
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
hasUnbridgePermission = levels.GetUserLevel(ce.User.GetMXID()) >= levels.GetEventLevel(roomModerator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !unbridgeOld || !hasUnbridgePermission {
|
||||||
|
extraHelp := "Rerun the command with `--replace` or `--replace=delete` to unbridge the old room."
|
||||||
|
if !hasUnbridgePermission {
|
||||||
|
extraHelp = "Additionally, you do not have the permissions to unbridge the old room."
|
||||||
|
}
|
||||||
|
ce.Reply("That channel is already bridged to [%s](https://matrix.to/#/%s). %s", portal.Name, portal.MXID, extraHelp)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ce.ZLog.Debug().
|
||||||
|
Str("old_room_id", portal.MXID.String()).
|
||||||
|
Bool("delete", deleteOld).
|
||||||
|
Msg("Unbridging old room")
|
||||||
|
portal.removeFromSpace()
|
||||||
|
portal.RemoveMXID()
|
||||||
|
portal.cleanup(deleteOld)
|
||||||
|
ce.ZLog.Info().
|
||||||
|
Str("old_room_id", portal.MXID.String()).
|
||||||
|
Bool("delete", deleteOld).
|
||||||
|
Msg("Unbridged old room to make space for new bridge")
|
||||||
|
}
|
||||||
|
if portal.Guild != nil && portal.Guild.BridgingMode < database.GuildBridgeIfPortalExists {
|
||||||
|
ce.ZLog.Debug().Str("guild_id", portal.Guild.ID).Msg("Bumping bridging mode of portal guild to if-portal-exists")
|
||||||
|
portal.Guild.BridgingMode = database.GuildBridgeIfPortalExists
|
||||||
|
portal.Guild.Update()
|
||||||
|
}
|
||||||
|
ce.ZLog.Debug().Str("channel_id", portal.Key.ChannelID).Msg("Bridging room")
|
||||||
|
portal.MXID = ce.RoomID
|
||||||
|
portal.updateRoomName()
|
||||||
|
portal.updateRoomAvatar()
|
||||||
|
portal.updateRoomTopic()
|
||||||
|
portal.updateSpace()
|
||||||
|
portal.UpdateBridgeInfo()
|
||||||
|
portal.Update()
|
||||||
|
ce.Reply("Room successfully bridged")
|
||||||
|
ce.ZLog.Info().Str("channel_id", portal.Key.ChannelID).Msg("Manual bridging complete")
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdUnbridge = &commands.FullHandler{
|
||||||
|
Func: wrapCommand(fnUnbridge),
|
||||||
|
Name: "unbridge",
|
||||||
|
Help: commands.HelpMeta{
|
||||||
|
Section: HelpSectionPortalManagement,
|
||||||
|
Description: "Unbridge this room from the linked Discord channel",
|
||||||
|
},
|
||||||
|
RequiresPortal: true,
|
||||||
|
RequiresEventLevel: roomModerator,
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmdDeletePortal = &commands.FullHandler{
|
||||||
|
Func: wrapCommand(fnUnbridge),
|
||||||
|
Name: "delete-portal",
|
||||||
|
Help: commands.HelpMeta{
|
||||||
|
Section: HelpSectionPortalManagement,
|
||||||
|
Description: "Unbridge this room and kick all Matrix users",
|
||||||
|
},
|
||||||
|
RequiresPortal: true,
|
||||||
|
RequiresEventLevel: roomModerator,
|
||||||
|
}
|
||||||
|
|
||||||
|
func fnUnbridge(ce *WrappedCommandEvent) {
|
||||||
|
ce.Portal.roomCreateLock.Lock()
|
||||||
|
defer ce.Portal.roomCreateLock.Lock()
|
||||||
|
ce.Portal.removeFromSpace()
|
||||||
|
ce.Portal.RemoveMXID()
|
||||||
|
ce.Portal.cleanup(ce.Command == "delete-portal")
|
||||||
|
}
|
||||||
|
|
||||||
var cmdDeleteAllPortals = &commands.FullHandler{
|
var cmdDeleteAllPortals = &commands.FullHandler{
|
||||||
Func: wrapCommand(fnDeleteAllPortals),
|
Func: wrapCommand(fnDeleteAllPortals),
|
||||||
Name: "delete-all-portals",
|
Name: "delete-all-portals",
|
||||||
|
|||||||
16
portal.go
16
portal.go
@@ -160,7 +160,9 @@ func (br *DiscordBridge) GetExistingPortalByID(key database.PortalKey) *Portal {
|
|||||||
defer br.portalsLock.Unlock()
|
defer br.portalsLock.Unlock()
|
||||||
portal, ok := br.portalsByID[key]
|
portal, ok := br.portalsByID[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
if key.Receiver != "" {
|
||||||
portal, ok = br.portalsByID[database.NewPortalKey(key.ChannelID, "")]
|
portal, ok = br.portalsByID[database.NewPortalKey(key.ChannelID, "")]
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return br.loadPortal(br.DB.Portal.GetByID(key), nil, -1)
|
return br.loadPortal(br.DB.Portal.GetByID(key), nil, -1)
|
||||||
}
|
}
|
||||||
@@ -1732,6 +1734,11 @@ func (portal *Portal) UpdateNameDirect(name string) bool {
|
|||||||
portal.log.Debugfln("Updating name %q -> %q", portal.Name, name)
|
portal.log.Debugfln("Updating name %q -> %q", portal.Name, name)
|
||||||
portal.Name = name
|
portal.Name = name
|
||||||
portal.NameSet = false
|
portal.NameSet = false
|
||||||
|
portal.updateRoomName()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (portal *Portal) updateRoomName() {
|
||||||
if portal.MXID != "" {
|
if portal.MXID != "" {
|
||||||
_, err := portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
|
_, err := portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1740,7 +1747,6 @@ func (portal *Portal) UpdateNameDirect(name string) bool {
|
|||||||
portal.NameSet = true
|
portal.NameSet = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) UpdateAvatarFromPuppet(puppet *Puppet) bool {
|
func (portal *Portal) UpdateAvatarFromPuppet(puppet *Puppet) bool {
|
||||||
@@ -1779,7 +1785,7 @@ func (portal *Portal) UpdateGroupDMAvatar(iconID string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) updateRoomAvatar() {
|
func (portal *Portal) updateRoomAvatar() {
|
||||||
if portal.MXID == "" {
|
if portal.MXID == "" || portal.AvatarURL.IsEmpty() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err := portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL)
|
_, err := portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL)
|
||||||
@@ -1797,6 +1803,11 @@ func (portal *Portal) UpdateTopic(topic string) bool {
|
|||||||
portal.log.Debugfln("Updating topic %q -> %q", portal.Topic, topic)
|
portal.log.Debugfln("Updating topic %q -> %q", portal.Topic, topic)
|
||||||
portal.Topic = topic
|
portal.Topic = topic
|
||||||
portal.TopicSet = false
|
portal.TopicSet = false
|
||||||
|
portal.updateRoomTopic()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (portal *Portal) updateRoomTopic() {
|
||||||
if portal.MXID != "" {
|
if portal.MXID != "" {
|
||||||
_, err := portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
|
_, err := portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1805,7 +1816,6 @@ func (portal *Portal) UpdateTopic(topic string) bool {
|
|||||||
portal.TopicSet = true
|
portal.TopicSet = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (portal *Portal) removeFromSpace() {
|
func (portal *Portal) removeFromSpace() {
|
||||||
|
|||||||
Reference in New Issue
Block a user