Add alias management command and alt_aliases rendering

* /alias command can be used to create and remove local aliases
* Changes to the alt_aliases are now rendered properly
This commit is contained in:
Tulir Asokan 2020-06-17 14:15:22 +03:00
parent a8b6abe970
commit 38d5ef5603
3 changed files with 168 additions and 81 deletions

View File

@ -41,11 +41,13 @@ type Command struct {
Command string Command string
OrigCommand string OrigCommand string
Args []string Args []string
RawArgs string
OrigText string OrigText string
} }
func (cmd *Command) Reply(message string, args ...interface{}) { func (cmd *Command) Reply(message string, args ...interface{}) {
cmd.Room.AddServiceMessage(fmt.Sprintf(message, args...)) cmd.Room.AddServiceMessage(fmt.Sprintf(message, args...))
cmd.UI.Render()
} }
type Alias struct { type Alias struct {
@ -128,6 +130,7 @@ func NewCommandProcessor(parent *MainView) *CommandProcessor {
"rainbow": cmdRainbow, "rainbow": cmdRainbow,
"rainbowme": cmdRainbowMe, "rainbowme": cmdRainbowMe,
"notice": cmdNotice, "notice": cmdNotice,
"alias": cmdAlias,
"tags": cmdTags, "tags": cmdTags,
"tag": cmdTag, "tag": cmdTag,
"untag": cmdUntag, "untag": cmdUntag,
@ -146,15 +149,22 @@ func (ch *CommandProcessor) ParseCommand(roomView *RoomView, text string) *Comma
return nil return nil
} }
text = text[1:] text = text[1:]
split := strings.SplitN(text, " ", -1) split := strings.Fields(text)
command := split[0]
args := split[1:]
var rawArgs string
if len(text) > len(command)+1 {
rawArgs = text[len(command)+1:]
}
return &Command{ return &Command{
gomuksPointerContainer: ch.gomuksPointerContainer, gomuksPointerContainer: ch.gomuksPointerContainer,
Handler: ch, Handler: ch,
Room: roomView, Room: roomView,
Command: strings.ToLower(split[0]), Command: strings.ToLower(command),
OrigCommand: split[0], OrigCommand: command,
Args: split[1:], Args: args,
RawArgs: rawArgs,
OrigText: text, OrigText: text,
} }
} }

View File

@ -33,6 +33,7 @@ import (
"unicode" "unicode"
"github.com/lucasb-eyer/go-colorful" "github.com/lucasb-eyer/go-colorful"
"github.com/pkg/errors"
"github.com/russross/blackfriday/v2" "github.com/russross/blackfriday/v2"
"maunium.net/go/mautrix" "maunium.net/go/mautrix"
@ -124,7 +125,7 @@ func cmdAccept(cmd *Command) {
_, server, _ := room.SessionMember.Sender.Parse() _, server, _ := room.SessionMember.Sender.Parse()
_, err := cmd.Matrix.JoinRoom(room.ID, server) _, err := cmd.Matrix.JoinRoom(room.ID, server)
if err != nil { if err != nil {
cmd.Reply("Failed to accept invite:", err) cmd.Reply("Failed to accept invite: %v", err)
} else { } else {
cmd.Reply("Successfully accepted invite") cmd.Reply("Successfully accepted invite")
} }
@ -183,7 +184,7 @@ func cmdCopy(cmd *Command) {
if len(register) == 0 { if len(register) == 0 {
register = "clipboard" register = "clipboard"
} }
if (register == "clipboard" || register == "primary") { if register == "clipboard" || register == "primary" {
cmd.Room.StartSelecting(SelectCopy, register) cmd.Room.StartSelecting(SelectCopy, register)
} else { } else {
cmd.Reply("Usage: /copy [register], where register is either \"clipboard\" or \"primary\". Defaults to \"clipboard\".") cmd.Reply("Usage: /copy [register], where register is either \"clipboard\" or \"primary\". Defaults to \"clipboard\".")
@ -199,6 +200,85 @@ func cmdReact(cmd *Command) {
cmd.Room.StartSelecting(SelectReact, strings.Join(cmd.Args, " ")) cmd.Room.StartSelecting(SelectReact, strings.Join(cmd.Args, " "))
} }
func readRoomAlias(cmd *Command) (alias id.RoomAlias, err error) {
param := strings.Join(cmd.Args[1:], " ")
if strings.ContainsRune(param, ':') {
if param[0] != '#' {
return "", errors.New("Full aliases must start with #")
}
alias = id.RoomAlias(param)
} else {
_, homeserver, _ := cmd.Matrix.Client().UserID.Parse()
alias = id.NewRoomAlias(param, homeserver)
}
return
}
func cmdAlias(cmd *Command) {
if len(cmd.Args) < 2 {
cmd.Reply("Usage: /alias <add|remove> <localpart>")
return
}
alias, err := readRoomAlias(cmd)
if err != nil {
cmd.Reply(err.Error())
return
}
subcmd := strings.ToLower(cmd.Args[0])
switch subcmd {
case "add", "create":
cmdAddAlias(cmd, alias)
case "remove", "delete", "del", "rm":
cmdRemoveAlias(cmd, alias)
case "resolve", "get":
cmdResolveAlias(cmd, alias)
default:
cmd.Reply("Usage: /alias <add|remove|resolve> <localpart>")
}
}
func niceError(err error) string {
httpErr, ok := err.(mautrix.HTTPError)
if ok && httpErr.RespError != nil {
return httpErr.RespError.Error()
}
return err.Error()
}
func cmdAddAlias(cmd *Command, alias id.RoomAlias) {
_, err := cmd.Matrix.Client().CreateAlias(alias, cmd.Room.MxRoom().ID)
if err != nil {
cmd.Reply("Failed to create alias: %v", niceError(err))
} else {
cmd.Reply("Created alias %s", alias)
}
}
func cmdRemoveAlias(cmd *Command, alias id.RoomAlias) {
_, err := cmd.Matrix.Client().DeleteAlias(alias)
if err != nil {
cmd.Reply("Failed to delete alias: %v", niceError(err))
} else {
cmd.Reply("Deleted alias %s", alias)
}
}
func cmdResolveAlias(cmd *Command, alias id.RoomAlias) {
resp, err := cmd.Matrix.Client().ResolveAlias(alias)
if err != nil {
cmd.Reply("Failed to resolve alias: %v", niceError(err))
} else {
roomIDText := string(resp.RoomID)
if resp.RoomID == cmd.Room.MxRoom().ID {
roomIDText += " (this room)"
}
cmd.Reply("Alias %s points to room %s\nThere are %d servers in the room.", alias, roomIDText, len(resp.Servers))
}
}
func cmdTags(cmd *Command) { func cmdTags(cmd *Command) {
tags := cmd.Room.MxRoom().RawTags tags := cmd.Room.MxRoom().RawTags
if len(cmd.Args) > 0 && cmd.Args[0] == "--internal" { if len(cmd.Args) > 0 && cmd.Args[0] == "--internal" {
@ -384,6 +464,7 @@ Things: rooms, users, baremessages, images, typingnotif
/tag <tag> <priority> - Add the room to <tag>. /tag <tag> <priority> - Add the room to <tag>.
/untag <tag> - Remove the room from <tag>. /untag <tag> - Remove the room from <tag>.
/tags - List the tags the room is in. /tags - List the tags the room is in.
/alias <act> <name> - Add or remove local addresses.
/leave - Leave the current room. /leave - Leave the current room.
/kick <user id> [reason] - Kick a user. /kick <user id> [reason] - Kick a user.

View File

@ -93,8 +93,49 @@ func directParseEvent(matrix ifc.MatrixContainer, room *rooms.Room, evt *muksevt
} }
} }
func findAltAliasDifference(newList, oldList []string) (addedStr, removedStr tstring.TString) {
var addedList, removedList []tstring.TString
OldLoop:
for _, oldAlias := range oldList {
for _, newAlias := range newList {
if oldAlias == newAlias {
continue OldLoop
}
}
removedList = append(removedList, tstring.NewStyleTString(oldAlias, tcell.StyleDefault.Foreground(widget.GetHashColor(oldAlias)).Underline(true)))
}
NewLoop:
for _, newAlias := range newList {
for _, oldAlias := range oldList {
if newAlias == oldAlias {
continue NewLoop
}
}
addedList = append(addedList, tstring.NewStyleTString(newAlias, tcell.StyleDefault.Foreground(widget.GetHashColor(newAlias)).Underline(true)))
}
if len(addedList) == 1 {
addedStr = tstring.NewColorTString("added alternative address ", tcell.ColorGreen).AppendTString(addedList[0])
} else if len(addedList) != 0 {
addedStr = tstring.
Join(addedList[:len(addedList)-1], ", ").
PrependColor("added alternative addresses ", tcell.ColorGreen).
AppendColor(" and ", tcell.ColorGreen).
AppendTString(addedList[len(addedList)-1])
}
if len(removedList) == 1 {
removedStr = tstring.NewColorTString("removed alternative address ", tcell.ColorGreen).AppendTString(removedList[0])
} else if len(removedList) != 0 {
removedStr = tstring.
Join(removedList[:len(removedList)-1], ", ").
PrependColor("removed alternative addresses ", tcell.ColorGreen).
AppendColor(" and ", tcell.ColorGreen).
AppendTString(removedList[len(removedList)-1])
}
return
}
func ParseStateEvent(evt *muksevt.Event, displayname string) *UIMessage { func ParseStateEvent(evt *muksevt.Event, displayname string) *UIMessage {
text := tstring.NewColorTString(displayname, widget.GetHashColor(evt.Sender)) text := tstring.NewColorTString(displayname, widget.GetHashColor(evt.Sender)).Append(" ")
switch content := evt.Content.Parsed.(type) { switch content := evt.Content.Parsed.(type) {
case *event.TopicEventContent: case *event.TopicEventContent:
if len(content.Topic) == 0 { if len(content.Topic) == 0 {
@ -113,15 +154,33 @@ func ParseStateEvent(evt *muksevt.Event, displayname string) *UIMessage {
AppendColor(".", tcell.ColorGreen) AppendColor(".", tcell.ColorGreen)
} }
case *event.CanonicalAliasEventContent: case *event.CanonicalAliasEventContent:
if len(content.Alias) == 0 { _ = evt.Unsigned.PrevContent.ParseRaw(evt.Type)
text = text.AppendColor(" removed the main address of the room.", tcell.ColorGreen) prevContent := evt.Unsigned.PrevContent.AsCanonicalAlias()
debug.Printf("%+v -> %+v", prevContent, content)
if len(content.Alias) == 0 && len(prevContent.Alias) != 0 {
text = text.AppendColor("removed the main address of the room", tcell.ColorGreen)
} else if content.Alias != prevContent.Alias {
text = text.
AppendColor("changed the main address of the room to ", tcell.ColorGreen).
AppendStyle(string(content.Alias), tcell.StyleDefault.Underline(true))
} else { } else {
text = text.AppendColor(" changed the main address of the room to ", tcell.ColorGreen). added, removed := findAltAliasDifference(content.AltAliases, prevContent.AltAliases)
AppendStyle(string(content.Alias), tcell.StyleDefault.Underline(true)). if len(added) > 0 {
AppendColor(".", tcell.ColorGreen) if len(removed) > 0 {
text = text.
AppendTString(added).
AppendColor(" and ", tcell.ColorGreen).
AppendTString(removed)
} else {
text = text.AppendTString(added)
}
} else if len(removed) > 0 {
text = text.AppendTString(removed)
} else {
text = text.AppendColor("changed nothing", tcell.ColorGreen)
}
text = text.AppendColor(" for this room", tcell.ColorGreen)
} }
//case event.StateAliases:
// text = ParseAliasEvent(evt, displayname)
} }
return NewExpandedTextMessage(evt, displayname, text) return NewExpandedTextMessage(evt, displayname, text)
} }
@ -243,66 +302,3 @@ func ParseMembershipEvent(room *rooms.Room, evt *muksevt.Event) *UIMessage {
return NewExpandedTextMessage(evt, displayname, text) return NewExpandedTextMessage(evt, displayname, text)
} }
//func ParseAliasEvent(evt *muksevt.Event, displayname string) tstring.TString {
// var prevAliases []string
// if evt.Unsigned.PrevContent != nil {
// prevAliases = evt.Unsigned.PrevContent.Aliases
// }
// aliases := evt.Content.Aliases
// var added, removed []tstring.TString
//Outer1:
// for _, oldAlias := range prevAliases {
// for _, newAlias := range aliases {
// if oldAlias == newAlias {
// continue Outer1
// }
// }
// removed = append(removed, tstring.NewStyleTString(oldAlias, tcell.StyleDefault.Foreground(widget.GetHashColor(oldAlias)).Underline(true)))
// }
//Outer2:
// for _, newAlias := range aliases {
// for _, oldAlias := range prevAliases {
// if oldAlias == newAlias {
// continue Outer2
// }
// }
// added = append(added, tstring.NewStyleTString(newAlias, tcell.StyleDefault.Foreground(widget.GetHashColor(newAlias)).Underline(true)))
// }
// var addedStr, removedStr tstring.TString
// if len(added) == 1 {
// addedStr = added[0]
// } else if len(added) > 1 {
// addedStr = tstring.
// Join(added[:len(added)-1], ", ").
// Append(" and ").
// AppendTString(added[len(added)-1])
// }
// if len(removed) == 1 {
// removedStr = removed[0]
// } else if len(removed) > 1 {
// removedStr = tstring.
// Join(removed[:len(removed)-1], ", ").
// Append(" and ").
// AppendTString(removed[len(removed)-1])
// }
// text := tstring.NewBlankTString()
// if len(addedStr) > 0 && len(removedStr) > 0 {
// text = text.AppendColor(fmt.Sprintf("%s added ", displayname), tcell.ColorGreen).
// AppendTString(addedStr).
// AppendColor(" and removed ", tcell.ColorGreen).
// AppendTString(removedStr).
// AppendColor(" as addresses for this room.", tcell.ColorGreen)
// } else if len(addedStr) > 0 {
// text = text.AppendColor(fmt.Sprintf("%s added ", displayname), tcell.ColorGreen).
// AppendTString(addedStr).
// AppendColor(" as addresses for this room.", tcell.ColorGreen)
// } else if len(removedStr) > 0 {
// text = text.AppendColor(fmt.Sprintf("%s removed ", displayname), tcell.ColorGreen).
// AppendTString(removedStr).
// AppendColor(" as addresses for this room.", tcell.ColorGreen)
// } else {
// return nil
// }
// return text
//}