From bc7ef238deb41f80e8be25a8898ac7d2f117fce5 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Thu, 28 Nov 2019 20:24:09 +0100 Subject: [PATCH 01/15] minor formatting fixes --- main.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 67f2a06..e869f2d 100644 --- a/main.go +++ b/main.go @@ -466,16 +466,18 @@ func formatMessageBody(body string) StyledString { message := config.Colors.Message.Body.stylize(body) message = colorReplaceMentionMe(message) - message = message.colorRegex(`_[^_]*_`, config.Colors.Message.Body.withItalic()) - message = message.colorRegex(`~[^~]*~`, config.Colors.Message.Body.withStrikethrough()) + // TODO when gocui actually fixes there shit with formatting, then un comment these lines + // message = message.colorRegex(`_[^_]*_`, config.Colors.Message.Body.withItalic()) + // message = message.colorRegex(`~[^~]*~`, config.Colors.Message.Body.withStrikethrough()) message = message.colorRegex(`@[\w_]*([\.#][\w_]+)*`, config.Colors.Message.LinkKeybase) // TODO change how bold, italic etc works, so it uses boldOn boldOff ([1m and [22m) message = message.colorRegex(`\*[^\*]*\*`, config.Colors.Message.Body.withBold()) - message = message.colorRegex(">.*$", config.Colors.Message.Quote) + message = message.colorRegex("^>.*$", config.Colors.Message.Quote) message = message.regexReplaceFunc("```(.*\n)*```", func(match string) string { maxWidth, _ := g.Size() output := "\n" match = strings.Replace(strings.Replace(match, "```", "", -1), "\t", " ", -1) + match = removeFormatting(match) lines := strings.Split(match, "\n") for _, line := range lines { maxLineLength := maxWidth/2 + maxWidth/3 - 2 From 023f22a1ea232bb0dbe08b4428b4992a39cc2fb7 Mon Sep 17 00:00:00 2001 From: Casper Weiss Bang Date: Wed, 13 Nov 2019 20:48:14 +0100 Subject: [PATCH 02/15] More User Info Added: - `/inspect` (`/id`) - `/follow` - `/unfollow` --- cmdFollow.go | 34 ++++++++++++ cmdInspect.go | 135 +++++++++++++++++++++++++++++++++++++++++++++++ cmdUnfollow.go | 33 ++++++++++++ cmdWall.go | 4 +- defaultConfig.go | 88 ++++++++++++++++-------------- kbtui.toml | 88 ++++++++++++++++-------------- main.go | 43 ++++++++------- types.go | 23 ++++---- userTags.go | 58 ++++++++++++++++++++ 9 files changed, 399 insertions(+), 107 deletions(-) create mode 100644 cmdFollow.go create mode 100644 cmdInspect.go create mode 100644 cmdUnfollow.go create mode 100644 userTags.go diff --git a/cmdFollow.go b/cmdFollow.go new file mode 100644 index 0000000..ef2b7e2 --- /dev/null +++ b/cmdFollow.go @@ -0,0 +1,34 @@ +// +build !rm_basic_commands allcommands followcmd + +package main + +import ( + "fmt" +) + +func init() { + command := Command{ + Cmd: []string{"follow"}, + Description: "$username - Follows the given user", + Help: "", + Exec: cmdFollow, + } + RegisterCommand(command) +} + +func cmdFollow(cmd []string) { + if len(cmd) == 2 { + go follow(cmd[1]) + } else { + printFollowHelp() + } +} +func follow(username string) { + k.Exec("follow", username, "-y") + printInfoF("Now follows $TEXT", config.Colors.Message.LinkKeybase.stylize(username)) + followedInSteps[username] = 1 +} + +func printFollowHelp() { + printInfo(fmt.Sprintf("To follow a user use %sfollow ", config.Basics.CmdPrefix)) +} diff --git a/cmdInspect.go b/cmdInspect.go new file mode 100644 index 0000000..5b01c56 --- /dev/null +++ b/cmdInspect.go @@ -0,0 +1,135 @@ +// +build !rm_basic_commands allcommands inspectcmd + +package main + +import ( + "fmt" + "regexp" + "samhofi.us/x/keybase" + "strconv" + "strings" +) + +func init() { + command := Command{ + Cmd: []string{"inspect", "id"}, + Description: "$identifier - shows info about $identifier ($identifier is either username, messageId or team)", + Help: "", + Exec: cmdInspect, + } + + RegisterCommand(command) +} + +func cmdInspect(cmd []string) { + if len(cmd) == 2 { + regexIsNumeric := regexp.MustCompile(`^\d+$`) + if regexIsNumeric.MatchString(cmd[1]) { + // Then it must be a message id + id, _ := strconv.Atoi(cmd[1]) + go printMessage(id) + + } else { + go printUser(strings.ReplaceAll(cmd[1], "@", "")) + } + + } else { + printInfo(fmt.Sprintf("To inspect something use %sid ", config.Basics.CmdPrefix)) + } + +} +func printMessage(id int) { + chat := k.NewChat(channel) + messages, err := chat.ReadMessage(id) + if err == nil { + var response StyledString + if messages != nil && len((*messages).Result.Messages) > 0 { + message := (*messages).Result.Messages[0].Msg + var apiCast keybase.ChatAPI + apiCast.Msg = &message + response = formatOutput(apiCast) + } else { + response = config.Colors.Feed.Error.stylize("message not found") + } + printToView("Chat", response.string()) + } +} + +func formatProofs(userLookup keybase.UserAPI) StyledString { + messageColor := config.Colors.Message + message := basicStyle.stylize("") + for _, proof := range userLookup.Them[0].ProofsSummary.All { + style := config.Colors.Feed.Success + if proof.State != 1 { + style = config.Colors.Feed.Error + } + proofString := style.stylize("Proof [$NAME@$SITE]: $URL\n") + proofString = proofString.replace("$NAME", messageColor.SenderDefault.stylize(proof.Nametag)) + proofString = proofString.replace("$SITE", messageColor.SenderDevice.stylize(proof.ProofType)) + proofString = proofString.replace("$URL", messageColor.LinkURL.stylize(proof.HumanURL)) + message = message.append(proofString) + } + return message.appendString("\n") +} +func formatProfile(userLookup keybase.UserAPI) StyledString { + messageColor := config.Colors.Message + user := userLookup.Them[0] + profileText := messageColor.Body.stylize("Name: $FNAME\nLocation: $LOC\nBio: $BIO\n") + profileText = profileText.replaceString("$FNAME", user.Profile.FullName) + profileText = profileText.replaceString("$LOC", user.Profile.Location) + profileText = profileText.replaceString("$BIO", user.Profile.Bio) + + return profileText +} + +func formatFollowState(userLookup keybase.UserAPI) StyledString { + username := userLookup.Them[0].Basics.Username + followSteps := followedInSteps[username] + if followSteps == 1 { + return config.Colors.Feed.Success.stylize("\n\n") + } else if followSteps > 1 { + var steps []string + for head := username; head != ""; head = trustTreeParent[head] { + steps = append(steps, fmt.Sprintf("[%s]", head)) + } + trustLine := fmt.Sprintf("Indirect follow: <%s>\n\n", strings.Join(steps, " Followed by ")) + return config.Colors.Message.Body.stylize(trustLine) + } + + return basicStyle.stylize("") + +} + +func formatFollowerAndFollowedList(username string, listType string) StyledString { + messageColor := config.Colors.Message + response := basicStyle.stylize("") + bytes, _ := k.Exec("list-"+listType, username) + bigString := string(bytes) + lines := strings.Split(bigString, "\n") + response = response.appendString(fmt.Sprintf("%s (%d): ", listType, len(lines)-1)) + for i, user := range lines[:len(lines)-1] { + if i != 0 { + response = response.appendString(", ") + } + response = response.append(messageColor.LinkKeybase.stylize(user)) + response = response.append(getUserFlags(user)) + } + return response.appendString("\n\n") +} + +func printUser(username string) { + messageColor := config.Colors.Message + + userLookup, _ := k.UserLookup(username) + + response := messageColor.Header.stylize("[Inspecting `$USER`]\n") + response = response.replace("$USER", messageColor.SenderDefault.stylize(username)) + response = response.append(formatProfile(userLookup)) + response = response.append(formatFollowState(userLookup)) + + response = response.append(formatProofs(userLookup)) + response = response.append(formatFollowerAndFollowedList(username, "followers")) + response = response.append(formatFollowerAndFollowedList(username, "following")) + + printToView("Chat", response.string()) +} diff --git a/cmdUnfollow.go b/cmdUnfollow.go new file mode 100644 index 0000000..241e545 --- /dev/null +++ b/cmdUnfollow.go @@ -0,0 +1,33 @@ +// +build !rm_basic_commands allcommands followcmd + +package main + +import ( + "fmt" +) + +func init() { + command := Command{ + Cmd: []string{"unfollow"}, + Description: "$username - Unfollows the given user", + Help: "", + Exec: cmdUnfollow, + } + RegisterCommand(command) +} + +func cmdUnfollow(cmd []string) { + if len(cmd) == 2 { + go unfollow(cmd[1]) + } else { + printUnfollowHelp() + } +} +func unfollow(username string) { + k.Exec("unfollow", username) + printInfoF("Now unfollows $TEXT", config.Colors.Message.LinkKeybase.stylize(username)) +} + +func printUnfollowHelp() { + printInfo(fmt.Sprintf("To unfollow a user use %sunfollow ", config.Basics.CmdPrefix)) +} diff --git a/cmdWall.go b/cmdWall.go index 51f27b4..168729b 100644 --- a/cmdWall.go +++ b/cmdWall.go @@ -81,7 +81,7 @@ func cmdPopulateWall(cmd []string) { apiCast.Msg = &api.Result.Messages[i].Msg result[apiCast.Msg.SentAt] = apiCast newMessage := formatOutput(apiCast) - printMe = append(printMe, newMessage) + printMe = append(printMe, newMessage.string()) } } @@ -96,7 +96,7 @@ func cmdPopulateWall(cmd []string) { sort.Ints(keys) time.Sleep(1 * time.Millisecond) for _, k := range keys { - actuallyPrintMe += formatOutput(result[k]) + "\n" + actuallyPrintMe += formatOutput(result[k]).string() + "\n" } printToView("Chat", fmt.Sprintf("\n\n\n%s\nYour wall query took %s\n\n", actuallyPrintMe, time.Since(start))) } diff --git a/defaultConfig.go b/defaultConfig.go index 0471703..f017e9d 100644 --- a/defaultConfig.go +++ b/defaultConfig.go @@ -11,9 +11,9 @@ cmd_prefix = "/" [formatting] # BASH-like PS1 variable equivalent -output_format = "┌──[$USER@$DEVICE] [$ID] [$DATE - $TIME]\n└╼ $MSG" -output_stream_format = "┌──[$USER@$DEVICE] [$ID] [$DATE - $TIME]\n└╼ $MSG" -output_mention_format = "┌──[$USER@$DEVICE] [$ID] [$DATE - $TIME]\n└╼ $MSG" +output_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" +output_stream_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" +output_mention_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" pm_format = "PM from $USER@$DEVICE: $MSG" # 02 = Day, Jan = Month, 06 = Year @@ -22,6 +22,8 @@ date_format = "02Jan06" # 15 = hours, 04 = minutes, 05 = seconds time_format = "15:04" +icon_following_user = "[*]" +icon_indirect_following_user = "[?]" [colors] [colors.channels] @@ -34,44 +36,52 @@ time_format = "15:04" foreground = "green" italic = true - [colors.message] - [colors.message.body] - foreground = "normal" - [colors.message.header] - foreground = "grey" - bold = true - [colors.message.mention] - foreground = "green" - italic = true - bold = true - [colors.message.id] - foreground = "yellow" - [colors.message.time] - foreground = "magenta" - [colors.message.sender_default] - foreground = "cyan" - bold = true - [colors.message.sender_device] - foreground = "cyan" - [colors.message.attachment] - foreground = "red" - [colors.message.link_url] - foreground = "yellow" - [colors.message.link_keybase] - foreground = "yellow" - [colors.message.reaction] - foreground = "magenta" - bold = true + [colors.message] + [colors.message.body] + foreground = "normal" + [colors.message.header] + foreground = "grey" + bold = true + [colors.message.mention] + foreground = "green" + italic = true + bold = true + [colors.message.id] + foreground = "yellow" + bold = true + [colors.message.time] + foreground = "magenta" + bold = true + [colors.message.sender_default] + foreground = "cyan" + bold = true + [colors.message.sender_device] + foreground = "cyan" + bold = true + [colors.message.sender_tags] + foreground = "yellow" + [colors.message.attachment] + foreground = "red" + [colors.message.link_url] + foreground = "yellow" + [colors.message.link_keybase] + foreground = "cyan" + [colors.message.reaction] + foreground = "magenta" + bold = true [colors.message.quote] foreground = "green" - [colors.message.code] - foreground = "green" - background = "grey" - [colors.feed] - [colors.feed.basic] - foreground = "grey" - [colors.feed.error] - foreground = "red" + [colors.message.code] + foreground = "cyan" + background = "grey" + + [colors.feed] + [colors.feed.basic] + foreground = "grey" + [colors.feed.error] + foreground = "red" + [colors.feed.success] + foreground = "green" [colors.feed.file] foreground = "yellow" ` diff --git a/kbtui.toml b/kbtui.toml index fa98691..871de8f 100644 --- a/kbtui.toml +++ b/kbtui.toml @@ -8,9 +8,9 @@ cmd_prefix = "/" [formatting] # BASH-like PS1 variable equivalent -output_format = "┌──[$USER@$DEVICE] [$ID] [$DATE - $TIME]\n└╼ $MSG" -output_stream_format = "┌──[$USER@$DEVICE] [$ID] [$DATE - $TIME]\n└╼ $MSG" -output_mention_format = "┌──[$USER@$DEVICE] [$ID] [$DATE - $TIME]\n└╼ $MSG" +output_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" +output_stream_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" +output_mention_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" pm_format = "PM from $USER@$DEVICE: $MSG" # 02 = Day, Jan = Month, 06 = Year @@ -19,6 +19,8 @@ date_format = "02Jan06" # 15 = hours, 04 = minutes, 05 = seconds time_format = "15:04" +icon_following_user = "[*]" +icon_indirect_following_user = "[?]" [colors] [colors.channels] @@ -31,43 +33,51 @@ time_format = "15:04" foreground = "green" italic = true - [colors.message] - [colors.message.body] - foreground = "normal" - [colors.message.header] - foreground = "grey" - bold = true - [colors.message.mention] - foreground = "green" - italic = true - bold = true - [colors.message.id] - foreground = "yellow" - [colors.message.time] - foreground = "magenta" - [colors.message.sender_default] - foreground = "cyan" - bold = true - [colors.message.sender_device] - foreground = "cyan" - [colors.message.attachment] - foreground = "red" - [colors.message.link_url] - foreground = "yellow" - [colors.message.link_keybase] - foreground = "yellow" - [colors.message.reaction] - foreground = "magenta" - bold = true + [colors.message] + [colors.message.body] + foreground = "normal" + [colors.message.header] + foreground = "grey" + bold = true + [colors.message.mention] + foreground = "green" + italic = true + bold = true + [colors.message.id] + foreground = "yellow" + bold = true + [colors.message.time] + foreground = "magenta" + bold = true + [colors.message.sender_default] + foreground = "cyan" + bold = true + [colors.message.sender_device] + foreground = "cyan" + bold = true + [colors.message.sender_tags] + foreground = "yellow" + [colors.message.attachment] + foreground = "red" + [colors.message.link_url] + foreground = "yellow" + [colors.message.link_keybase] + foreground = "cyan" + [colors.message.reaction] + foreground = "magenta" + bold = true [colors.message.quote] foreground = "green" - [colors.message.code] - foreground = "green" - background = "grey" - [colors.feed] - [colors.feed.basic] - foreground = "grey" - [colors.feed.error] - foreground = "red" + [colors.message.code] + foreground = "cyan" + background = "grey" + + [colors.feed] + [colors.feed.basic] + foreground = "grey" + [colors.feed.error] + foreground = "red" + [colors.feed.success] + foreground = "green" [colors.feed.file] foreground = "yellow" diff --git a/main.go b/main.go index 67f2a06..16fa539 100644 --- a/main.go +++ b/main.go @@ -49,6 +49,8 @@ func main() { RunCommand(os.Args...) } + // Create map of users following users, to populate flags + go generateFollowersList() fmt.Println("initKeybindings") if err := initKeybindings(); err != nil { fmt.Printf("%+v", err) @@ -405,7 +407,7 @@ func populateChat() { } var apiCast keybase.ChatAPI apiCast.Msg = &message.Msg - newMessage := formatOutput(apiCast) + newMessage := formatOutput(apiCast).string() printMe = append(printMe, newMessage) } } @@ -424,6 +426,7 @@ func populateList() { log.Printf("%+v", err) } else { clearView("List") + var textBase = config.Colors.Channels.Basic.stylize("") var recentPMs = textBase.append(config.Colors.Channels.Header.stylize("---[PMs]---\n")) var recentPMsCount = 0 @@ -465,10 +468,10 @@ func populateList() { func formatMessageBody(body string) StyledString { message := config.Colors.Message.Body.stylize(body) + message = message.colorRegex(`@[\w_]*([\.#][\w_]+)*`, config.Colors.Message.LinkKeybase) message = colorReplaceMentionMe(message) message = message.colorRegex(`_[^_]*_`, config.Colors.Message.Body.withItalic()) message = message.colorRegex(`~[^~]*~`, config.Colors.Message.Body.withStrikethrough()) - message = message.colorRegex(`@[\w_]*([\.#][\w_]+)*`, config.Colors.Message.LinkKeybase) // TODO change how bold, italic etc works, so it uses boldOn boldOff ([1m and [22m) message = message.colorRegex(`\*[^\*]*\*`, config.Colors.Message.Body.withBold()) message = message.colorRegex(">.*$", config.Colors.Message.Quote) @@ -485,6 +488,7 @@ func formatMessageBody(body string) StyledString { } output += line + strings.Repeat(" ", spaces) + "\n" } + // TODO stylize should remove formatting - in general everything should return config.Colors.Message.Code.stylize(output).stringFollowedByStyle(message.style) }) message = message.colorRegex("`[^`]*`", config.Colors.Message.Code) @@ -515,43 +519,46 @@ func cleanChannelName(c string) string { } func formatMessage(api keybase.ChatAPI, formatString string) StyledString { + msg := api.Msg ret := config.Colors.Message.Header.stylize("") - msgType := api.Msg.Content.Type + msgType := msg.Content.Type switch msgType { case "text", "attachment": ret = config.Colors.Message.Header.stylize(formatString) - tm := time.Unix(int64(api.Msg.SentAt), 0) - var msg = formatMessageBody(api.Msg.Content.Text.Body) + tm := time.Unix(int64(msg.SentAt), 0) + var body = formatMessageBody(msg.Content.Text.Body) if msgType == "attachment" { - msg = config.Colors.Message.Body.stylize("$TITLE\n$FILE") - attachment := api.Msg.Content.Attachment - msg = msg.replaceString("$TITLE", attachment.Object.Title) - msg = msg.replace("$FILE", config.Colors.Message.Attachment.stylize(fmt.Sprintf("[Attachment: %s]", attachment.Object.Filename))) + body = config.Colors.Message.Body.stylize("$TITLE\n$FILE") + attachment := msg.Content.Attachment + body = body.replaceString("$TITLE", attachment.Object.Title) + body = body.replace("$FILE", config.Colors.Message.Attachment.stylize(fmt.Sprintf("[Attachment: %s]", attachment.Object.Filename))) } - user := colorUsername(api.Msg.Sender.Username) - device := config.Colors.Message.SenderDevice.stylize(api.Msg.Sender.DeviceName) - msgID := config.Colors.Message.ID.stylize(fmt.Sprintf("%d", api.Msg.ID)) + user := colorUsername(msg.Sender.Username) + device := config.Colors.Message.SenderDevice.stylize(msg.Sender.DeviceName) + msgID := config.Colors.Message.ID.stylize(fmt.Sprintf("%d", msg.ID)) date := config.Colors.Message.Time.stylize(tm.Format(config.Formatting.DateFormat)) msgTime := config.Colors.Message.Time.stylize(tm.Format(config.Formatting.TimeFormat)) - channelName := config.Colors.Message.ID.stylize(fmt.Sprintf("@%s#%s", api.Msg.Channel.Name, api.Msg.Channel.TopicName)) - ret = ret.replace("$MSG", msg) + channelName := config.Colors.Message.ID.stylize(fmt.Sprintf("@%s#%s", msg.Channel.Name, msg.Channel.TopicName)) + ret = ret.replace("$MSG", body) ret = ret.replace("$USER", user) ret = ret.replace("$DEVICE", device) ret = ret.replace("$ID", msgID) ret = ret.replace("$TIME", msgTime) ret = ret.replace("$DATE", date) ret = ret.replace("$TEAM", channelName) + ret = ret.replace("$TAGS", getUserFlags(api.Msg.Sender.Username)) } return ret } -func formatOutput(api keybase.ChatAPI) string { + +func formatOutput(api keybase.ChatAPI) StyledString { format := config.Formatting.OutputFormat if stream { format = config.Formatting.OutputStreamFormat } - return formatMessage(api, format).string() + return formatMessage(api, format) } // End formatting @@ -594,7 +601,7 @@ func handleMessage(api keybase.ChatAPI) { } if api.Msg.Channel.MembersType == channel.MembersType && cleanChannelName(api.Msg.Channel.Name) == channel.Name { if channel.MembersType == keybase.USER || channel.MembersType == keybase.TEAM && channel.TopicName == api.Msg.Channel.TopicName { - printToView("Chat", formatOutput(api)) + printToView("Chat", formatOutput(api).string()) chat := k.NewChat(channel) lastMessage.ID = api.Msg.ID chat.Read(api.Msg.ID) @@ -602,7 +609,7 @@ func handleMessage(api keybase.ChatAPI) { } } else { if api.Msg.Channel.MembersType == keybase.TEAM { - printToView("Chat", formatOutput(api)) + printToView("Chat", formatOutput(api).string()) } else { printToView("Chat", formatMessage(api, config.Formatting.PMFormat).string()) } diff --git a/types.go b/types.go index 1d68216..676ef97 100644 --- a/types.go +++ b/types.go @@ -36,12 +36,14 @@ type Basics struct { // Formatting holds the 'formatting' section of the config file type Formatting struct { - OutputFormat string `toml:"output_format"` - OutputStreamFormat string `toml:"output_stream_format"` - OutputMentionFormat string `toml:"output_mention_format"` - PMFormat string `toml:"pm_format"` - DateFormat string `toml:"date_format"` - TimeFormat string `toml:"time_format"` + OutputFormat string `toml:"output_format"` + OutputStreamFormat string `toml:"output_stream_format"` + OutputMentionFormat string `toml:"output_mention_format"` + PMFormat string `toml:"pm_format"` + DateFormat string `toml:"date_format"` + TimeFormat string `toml:"time_format"` + IconFollowingUser string `toml:"icon_following_user"` + IconIndirectFollowUser string `toml:"icon_indirect_following_user"` } // Colors holds the 'colors' section of the config file @@ -75,9 +77,11 @@ type Message struct { Header Style `toml:"header"` Mention Style `toml:"mention"` ID Style `toml:"id"` + Tags Style `toml:"tags"` Time Style `toml:"time"` SenderDefault Style `toml:"sender_default"` SenderDevice Style `toml:"sender_device"` + SenderTags Style `toml:"sender_tags"` Attachment Style `toml:"attachment"` LinkURL Style `toml:"link_url"` LinkKeybase Style `toml:"link_keybase"` @@ -88,7 +92,8 @@ type Message struct { // Feed holds the style information for various elements of the feed window type Feed struct { - Basic Style `toml:"basic"` - Error Style `toml:"error"` - File Style `toml:"file"` + Basic Style `toml:"basic"` + Error Style `toml:"error"` + File Style `toml:"file"` + Success Style `toml:"success"` } diff --git a/userTags.go b/userTags.go new file mode 100644 index 0000000..cf2dca0 --- /dev/null +++ b/userTags.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "strings" +) + +var followedInSteps = make(map[string]int) +var trustTreeParent = make(map[string]string) + +func clearFlagCache() { + followedInSteps = make(map[string]int) + trustTreeParent = make(map[string]string) +} + +var maxDepth = 4 + +func generateFollowersList() { + // Does a BFS of followedInSteps + queue := []string{k.Username} + printInfo("Generating Tree of Trust...") + lastDepth := 1 + for len(queue) > 0 { + head := queue[0] + queue = queue[1:] + depth := followedInSteps[head] + 1 + if depth > maxDepth { + continue + } + if depth > lastDepth { + printInfo(fmt.Sprintf("Trust generated at Level #%d", depth-1)) + lastDepth = depth + } + + bytes, _ := k.Exec("list-following", head) + bigString := string(bytes) + following := strings.Split(bigString, "\n") + for _, user := range following { + if followedInSteps[user] == 0 && user != k.Username { + followedInSteps[user] = depth + trustTreeParent[user] = head + queue = append(queue, user) + } + } + } + printInfo(fmt.Sprintf("Trust-level estabilished for %d users", len(followedInSteps))) +} + +func getUserFlags(username string) StyledString { + tags := "" + followDepth := followedInSteps[username] + if followDepth == 1 { + tags += fmt.Sprintf(" %s", config.Formatting.IconFollowingUser) + } else if followDepth > 1 { + tags += fmt.Sprintf(" %s%d", config.Formatting.IconIndirectFollowUser, followDepth-1) + } + return config.Colors.Message.SenderTags.stylize(tags) +} From cd79a10528d293e420dba2fc0f9dc992a03468c2 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Mon, 2 Dec 2019 18:02:29 -0500 Subject: [PATCH 03/15] Fix ReplaceAll so that standard repo go can compile --- cmdInspect.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmdInspect.go b/cmdInspect.go index 5b01c56..060ccd5 100644 --- a/cmdInspect.go +++ b/cmdInspect.go @@ -30,7 +30,7 @@ func cmdInspect(cmd []string) { go printMessage(id) } else { - go printUser(strings.ReplaceAll(cmd[1], "@", "")) + go printUser(strings.Replace(cmd[1], "@", "", -1)) } } else { From 84e5beada4d169ad7385ac7b9c55d29578d57b4e Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Tue, 3 Dec 2019 21:22:16 +0100 Subject: [PATCH 04/15] "~/" does not work as hoped for i.e. it is expanded only by a shell, not a system call, so ~/.config/kbtui.toml was never used. --- cmdConfig.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cmdConfig.go b/cmdConfig.go index a32373d..7b7b512 100644 --- a/cmdConfig.go +++ b/cmdConfig.go @@ -50,7 +50,7 @@ func cmdConfig(cmd []string) { func readConfig(filepath ...string) (*Config, error) { var result = new(Config) - var configFile string + var configFile, path string var env bool // Load default config first, this way any values missing from the provided config file will remain the default value @@ -61,8 +61,13 @@ func readConfig(filepath ...string) (*Config, error) { case 0: configFile, env = os.LookupEnv("KBTUI_CFG") if !env { - configFile = "~/.config/kbtui.toml" - if _, err := os.Stat(configFile); os.IsNotExist(err) { + path, env = os.LookupEnv("HOME") + if env { + configFile = path + "/.config/kbtui.toml" + if _, err := os.Stat(configFile); os.IsNotExist(err) { + configFile = "kbtui.toml" + } + } else { configFile = "kbtui.toml" } } From db082787809b058932f3c86d6d88d89d122afe43 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Fri, 6 Dec 2019 11:24:28 -0500 Subject: [PATCH 05/15] Remove auto-RAMRAPE and instead have it triggered on command --- main.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/main.go b/main.go index 1a7cebb..e1f14b5 100644 --- a/main.go +++ b/main.go @@ -49,8 +49,6 @@ func main() { RunCommand(os.Args...) } - // Create map of users following users, to populate flags - go generateFollowersList() fmt.Println("initKeybindings") if err := initKeybindings(); err != nil { fmt.Printf("%+v", err) From 9a71d50ab786895907f6e44e604be5472519f9c5 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Fri, 6 Dec 2019 11:29:47 -0500 Subject: [PATCH 06/15] Remove unused import --- cmdTags.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 cmdTags.go diff --git a/cmdTags.go b/cmdTags.go new file mode 100644 index 0000000..095df0c --- /dev/null +++ b/cmdTags.go @@ -0,0 +1,19 @@ +// +ignore +// +build allcommands tagscmd + +package main + +func init() { + command := Command{ + Cmd: []string{"tags", "map"}, + Description: "$- Create map of users following users, to populate $TAGS", + Help: "", + Exec: cmdTags, + } + + RegisterCommand(command) +} + +func cmdTags(cmd []string) { + go generateFollowersList() +} From 0a4c2614a89e00f67150dc7319f083797d580ac5 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Wed, 18 Dec 2019 13:35:14 -0500 Subject: [PATCH 07/15] Fix multiline code to have newlines for mkbot gameroom etc --- main.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index e1f14b5..005e20c 100644 --- a/main.go +++ b/main.go @@ -464,6 +464,7 @@ func populateList() { // Formatting func formatMessageBody(body string) StyledString { + body = strings.Replace(body, "```", "\n\n", -1) message := config.Colors.Message.Body.stylize(body) message = message.colorRegex(`@[\w_]*([\.#][\w_]+)*`, config.Colors.Message.LinkKeybase) @@ -476,10 +477,10 @@ func formatMessageBody(body string) StyledString { // TODO change how bold, italic etc works, so it uses boldOn boldOff ([1m and [22m) message = message.colorRegex(`\*[^\*]*\*`, config.Colors.Message.Body.withBold()) message = message.colorRegex("^>.*$", config.Colors.Message.Quote) - message = message.regexReplaceFunc("```(.*\n)*```", func(match string) string { + message = message.regexReplaceFunc("\n(.*\n)*\n", func(match string) string { maxWidth, _ := g.Size() - output := "\n" - match = strings.Replace(strings.Replace(match, "```", "", -1), "\t", " ", -1) + output := "" + match = strings.Replace(strings.Replace(match, "```", "\n\n", -1), "\t", " ", -1) match = removeFormatting(match) lines := strings.Split(match, "\n") for _, line := range lines { @@ -491,6 +492,7 @@ func formatMessageBody(body string) StyledString { output += line + strings.Repeat(" ", spaces) + "\n" } // TODO stylize should remove formatting - in general everything should + return config.Colors.Message.Code.stylize(output).stringFollowedByStyle(message.style) }) message = message.colorRegex("`[^`]*`", config.Colors.Message.Code) From ff120c036610f90d3054a785ac9cd475be868cd0 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Wed, 18 Dec 2019 13:39:00 -0500 Subject: [PATCH 08/15] Create go.yml --- .github/workflows/go.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/go.yml diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..0e4ac54 --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,28 @@ +name: Go +on: [push] +jobs: + + build: + name: Build + runs-on: ubuntu-latest + steps: + + - name: Set up Go 1.13 + uses: actions/setup-go@v1 + with: + go-version: 1.13 + id: go + + - name: Check out code into the Go module directory + uses: actions/checkout@v1 + + - name: Get dependencies + run: | + go get -v -t -d ./... + if [ -f Gopkg.toml ]; then + curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh + dep ensure + fi + + - name: Build + run: go run build.go buildbeta From 8abde78bf796db3a08e01675d54347cc0e792025 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Wed, 18 Dec 2019 13:43:03 -0500 Subject: [PATCH 09/15] Update go.yml --- .github/workflows/go.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 0e4ac54..d6b5cef 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -19,6 +19,7 @@ jobs: - name: Get dependencies run: | go get -v -t -d ./... + go get github.com/magefile/mage if [ -f Gopkg.toml ]; then curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh dep ensure From 66e2552a7e5b5b59126be2b3d74384cc8e48e273 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Thu, 19 Dec 2019 12:19:34 -0500 Subject: [PATCH 10/15] Don't error out on api errors --- main.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main.go b/main.go index 005e20c..6ba2163 100644 --- a/main.go +++ b/main.go @@ -569,6 +569,10 @@ func formatOutput(api keybase.ChatAPI) StyledString { // Input handling func handleMessage(api keybase.ChatAPI) { + if api.Error != nil { + printError(fmt.Sprintf("%+v", api.Error)) + return + } if _, ok := typeCommands[api.Msg.Content.Type]; ok { if api.Msg.Channel.MembersType == channel.MembersType && cleanChannelName(api.Msg.Channel.Name) == channel.Name { if channel.MembersType == keybase.TEAM && channel.TopicName != api.Msg.Channel.TopicName { From fc48ad5c4a0534d1815b7c46aeaaa0c80ebe169f Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Fri, 20 Dec 2019 08:44:51 -0500 Subject: [PATCH 11/15] Add replies to messages --- kbtui.toml | 2 +- main.go | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/kbtui.toml b/kbtui.toml index 871de8f..260ce02 100644 --- a/kbtui.toml +++ b/kbtui.toml @@ -8,7 +8,7 @@ cmd_prefix = "/" [formatting] # BASH-like PS1 variable equivalent -output_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" +output_format = "$REPL┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" output_stream_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" output_mention_format = "┌──[$USER@$DEVICE$TAGS] [$ID] [$DATE - $TIME]\n└╼ $MSG" pm_format = "PM from $USER@$DEVICE: $MSG" diff --git a/main.go b/main.go index 6ba2163..e3dcbc1 100644 --- a/main.go +++ b/main.go @@ -537,14 +537,29 @@ func formatMessage(api keybase.ChatAPI, formatString string) StyledString { body = body.replaceString("$TITLE", attachment.Object.Title) body = body.replace("$FILE", config.Colors.Message.Attachment.stylize(fmt.Sprintf("[Attachment: %s]", attachment.Object.Filename))) } + reply := "" + if msg.Content.Text.ReplyTo != 0 { + chat := k.NewChat(channel) + replyMsg, replErr := chat.ReadMessage(msg.Content.Text.ReplyTo) + if replErr == nil { + replyUser := replyMsg.Result.Messages[0].Msg.Sender.Username + replyBody := "" + if replyMsg.Result.Messages[0].Msg.Content.Type == "text" { + replyBody = replyMsg.Result.Messages[0].Msg.Content.Text.Body + } + reply = fmt.Sprintf("\nReplyTo> %s: %s\n", replyUser, replyBody) + } + } + //printInfo(fmt.Sprintf("%d", msg.Content.Text.ReplyTo)) user := colorUsername(msg.Sender.Username) device := config.Colors.Message.SenderDevice.stylize(msg.Sender.DeviceName) msgID := config.Colors.Message.ID.stylize(fmt.Sprintf("%d", msg.ID)) date := config.Colors.Message.Time.stylize(tm.Format(config.Formatting.DateFormat)) msgTime := config.Colors.Message.Time.stylize(tm.Format(config.Formatting.TimeFormat)) - + c0ck := config.Colors.Message.Quote.stylize(reply) channelName := config.Colors.Message.ID.stylize(fmt.Sprintf("@%s#%s", msg.Channel.Name, msg.Channel.TopicName)) + ret = ret.replace("$REPL", c0ck) ret = ret.replace("$MSG", body) ret = ret.replace("$USER", user) ret = ret.replace("$DEVICE", device) @@ -569,8 +584,8 @@ func formatOutput(api keybase.ChatAPI) StyledString { // Input handling func handleMessage(api keybase.ChatAPI) { - if api.Error != nil { - printError(fmt.Sprintf("%+v", api.Error)) + if api.ErrorListen != nil { + printError(fmt.Sprintf("%+v", api.ErrorListen)) return } if _, ok := typeCommands[api.Msg.Content.Type]; ok { From 67fc7c6e5df5ab89d1d73ded24087c0160c6e8e4 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Fri, 20 Dec 2019 09:15:55 -0500 Subject: [PATCH 12/15] Check if api.Result is nil before reading it in populateChat() --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index e3dcbc1..d145dce 100644 --- a/main.go +++ b/main.go @@ -376,7 +376,7 @@ func populateChat() { chat := k.NewChat(channel) maxX, _ := g.Size() api, err := chat.Read(maxX / 2) - if err != nil { + if err != nil || api.Result == nil { for _, testChan := range channels { if channel.Name == testChan.Name { channel = testChan From f55270f4233c60d90f38d347d1150006221668ee Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Fri, 20 Dec 2019 10:59:21 -0500 Subject: [PATCH 13/15] Rudi9719 workflow (#53) * Update go.yml * Update go.yml --- .github/workflows/go.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index d6b5cef..b483f40 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -27,3 +27,8 @@ jobs: - name: Build run: go run build.go buildbeta + - name: Upload Artifact + uses: actions/upload-artifact@v1.0.0 + with: + name: kbtui-ubuntu-latest-buildbeta + path: kbtui From f222464849efe5229c63e5c9dd4a37f782403269 Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Fri, 20 Dec 2019 12:02:04 -0500 Subject: [PATCH 14/15] Multi platform (#54) * Test go.yaml * Update go.yml * Update go.yml * Update go.yml --- .github/workflows/go.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index b483f40..4a202c2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -1,10 +1,12 @@ name: Go on: [push] jobs: - build: + strategy: + matrix: + platform: [ubuntu-latest, macos-latest, windows-latest] name: Build - runs-on: ubuntu-latest + runs-on: ${{ matrix.platform }} steps: - name: Set up Go 1.13 @@ -20,15 +22,19 @@ jobs: run: | go get -v -t -d ./... go get github.com/magefile/mage - if [ -f Gopkg.toml ]; then - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - dep ensure - fi - name: Build run: go run build.go buildbeta - name: Upload Artifact + if: matrix.platform != 'windows-latest' uses: actions/upload-artifact@v1.0.0 with: - name: kbtui-ubuntu-latest-buildbeta + name: kbtui-${{ matrix.platform }}-buildbeta path: kbtui + + - name: Upload Artifact + if: matrix.platform == 'windows-latest' + uses: actions/upload-artifact@v1.0.0 + with: + name: kbtui-${{ matrix.platform }}-buildbeta + path: kbtui.exe From ae9f71be96130e96759db4236651d4f848b826ed Mon Sep 17 00:00:00 2001 From: Gregory Rudolph Date: Thu, 26 Dec 2019 12:40:25 -0500 Subject: [PATCH 15/15] Remove comment for debugging print --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index d145dce..b91e356 100644 --- a/main.go +++ b/main.go @@ -551,7 +551,6 @@ func formatMessage(api keybase.ChatAPI, formatString string) StyledString { } } - //printInfo(fmt.Sprintf("%d", msg.Content.Text.ReplyTo)) user := colorUsername(msg.Sender.Username) device := config.Colors.Message.SenderDevice.stylize(msg.Sender.DeviceName) msgID := config.Colors.Message.ID.stylize(fmt.Sprintf("%d", msg.ID))