OK, turing.

<- leave blank

Sat Dec 15 07:12:33 EST 2018

Node
Parser.p_expr_core()
{
	Node ex[];
	OpType op[];
	OpType t;
	Node a;

	ex = [this.p_primary()];
	op = [];
	while(t = tok2op[this.peek().t], t !== undefined){
		while(op.length > 0 && prectab[op[0]] >= prectab[t]){
			a = ex.shift();
			ex[0] = new Node(Node{t: ASTBIN, op: op.shift(), n1:
			ex[0], n2: a, lineno: this.lineno});
		}
		this.lex();
		op.unshift(t);
		this.p_attributes();
		ex.unshift(this.p_primary());
	}
	while(op.length > 0){
		a = ex.shift();
		ex[0] = new Node(Node{t: ASTBIN, op: op.shift(), n1: ex[0], n2: a,
		lineno: this.lineno});
	}
	return ex[0];
}


Fri Dec 14 20:40:48 EST 2018
--- /sys/src/cmd/aux/statusbar.c Sun Jul 8 09:18:00 2018
+++ /tmp/statusbar.c Fri Dec 14 19:29:04 2018
@@ -4,6 +4,7 @@
 #include <bio.h>
 #include <event.h>
 #include <keyboard.h>
+#include <theme.h>

 int newwin(char*);

@@ -18,9 +19,11 @@
 void
 initcolor(void)
 {
- text = display->black;
- light = allocimagemix(display, DPalegreen, DWhite);
- dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, DDarkgreen);
+ themeinit("statusbar");
+ text = allocimage(display, Rect(0,0,1,1), CMAP8, 1, themeget("text", DBlack));
+ light = allocimage(display, Rect(0,0,1,1), CMAP8, 1, themeget("background",
DWhite));
+ dark = allocimage(display, Rect(0,0,1,1), CMAP8, 1, themeget("foreground",
DDarkgreen));
+ themeend();
 }

 Rectangle rbar;
--- /sys/src/cmd/aux/statusmsg.c Sun Jul 8 09:18:00 2018
+++ /tmp/statusmsg.c Fri Dec 14 19:28:20 2018
@@ -4,6 +4,7 @@
 #include <bio.h>
 #include <event.h>
 #include <keyboard.h>
+#include <theme.h>

 int newwin(char*);

@@ -20,8 +21,10 @@
 void
 initcolor(void)
 {
- text = display->black;
- light = allocimagemix(display, DPalegreen, DWhite);
+ themeinit("statusmsg");
+ text = allocimage(display, Rect(0,0,1,1), CMAP8, 1, themeget("text", DBlack));
+ light = allocimage(display, Rect(0,0,1,1), CMAP8, 1, themeget("background",
DWhite));
+ themeend();
 }

 void


Fri Dec 14 12:25:23 EST 2018
diff -r 98d8850e0551 commands.go
--- a/commands.go Thu Dec 13 15:05:57 2018 -0600
+++ b/commands.go Fri Dec 14 12:25:13 2018 -0700
@@ -3,27 +3,58 @@
 import (
	"strconv"
	"strings"
+ "github.com/bwmarrin/discordgo"
 )

 //ParseForCommands parses input for Commands, returns message if no command
 specified, else return is empty
 func ParseForCommands(line string) string {
- //One Key Commands
- switch line {
+ if len(line) < 2 {
+ return line
+ }
+ switch line[:2] {
	case ":g":
		SelectGuild()
- line = ""
- case ":c":
- SelectChannel()
- line = ""
+ return ""
	case ":p":
		SelectPrivate()
- line = ""
- default:
- // Nothing
- }
-
- //Argument Commands
- if strings.HasPrefix(line, ":m") {
+ return ""
+ case ":c":
+ opts := strings.Split(line, " ")
+ if len(opts) == 1 {
+ SelectChannel()
+ return ""
+ }
+ selectID := 0
+ if opts[1] == "?" {
+ for _, channel := range State.Channels {
+ if channel.Type == 0 {
+ Msg(TextMsg, "[%d] %s\n", selectID, channel.Name)
+ selectID++
+ }
+ }
+ return ""
+ }
+ selectMap := make(map[int]*discordgo.Channel)
+ for _, channel := range State.Channels {
+ if channel.Type == 0 {
+ selectMap[selectID] = channel
+ selectID++
+ }
+ }
+ selection, err := strconv.Atoi(opts[1])
+ if err != nil {
+ Msg(ErrorMsg, "[:c] Argument Error: %s\n", err)
+ return ""
+ }
+ if len(State.Channels) < selection || selection < 0 {
+ Msg(ErrorMsg, "[:c] Argument Error: Out of bounds\n")
+ return ""
+ }
+ channel := selectMap[selection]
+ State.SetChannel(channel.ID)
+ ShowContent()
+ return ""
+ case ":m":
		AmountStr := strings.Split(line, " ")
		if len(AmountStr) < 2 {
			Msg(ErrorMsg, "[:m] No Arguments \n")
@@ -39,9 +70,8 @@
		Msg(InfoMsg, "Printing last %d messages!\n", Amount)
		State.RetrieveMessages(Amount)
		PrintMessages(Amount)
- line = ""
- }
- if strings.HasPrefix(line, ":u") {
+ return line
+ case ":u":
		session := State.Session
		user := session.User
		newName := strings.TrimPrefix(line, ":u ")
@@ -49,9 +79,8 @@
		if err != nil {
			Msg(ErrorMsg, "[:u] Argument Error: %s\n", err)
		}
- line = ""
- }
-
+ return line
+ }
	return line
 }

diff -r 98d8850e0551 helper.go
--- a/helper.go Thu Dec 13 15:05:57 2018 -0600
+++ b/helper.go Fri Dec 14 12:25:13 2018 -0700
@@ -5,6 +5,7 @@
	"fmt"
	"github.com/bwmarrin/discordgo"
	"io"
+ "io/ioutil"
	"log"
	"os"
	"os/exec"
@@ -60,11 +61,16 @@
 //PrintMessages prints amount of Messages to CLI
 func PrintMessages(Amount int) {
	for Key, m := range State.Messages {
+ name := m.Author.Username
+ if member, ok := State.Members[m.Author.Username]; ok {
+ if member.Nick != "" {
+ name = member.Nick
+ }
+ }
		if Key >= len(State.Messages)-Amount {
			Messages := ReceivingMessageParser(m)
			for _, Msg := range Messages {
- //log.Printf("> %s > %s\n", UserName(m.Author.Username), Msg)
- MessagePrint(string(m.Timestamp), m.Author.Username, Msg)
+ MessagePrint(string(m.Timestamp), name, Msg)

			}
		}
@@ -94,7 +100,7 @@
	switch runtime.GOOS {
	case "plan9":
		pr, pw := io.Pipe()
- cmd := exec.Command("/bin/aux/statusmsg", "-k", *notifyFlag, Title)
+ cmd := exec.Command("/bin/aux/statusmsg", *notifyFlag, Title)
		cmd.Stdin = pr
		go func() {
			defer pw.Close()
@@ -105,7 +111,7 @@
		if err != nil {
			Msg(ErrorMsg, "%s\n", err)
		}
-
+ ioutil.WriteFile("/dev/wctl", []byte("current"), 0644)
	default:
		cmd := exec.Command("notify-send", Title,
		m.ContentWithMentionsReplaced())
		err := cmd.Start()
diff -r 98d8850e0551 main.go
--- a/main.go Thu Dec 13 15:05:57 2018 -0600
+++ b/main.go Fri Dec 14 12:25:13 2018 -0700
@@ -141,9 +141,8 @@
 //ReplaceMentions replaces mentions to ID
 func ReplaceMentions(input string) string {
	// Check for guild members that match
- channel := State.Guild.Members
- for _, member := range channel {
- if member.Nick == input[1:] {
+ for _, member := range State.Guild.Members {
+ if strings.HasPrefix(member.Nick, input[1:]) {
			return member.User.Mention()
		}
		if strings.HasPrefix(member.User.Username, input[1:]) {
@@ -158,7 +157,6 @@
	for _, channel := range userChannels {
		for _, recipient := range channel.Recipients {
			if strings.HasPrefix(input[1:], recipient.Username) {
- fmt.Println("usermatch")
				return recipient.Mention()
			}
		}


Fri Dec 14 12:04:39 EST 2018
def p_eve_1(p):
    '''eve : statement'''
    p[0] = [p[1]]


def p_eve_2(p):
    '''eve : eve statement'''
    p[1].append(p[2])
    p[0] = p[1]


def p_statement_1(p):
    '''statement : NAMESPACE SYM EQ INT DASH INT'''
    current_namespace = Namespace(p[2], p[4], p[6])
    p[0] = current_namespace


def p_statement_2(p):
    '''
    statement : type
	| global_field
    '''
    p[0] = p[1]


def p_type(p):
    '''type : TYPE SYM typedef'''
    p[3].name = p[2]
    p[3].namespace = current_namespace.name
    p[0] = p[3]


Thu Dec 13 20:36:39 EST 2018
diff -r 98d8850e0551 helper.go
--- a/helper.go Thu Dec 13 15:05:57 2018 -0600
+++ b/helper.go Thu Dec 13 20:36:53 2018 -0700
@@ -5,6 +5,7 @@
	"fmt"
	"github.com/bwmarrin/discordgo"
	"io"
+ "io/ioutil"
	"log"
	"os"
	"os/exec"
@@ -60,11 +61,16 @@
 //PrintMessages prints amount of Messages to CLI
 func PrintMessages(Amount int) {
	for Key, m := range State.Messages {
+ name := m.Author.Username
+ if member, ok := State.Members[m.Author.Username]; ok {
+ if member.Nick != "" {
+ name = member.Nick
+ }
+ }
		if Key >= len(State.Messages)-Amount {
			Messages := ReceivingMessageParser(m)
			for _, Msg := range Messages {
- //log.Printf("> %s > %s\n", UserName(m.Author.Username), Msg)
- MessagePrint(string(m.Timestamp), m.Author.Username, Msg)
+ MessagePrint(string(m.Timestamp), name, Msg)

			}
		}
@@ -94,7 +100,7 @@
	switch runtime.GOOS {
	case "plan9":
		pr, pw := io.Pipe()
- cmd := exec.Command("/bin/aux/statusmsg", "-k", *notifyFlag, Title)
+ cmd := exec.Command("/bin/aux/statusmsg", *notifyFlag, Title)
		cmd.Stdin = pr
		go func() {
			defer pw.Close()
@@ -105,7 +111,7 @@
		if err != nil {
			Msg(ErrorMsg, "%s\n", err)
		}
-
+ ioutil.WriteFile("/dev/wctl", []byte("current"), 0644)
	default:
		cmd := exec.Command("notify-send", Title,
		m.ContentWithMentionsReplaced())
		err := cmd.Start()
diff -r 98d8850e0551 main.go
--- a/main.go Thu Dec 13 15:05:57 2018 -0600
+++ b/main.go Thu Dec 13 20:36:53 2018 -0700
@@ -141,9 +141,8 @@
 //ReplaceMentions replaces mentions to ID
 func ReplaceMentions(input string) string {
	// Check for guild members that match
- channel := State.Guild.Members
- for _, member := range channel {
- if member.Nick == input[1:] {
+ for _, member := range State.Guild.Members {
+ if strings.HasPrefix(member.Nick, input[1:]) {
			return member.User.Mention()
		}
		if strings.HasPrefix(member.User.Username, input[1:]) {
@@ -158,7 +157,6 @@
	for _, channel := range userChannels {
		for _, recipient := range channel.Recipients {
			if strings.HasPrefix(input[1:], recipient.Username) {
- fmt.Println("usermatch")
				return recipient.Mention()
			}
		}


Thu Dec 13 19:40:50 EST 2018
use std

const main = {
	var ahead, as, bs
	var a, b, r
	var t0, t

	ahead = "126308761238761823681238076128073687012638701623876" \
		"128036810273608712638706128073612" \
		"807367801263870162083761208736807" \
		"123607812638071623087612807361807" \
		"236087126308712638071628073612087" \
		"368017236016238061208736817023680" \
		"712638701628073612087360187236870" \
		"126387016238706128703681723680126" \
		"380126380612873618270368071236801" \
		"263807126837061280736128073687102" \
		"360871263807126308712630876128730" \
		"612087361208736087126308712630871" \
		"263807612387061287361287036081263" \
		"08712630871623078621"
	bs = \
		"912539716253961283768710263807126308761287670182367801263016"\
		"230861208361287036081726387012636123086128036102368012360812"\
		"630871623087612087361208361287360812630871263807126380761283"\
		"076120873610287361028736018726308712637801263081726308712638"\
		"706123087612308761208736120960189273981273987120938710923709"\
		"127309871289371092873098172397129037091287390127390817290371"\
		"289037918273901273097129083712980370918273098127390817293087"\
		"120983719802738912318273098127390817293087120983719802738912"\
		"318273098127390817293087120983719802738912318273098127390817"\
		"293087120983719802738912318273098127390817293087120983719802"\
		"738912318273098127390817293087120983719802738912318273098127"\
		"390817293087120983719802738912318273098127390817293087120983"\
		"719802738912318273098127390817293087120983719802738912318273"\
		"098127390817293087120983719802738912318273098127390817293087"\
		"120983719802738912318273098127390817293087120983719802738911"\
		"827309812739081729308712098371980273891231827309812739081729"\
		"308712098371980273891231827309812739081729308712098371980273"\
		"891231827309812739081729308712098371980273891231827309812739"\
		"081729308712098371980273891231827309812739081729308712098371"\
		"980273891231827309812739081729308712098371980273891231827309"\
		"812739081729308712098371980273891231827309812739081729308712"\
		"098371980273891231827309812739081729308712098371980273891231"\
		"827309812739081729308712098371980273891231827309812739081729"\
		"308712098371980273891231827309812739081729308712098371980273"\
		"891231827309812739081729308712098371980273891231827309812739"\
		"081729308712098371980273891231827309812739081729308712098371"\
		"980273891231827309812739081729308712098371980273891231827309"\
		"812739081729308712098371980273891231827309812739081729308712"\
		"098371980273891231827309812739081729308712098371980273891231"\
		"827309812739081729308712098371980273891231827309812739081729"\
		"308712098371980273891231827309812739081729308712098371980273"\
		"891231827309812739081729308712098371980273891231827309812739"\
		"081729308712098371980273891232318273098127390817293087120983"\
		"719802738912318273098127390817293087120983719802738912318273"\
		"098127390817293087120983719802738912318273098127390817293087"\
		"120983719802738912318273098127390817293087120983719802738912"\
		"318273098127390817293087120983719802738912318273098127390817"\
		"293087120983719802738912318273098127390817293087120983719802"\
		"738912318273098127390817293087120983719802738912318273098127"\
		"390817293087120983719802738912318273098127390817293087120983"\
		"719802738912318273098127390817293087120983719802738912318273"\
		"098127390817293087120983719802738912318273098127390817293087"\
		"120983719802738912318273098127390817293087120983719802738912"\
		"318273098127390817293087120983719802738912318273098127390817"\
		"293087120983719802738912318273098127390817293087120983719802"\
		"738911827309812739081729308712098371980273891231827309812739"\
		"081729308712098371980273891231827309812739081729308712098371"\
		"980273891231827309812739081729308712098371980273891231827309"\
		"812739081729308712098371980273891231827309812739081729308712"\
		"098371980273891231827309812739081729308712098371980273891231"\
		"827309812739081729308712098371980273891231827309812739081729"\
		"308712098371980273891231827309812739081729308712098371980273"\
		"891231827309812739081729308712098371980273891231827309812739"\
		"081729308712098371980273891231827309812739081729308712098371"\
		"9802738912318273098127390817293087120983719802738912323736"

	as = std.slalloc(ahead.len + 1_000_000)
	std.slfill(as, ('0' : byte))
	std.slcp(as[:ahead.len], ahead)
	a = std.get(std.bigparse(as))
	b = std.get(std.bigparse(bs))

	t0 = std.now()
	r = std.bigdiv(a, b)
	t = std.now() - t0
	std.put("r: {}, tm: {}\n", r, t)
}

Thu Dec 13 19:33:55 EST 2018
use std

const main = {
	var as, bs
	var a, b, r
	var t0, t

	as = "126308761238761823681238076128073687012638701623876" \
		"128036810273608712638706128073612" \
		"807367801263870162083761208736807" \
		"123607812638071623087612807361807" \
		"236087126308712638071628073612087" \
		"368017236016238061208736817023680" \
		"712638701628073612087360187236870" \
		"126387016238706128703681723680126" \
		"380126380612873618270368071236801" \
		"263807126837061280736128073687102" \
		"360871263807126308712630876128730" \
		"612087361208736087126308712630871" \
		"263807612387061287361287036081263" \
		"08712630871623078621"
	bs = "1000000"
	a = std.get(std.bigparse(as))
	b = std.get(std.bigparse(bs))


	t0 = std.now()
	r = std.bigdiv(a, b)
	t = std.now() - t0
	std.put("r: {}, tm: {}\n", r, t)
}

Thu Dec 13 14:37:56 EST 2018
thanks for setting up the plumb logger, kvik!


Thu Dec 13 14:35:52 EST 2018
diff -r b0162227c921 TODO
--- a/TODO Wed Dec 12 21:43:17 2018 -0600
+++ b/TODO Thu Dec 13 14:36:21 2018 -0700
@@ -2,7 +2,7 @@

 :r -- register via Register(email)

-:u -- change username via UserUpdate
+:u [done] -- change username via UserUpdate

 :d [n] [file] -- dump backlog of last 'n' msgs to a file 'file'

@@ -20,17 +20,17 @@

 * if ``` entered, allow multi-line message (composition)

-* replace <:emoji:3lk4j12:> garbage with :emoji:
+* [done] replace <:emoji:3lk4j12:> garbage with :emoji:

-* fix @'s
+* [done] fix @'s

 * flag for larger backlog loading

 * CAPTCHA solution -- http-proxy is a bad one

-* change > to → or whtever desired
+* [done] change > to → or whtever desired

-* fix pm's
+* [done] fix pm's

 * aux/statusmsg backgrounds and doesn't steal input

diff -r b0162227c921 commands.go
--- a/commands.go Wed Dec 12 21:43:17 2018 -0600
+++ b/commands.go Thu Dec 13 14:36:21 2018 -0700
@@ -41,7 +41,17 @@
		PrintMessages(Amount)
		line = ""
	}
-
+ if strings.HasPrefix(line, ":u") {
+ session := State.Session
+ user := session.User
+ newName := strings.TrimPrefix(line, ":u ")
+ _, err := State.Session.DiscordGo.UserUpdate(user.Email, session.Password,
newName, user.Avatar, "")
+ if err != nil {
+ Msg(ErrorMsg, "[:u] Argument Error: %s\n", err)
+ }
+ line = ""
+ }
+
	return line
 }

@@ -49,10 +59,8 @@
 func SelectGuild() {
	State.Enabled = false
	SelectGuildMenu()
- /* this causes a segfault, investigate later */
- //if !State.Channel.IsPrivate {
+ // Segfaults would happen here
	SelectChannelMenu()
- //}
	State.Enabled = true
	ShowContent()
 }
@@ -76,18 +84,15 @@
 //SelectPrivate a private channel
 func SelectPrivate() {
	State.Enabled = false
- /* FIXME -- PM's broken
- SelectPrivateMenu()*/
+ SelectPrivateMenu()
	State.Enabled = true
+ ShowContent()
 }

 //SelectDeletePrivate a private channel
 func SelectDeletePrivate() {
	State.Enabled = false
- /* FIXME -- PM's broken
- SelectDeletePrivateMenu()*/
+ SelectDeletePrivateMenu()
	State.Enabled = true
- if State.Channel != nil {
- ShowContent()
- }
+ ShowContent()
 }
diff -r b0162227c921 config.go
--- a/config.go Wed Dec 12 21:43:17 2018 -0600
+++ b/config.go Thu Dec 13 14:36:21 2018 -0700
@@ -7,8 +7,7 @@
	"log"
	"os"
	"os/user"
-
-// "golang.org/x/crypto/ssh/terminal"
+ // "golang.org/x/crypto/ssh/terminal"
 )

 //Configuration is a struct that contains all configuration fields
@@ -17,6 +16,8 @@
	Password string `json:"password"`
	MessageDefault bool `json:"messagedefault"`
	Messages int `json:"messages"`
+ CompletionChar string `json:"completionchar"`
+ TimeCompChar string `json:"timecompchar"`
 }

 // Config is the global configuration of discord-cli
@@ -24,7 +25,7 @@

 //GetConfig retrieves configuration file from $home/lib/disco.cfg, if it doesn't
 exist it calls CreateConfig()
 func GetConfig() {
-//Get User
+ //Get User
 Start:
	usr, err := user.Current()
	if err != nil {
@@ -65,7 +66,7 @@
	EmptyStruct.Username = scan.Text()
	fmt.Print("Input your password: ")
	//password, err := terminal.ReadPassword(0)
-
+
	plan9 := true
	/* Plan 9 raw mode for rio */
	consctl, err := Rawon()
@@ -73,13 +74,13 @@
		fmt.Println("Failed to set rawon")
		plan9 = false
	}
-
- password := "";
-
+
+ password := ""
+
	if plan9 {
-
+
		password = GetCons()
-
+
		err = RawOff(consctl)
		if err != nil {
			fmt.Println("\nFailed to set rawoff")
@@ -89,13 +90,15 @@
		/* Maybe put linux terminal raw mode in here one day */
		fmt.Println("Skipping raw input for Plan 9")
	}
-
+
	EmptyStruct.Password = string(password)
	EmptyStruct.Messages = 10
	EmptyStruct.MessageDefault = true
+ EmptyStruct.CompletionChar = ">"
+ EmptyStruct.TimeCompChar = ">"

	//Create File
- os.Mkdir(usr.HomeDir + "/lib", 0775)
+ os.Mkdir(usr.HomeDir+"/lib", 0775)
	file, err := os.Create(usr.HomeDir + "/lib/disco.cfg")
	if err != nil {
		log.Fatalln(err)
diff -r b0162227c921 helper.go
--- a/helper.go Wed Dec 12 21:43:17 2018 -0600
+++ b/helper.go Thu Dec 13 14:36:21 2018 -0700
@@ -1,6 +1,9 @@
 package main

 import (
+ "bufio"
+ "fmt"
+ "github.com/bwmarrin/discordgo"
	"io"
	"log"
	"os"
@@ -8,16 +11,13 @@
	"runtime"
	"strings"
	"time"
- "fmt"
- "github.com/bwmarrin/discordgo"
- "bufio"
 )

 //HexColor is a struct gives RGB values
 type HexColor struct {
- R int
- G int
- B int
+ R int
+ G int
+ B int
 }

 //Msg is a composition of Color.New printf functions
@@ -28,13 +28,18 @@
 //Header simply prints a header containing state/session information
 func Header() {
	Msg(InfoMsg, "Welcome, %s!\n\n", State.Session.User.Username)
- /* FIXME -- PM's won't work
- if State.Channel.IsPrivate {
- Msg(InfoMsg, "Channel: %s\n", State.Channel.Recipient.Username)
- } else {
- */
+ switch State.Channel.Type {
+ case discordgo.ChannelTypeGuildText:
		Msg(InfoMsg, "Guild: %s, Channel: %s\n", State.Guild.Name,
		State.Channel.Name)
- /*}*/
+ case discordgo.ChannelTypeDM:
+ Msg(InfoMsg, "Channel: %s\n", State.Channel.Recipients[0].Username)
+ case discordgo.ChannelTypeGroupDM:
+ var nicklist string
+ for _, user := range State.Channel.Recipients {
+ nicklist += user.Username
+ }
+ Msg(InfoMsg, "Channel: %s\n", nicklist)
+ }
 }

 //ReceivingMessageParser parses receiving message for mentions, images and
 MultiLine and returns string array
@@ -57,7 +62,6 @@
	for Key, m := range State.Messages {
		if Key >= len(State.Messages)-Amount {
			Messages := ReceivingMessageParser(m)
-
			for _, Msg := range Messages {
				//log.Printf("> %s > %s\n",
				UserName(m.Author.Username), Msg)
				MessagePrint(string(m.Timestamp),
				m.Author.Username, Msg)
@@ -72,15 +76,21 @@
	if *enableNotify == false {
		return
	}
- Channel, err := State.Session.DiscordGo.Channel(m.ChannelID)
- if err != nil {
- Msg(ErrorMsg, "(NOT) Channel Error: %s\n", err)
+ var Title string
+ switch State.Channel.Type {
+ case discordgo.ChannelTypeGuildText:
+ Channel, err := State.Session.DiscordGo.Channel(m.ChannelID)
+ if err != nil {
+ Msg(ErrorMsg, "(NOT) Channel Error: %s\n", err)
+ }
+ Guild, err := State.Session.DiscordGo.Guild(Channel.GuildID)
+ if err != nil {
+ Msg(ErrorMsg, "(NOT) Guild Error: %s\n", err)
+ }
+ Title = "@" + m.Author.Username + " : " + Guild.Name + "/" + Channel.Name
+ case discordgo.ChannelTypeDM:
+ Title = fmt.Sprintf("%s (pm)\n", m.Author.Username)
	}
- Guild, err := State.Session.DiscordGo.Guild(Channel.GuildID)
- if err != nil {
- Msg(ErrorMsg, "(NOT) Guild Error: %s\n", err)
- }
- Title := "@" + m.Author.Username + " : " + Guild.Name + "/" + Channel.Name
	switch runtime.GOOS {
	case "plan9":
		pr, pw := io.Pipe()
@@ -91,32 +101,33 @@
			fmt.Fprintf(pw, "%s\n", m.ContentWithMentionsReplaced())
			cmd.Wait()
		}()
- err = cmd.Start()
+ err := cmd.Start()
		if err != nil {
			Msg(ErrorMsg, "%s\n", err)
		}
-
+
	default:
		cmd := exec.Command("notify-send", Title,
		m.ContentWithMentionsReplaced())
- err = cmd.Start()
+ err := cmd.Start()
		if err != nil {
			Msg(ErrorMsg, "(NOT) Check if libnotify is installed, or
			disable notifications.\n")
		}
	}

-
 }

 //MessagePrint prints one correctly formatted Message to stdout
 func MessagePrint(Time, Username, Content string) {
+ //Clean up emoji
+ content := ParseForEmoji(Content)
	//var Color color.Attribute
	log.SetFlags(0)
	if *hideTimeStamp {
- log.Printf("%s > %s\n", Username, Content)
+ log.Printf("%s %s %s\n", Username, Config.CompletionChar, content)
	} else {
		TimeStamp, _ := time.Parse(time.RFC3339, Time)
		LocalTime := TimeStamp.Local().Format("2006/01/02 15:04:05")
- log.Printf("%s > %s > %s\n", LocalTime, Username, Content)
+ log.Printf("%s %s %s %s %s\n", LocalTime, Config.TimeCompChar, Username,
Config.CompletionChar, content)

	}
	log.SetFlags(log.LstdFlags)
@@ -126,21 +137,21 @@
	return float64((a - b) * (a - b))
 }

-func Rawon() (*os.File, error){
+func Rawon() (*os.File, error) {
	consctl, err := os.OpenFile("/dev/consctl", os.O_WRONLY, 0200)
	if err != nil {
		/* not on Plan 9 */
		fmt.Println("\nNot running on Plan 9")
		return consctl, err
	}
-
+
	rawon := []byte("rawon")
	_, err = consctl.Write(rawon)
	if err != nil {
		consctl.Close()
		return consctl, err
	}
-
+
	return consctl, nil
 }

@@ -150,14 +161,14 @@
	// /* not on Plan 9 */
	// return err
	//}
-
+
	rawoff := []byte("rawoff")
	_, err := consctl.Write(rawoff)
	if err != nil {
		consctl.Close()
		return err
	}
-
+
	consctl.Close()
	return nil
 }
diff -r b0162227c921 main.go
--- a/main.go Wed Dec 12 21:43:17 2018 -0600
+++ b/main.go Thu Dec 13 14:36:21 2018 -0700
@@ -3,13 +3,14 @@
 package main

 import (
+ "bitbucket.org/henesy/disco/DiscordState"
+ "bufio"
	"flag"
+ "fmt"
	"log"
+ "os"
	"regexp"
- "bitbucket.org/henesy/disco/DiscordState"
- "fmt"
- "bufio"
- "os"
+ "strings"
 )

 //Global Message Types
@@ -88,9 +89,9 @@
		line = ParseForCommands(line)

		line = ParseForMentions(line)
-
+
		if line != "" {
- _ ,err := State.Session.DiscordGo.ChannelMessageSend(State.Channel.ID, line)
+ _, err := State.Session.DiscordGo.ChannelMessageSend(State.Channel.ID, line)
			if err != nil {
				fmt.Print("Error: ", err, "\n")
			}
@@ -110,7 +111,7 @@
	ShowContent()
 }

-//ShowContent shows defaulth Channel content
+//ShowContent shows default Channel content
 func ShowContent() {
	Header()
	if Config.MessageDefault {
@@ -122,31 +123,54 @@
 //ShowEmptyContent shows an empty channel
 func ShowEmptyContent() {
	Header()
+
 }

 //ParseForMentions parses input string for mentions
 func ParseForMentions(line string) string {
- r, err := regexp.Compile("\\@\\w+")
+ r, err := regexp.Compile("@\\w+")
	if err != nil {
		Msg(ErrorMsg, "Regex Error: ", err)
	}

- lineByte := r.ReplaceAllFunc([]byte(line), ReplaceMentions)
+ lineByte := r.ReplaceAllStringFunc(line, ReplaceMentions)

- return string(lineByte[:])
+ return lineByte
 }

-//ReplaceMentions replaces mentions to ID
-func ReplaceMentions(input []byte) []byte {
- var OutputString string
+//ReplaceMentions replaces mentions to ID
+func ReplaceMentions(input string) string {
+ // Check for guild members that match
+ channel := State.Guild.Members
+ for _, member := range channel {
+ if member.Nick == input[1:] {
+ return member.User.Mention()
+ }
+ if strings.HasPrefix(member.User.Username, input[1:]) {
+ return member.User.Mention()
+ }
+ }
+ // Walk all PM channels
+ userChannels, err := Session.DiscordGo.UserChannels()
+ if err != nil {
+ return input
+ }
+ for _, channel := range userChannels {
+ for _, recipient := range channel.Recipients {
+ if strings.HasPrefix(input[1:], recipient.Username) {
+ fmt.Println("usermatch")
+ return recipient.Mention()
+ }
+ }
+ }
+ return input
+}

- SizeByte := len(input)
- InputString := string(input[1:SizeByte])
-
- if Member, ok := State.Members[InputString]; ok {
- OutputString = "<@" + Member.User.ID + ">"
- } else {
- OutputString = "@" + InputString
+//Parse for guild-specific emoji
+func ParseForEmoji(line string) string {
+ r, err := regexp.Compile("<(:\\w+:)[0-9]+>")
+ if err != nil {
+ Msg(ErrorMsg, "Regex Error: ", err)
	}
- return []byte(OutputString)
+ return r.ReplaceAllString(line, "$1")
 }
diff -r b0162227c921 menu.go
--- a/menu.go Wed Dec 12 21:43:17 2018 -0600
+++ b/menu.go Thu Dec 13 14:36:21 2018 -0700
@@ -1,20 +1,20 @@
 package main

 import (
+ "bufio"
	"fmt"
	"log"
+ "os"
	"strconv"
- "bufio"
- "os"
 )
-/* FIXME -- PM's broken
+
 //SelectPrivateMenu is a menu item that changes to a private channel
 func SelectPrivateMenu() {

 Start:

	Msg(InfoMsg, "Select a Member:\n")
-
+ // List of PMs
	UserChannels, err := Session.DiscordGo.UserChannels()

	if err != nil {
@@ -26,7 +26,18 @@

	for _, user := range UserChannels {
		UserMap[SelectID] = user.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, UserChannels[SelectID].Recipient.Username)
+ // We have to loop through all recipients
+ recipients := UserChannels[SelectID].Recipients
+ for _, recipient := range recipients {
+ if recipient.ID == user.ID {
+ continue
+ }
+ if recipient.Username == "" {
+ continue
+ }
+ Msg(TextMsg, "[%d] %s\n", SelectID, recipient.Username)
+ break
+ }
		SelectID++
	}
	Msg(TextMsg, "[b] Extra Options\n")
@@ -78,9 +89,8 @@
	State.Channel = UserChannels[ResponseInteger]
	ShowContent()
 End:
-}*/
+}

-/* FIXME -- PM's broken
 //SelectDeletePrivateMenu deletes a user channel
 func SelectDeletePrivateMenu() {

@@ -99,7 +109,18 @@

	for _, user := range UserChannels {
		UserMap[SelectID] = user.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, UserChannels[SelectID].Recipient.Username)
+ // We have to loop through all recipients
+ recipients := UserChannels[SelectID].Recipients
+ for _, recipient := range recipients {
+ if recipient.ID == user.ID {
+ continue
+ }
+ if recipient.Username == "" {
+ continue
+ }
+ Msg(TextMsg, "[%d] %s\n", SelectID, recipient.Username)
+ break
+ }
		SelectID++
	}
	var response string
@@ -118,7 +139,7 @@

	Session.DiscordGo.ChannelDelete(UserChannels[ResponseInteger].ID)

-} */
+}

 //SelectGuildMenu is a menu item that creates a new State on basis of Guild
 selection
 func SelectGuildMenu() {
@@ -245,7 +266,7 @@
		response, _ := reader.ReadString('\n')
		response = response[:len(response)-1]
		fmt.Println(response, " ", len(response))
-
+
		//fmt.Scanf("%s\n", &response)
		if response == "y" {
			Session.DiscordGo.InviteAccept(Invite.Code)
@@ -281,44 +302,44 @@

 //AddUserChannelMenu takes a user from the current guild and adds them to a
 private message.  WILL RETURN ERROR IF IN USER CHANNEL.
 func AddUserChannelMenu() {
- /* FIXME -- PM's broken
- if State.Channel.IsPrivate {
+
+ if State.Channel.GuildID == "" {
		Msg(ErrorMsg, "Currently in a user channel, move to a guild with
		:g\n")
- } else {*/
- SelectMap := make(map[int]string)
- Start:
- SelectID := 0
- for _, Member := range State.Members {
- SelectMap[SelectID] = Member.User.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, Member.User.Username)
- SelectID++
- }
- var response string
- fmt.Scanf("%s\n", &response)
+ } else {
+ SelectMap := make(map[int]string)
+Start:
+ SelectID := 0
+ for _, Member := range State.Members {
+ SelectMap[SelectID] = Member.User.ID
+ Msg(TextMsg, "[%d] %s\n", SelectID, Member.User.Username)
+ SelectID++
+ }
+ var response string
+ fmt.Scanf("%s\n", &response)

- if response == "b" {
- return
- }
+ if response == "b" {
+ return
+ }

- ResponseInteger, err := strconv.Atoi(response)
- if err != nil {
- Msg(ErrorMsg, "(CH) Conversion Error: %s\n", err)
- goto Start
- }
+ ResponseInteger, err := strconv.Atoi(response)
+ if err != nil {
+ Msg(ErrorMsg, "(CH) Conversion Error: %s\n", err)
+ goto Start
+ }

- if ResponseInteger > SelectID-1 || ResponseInteger < 0 {
- Msg(ErrorMsg, "(CH) Error: ID is out of bound\n")
- goto Start
- }
- Chan, err := Session.DiscordGo.UserChannelCreate(SelectMap[ResponseInteger])
+ if ResponseInteger > SelectID-1 || ResponseInteger < 0 {
+ Msg(ErrorMsg, "(CH) Error: ID is out of bound\n")
+ goto Start
+ }
+ Chan, err := Session.DiscordGo.UserChannelCreate(SelectMap[ResponseInteger])

- if Chan.LastMessageID == "" {
- var firstMessage string
- fmt.Scanf("%s\n", &firstMessage)
- Session.DiscordGo.ChannelMessageSend(Chan.ID, "Test")
- }
- State.Channel = Chan
- /*}*/
+ if Chan.LastMessageID == "" {
+ var firstMessage string
+ fmt.Scanf("%s\n", &firstMessage)
+ Session.DiscordGo.ChannelMessageSend(Chan.ID, "Test")
+ }
+ State.Channel = Chan
+ }
 }

 //LeaveServerMenu is a copy of SelectGuildMenu that leaves instead of selects


Thu Dec 13 14:34:41 EST 2018
diff -r b0162227c921 TODO
--- a/TODO Wed Dec 12 21:43:17 2018 -0600
+++ b/TODO Thu Dec 13 14:35:15 2018 -0700
@@ -2,7 +2,7 @@

 :r -- register via Register(email)

-:u -- change username via UserUpdate
+:u [done] -- change username via UserUpdate

 :d [n] [file] -- dump backlog of last 'n' msgs to a file 'file'

@@ -20,7 +20,7 @@

 * if ``` entered, allow multi-line message (composition)

-* replace <:emoji:3lk4j12:> garbage with :emoji:
+* [done] replace <:emoji:3lk4j12:> garbage with :emoji:

 * fix @'s

@@ -28,9 +28,9 @@

 * CAPTCHA solution -- http-proxy is a bad one

-* change > to → or whtever desired
+* [done] change > to → or whtever desired

-* fix pm's
+* [done] fix pm's

 * aux/statusmsg backgrounds and doesn't steal input

diff -r b0162227c921 commands.go
--- a/commands.go Wed Dec 12 21:43:17 2018 -0600
+++ b/commands.go Thu Dec 13 14:35:15 2018 -0700
@@ -41,7 +41,17 @@
		PrintMessages(Amount)
		line = ""
	}
-
+ if strings.HasPrefix(line, ":u") {
+ session := State.Session
+ user := session.User
+ newName := strings.TrimPrefix(line, ":u ")
+ _, err := State.Session.DiscordGo.UserUpdate(user.Email, session.Password,
newName, user.Avatar, "")
+ if err != nil {
+ Msg(ErrorMsg, "[:u] Argument Error: %s\n", err)
+ }
+ line = ""
+ }
+
	return line
 }

@@ -49,10 +59,8 @@
 func SelectGuild() {
	State.Enabled = false
	SelectGuildMenu()
- /* this causes a segfault, investigate later */
- //if !State.Channel.IsPrivate {
+ // Segfaults would happen here
	SelectChannelMenu()
- //}
	State.Enabled = true
	ShowContent()
 }
@@ -76,18 +84,15 @@
 //SelectPrivate a private channel
 func SelectPrivate() {
	State.Enabled = false
- /* FIXME -- PM's broken
- SelectPrivateMenu()*/
+ SelectPrivateMenu()
	State.Enabled = true
+ ShowContent()
 }

 //SelectDeletePrivate a private channel
 func SelectDeletePrivate() {
	State.Enabled = false
- /* FIXME -- PM's broken
- SelectDeletePrivateMenu()*/
+ SelectDeletePrivateMenu()
	State.Enabled = true
- if State.Channel != nil {
- ShowContent()
- }
+ ShowContent()
 }
diff -r b0162227c921 config.go
--- a/config.go Wed Dec 12 21:43:17 2018 -0600
+++ b/config.go Thu Dec 13 14:35:15 2018 -0700
@@ -7,8 +7,7 @@
	"log"
	"os"
	"os/user"
-
-// "golang.org/x/crypto/ssh/terminal"
+ // "golang.org/x/crypto/ssh/terminal"
 )

 //Configuration is a struct that contains all configuration fields
@@ -17,6 +16,8 @@
	Password string `json:"password"`
	MessageDefault bool `json:"messagedefault"`
	Messages int `json:"messages"`
+ CompletionChar string `json:"completionchar"`
+ TimeCompChar string `json:"timecompchar"`
 }

 // Config is the global configuration of discord-cli
@@ -24,7 +25,7 @@

 //GetConfig retrieves configuration file from $home/lib/disco.cfg, if it doesn't
 exist it calls CreateConfig()
 func GetConfig() {
-//Get User
+ //Get User
 Start:
	usr, err := user.Current()
	if err != nil {
@@ -65,7 +66,7 @@
	EmptyStruct.Username = scan.Text()
	fmt.Print("Input your password: ")
	//password, err := terminal.ReadPassword(0)
-
+
	plan9 := true
	/* Plan 9 raw mode for rio */
	consctl, err := Rawon()
@@ -73,13 +74,13 @@
		fmt.Println("Failed to set rawon")
		plan9 = false
	}
-
- password := "";
-
+
+ password := ""
+
	if plan9 {
-
+
		password = GetCons()
-
+
		err = RawOff(consctl)
		if err != nil {
			fmt.Println("\nFailed to set rawoff")
@@ -89,13 +90,15 @@
		/* Maybe put linux terminal raw mode in here one day */
		fmt.Println("Skipping raw input for Plan 9")
	}
-
+
	EmptyStruct.Password = string(password)
	EmptyStruct.Messages = 10
	EmptyStruct.MessageDefault = true
+ EmptyStruct.CompletionChar = ">"
+ EmptyStruct.TimeCompChar = ">"

	//Create File
- os.Mkdir(usr.HomeDir + "/lib", 0775)
+ os.Mkdir(usr.HomeDir+"/lib", 0775)
	file, err := os.Create(usr.HomeDir + "/lib/disco.cfg")
	if err != nil {
		log.Fatalln(err)
diff -r b0162227c921 helper.go
--- a/helper.go Wed Dec 12 21:43:17 2018 -0600
+++ b/helper.go Thu Dec 13 14:35:15 2018 -0700
@@ -1,6 +1,9 @@
 package main

 import (
+ "bufio"
+ "fmt"
+ "github.com/bwmarrin/discordgo"
	"io"
	"log"
	"os"
@@ -8,16 +11,13 @@
	"runtime"
	"strings"
	"time"
- "fmt"
- "github.com/bwmarrin/discordgo"
- "bufio"
 )

 //HexColor is a struct gives RGB values
 type HexColor struct {
- R int
- G int
- B int
+ R int
+ G int
+ B int
 }

 //Msg is a composition of Color.New printf functions
@@ -28,13 +28,18 @@
 //Header simply prints a header containing state/session information
 func Header() {
	Msg(InfoMsg, "Welcome, %s!\n\n", State.Session.User.Username)
- /* FIXME -- PM's won't work
- if State.Channel.IsPrivate {
- Msg(InfoMsg, "Channel: %s\n", State.Channel.Recipient.Username)
- } else {
- */
+ switch State.Channel.Type {
+ case discordgo.ChannelTypeGuildText:
		Msg(InfoMsg, "Guild: %s, Channel: %s\n", State.Guild.Name,
		State.Channel.Name)
- /*}*/
+ case discordgo.ChannelTypeDM:
+ Msg(InfoMsg, "Channel: %s\n", State.Channel.Recipients[0].Username)
+ case discordgo.ChannelTypeGroupDM:
+ var nicklist string
+ for _, user := range State.Channel.Recipients {
+ nicklist += user.Username
+ }
+ Msg(InfoMsg, "Channel: %s\n", nicklist)
+ }
 }

 //ReceivingMessageParser parses receiving message for mentions, images and
 MultiLine and returns string array
@@ -57,7 +62,6 @@
	for Key, m := range State.Messages {
		if Key >= len(State.Messages)-Amount {
			Messages := ReceivingMessageParser(m)
-
			for _, Msg := range Messages {
				//log.Printf("> %s > %s\n",
				UserName(m.Author.Username), Msg)
				MessagePrint(string(m.Timestamp),
				m.Author.Username, Msg)
@@ -72,15 +76,21 @@
	if *enableNotify == false {
		return
	}
- Channel, err := State.Session.DiscordGo.Channel(m.ChannelID)
- if err != nil {
- Msg(ErrorMsg, "(NOT) Channel Error: %s\n", err)
+ var Title string
+ switch State.Channel.Type {
+ case discordgo.ChannelTypeGuildText:
+ Channel, err := State.Session.DiscordGo.Channel(m.ChannelID)
+ if err != nil {
+ Msg(ErrorMsg, "(NOT) Channel Error: %s\n", err)
+ }
+ Guild, err := State.Session.DiscordGo.Guild(Channel.GuildID)
+ if err != nil {
+ Msg(ErrorMsg, "(NOT) Guild Error: %s\n", err)
+ }
+ Title = "@" + m.Author.Username + " : " + Guild.Name + "/" + Channel.Name
+ case discordgo.ChannelTypeDM:
+ Title = fmt.Sprintf("%s (pm)\n", m.Author.Username)
	}
- Guild, err := State.Session.DiscordGo.Guild(Channel.GuildID)
- if err != nil {
- Msg(ErrorMsg, "(NOT) Guild Error: %s\n", err)
- }
- Title := "@" + m.Author.Username + " : " + Guild.Name + "/" + Channel.Name
	switch runtime.GOOS {
	case "plan9":
		pr, pw := io.Pipe()
@@ -91,32 +101,33 @@
			fmt.Fprintf(pw, "%s\n", m.ContentWithMentionsReplaced())
			cmd.Wait()
		}()
- err = cmd.Start()
+ err := cmd.Start()
		if err != nil {
			Msg(ErrorMsg, "%s\n", err)
		}
-
+
	default:
		cmd := exec.Command("notify-send", Title,
		m.ContentWithMentionsReplaced())
- err = cmd.Start()
+ err := cmd.Start()
		if err != nil {
			Msg(ErrorMsg, "(NOT) Check if libnotify is installed, or
			disable notifications.\n")
		}
	}

-
 }

 //MessagePrint prints one correctly formatted Message to stdout
 func MessagePrint(Time, Username, Content string) {
+ //Clean up emoji
+ content := ParseForEmoji(Content)
	//var Color color.Attribute
	log.SetFlags(0)
	if *hideTimeStamp {
- log.Printf("%s > %s\n", Username, Content)
+ log.Printf("%s %s %s\n", Username, Config.CompletionChar, content)
	} else {
		TimeStamp, _ := time.Parse(time.RFC3339, Time)
		LocalTime := TimeStamp.Local().Format("2006/01/02 15:04:05")
- log.Printf("%s > %s > %s\n", LocalTime, Username, Content)
+ log.Printf("%s %s %s %s %s\n", LocalTime, Config.TimeCompChar, Username,
Config.CompletionChar, content)

	}
	log.SetFlags(log.LstdFlags)
@@ -126,21 +137,21 @@
	return float64((a - b) * (a - b))
 }

-func Rawon() (*os.File, error){
+func Rawon() (*os.File, error) {
	consctl, err := os.OpenFile("/dev/consctl", os.O_WRONLY, 0200)
	if err != nil {
		/* not on Plan 9 */
		fmt.Println("\nNot running on Plan 9")
		return consctl, err
	}
-
+
	rawon := []byte("rawon")
	_, err = consctl.Write(rawon)
	if err != nil {
		consctl.Close()
		return consctl, err
	}
-
+
	return consctl, nil
 }

@@ -150,14 +161,14 @@
	// /* not on Plan 9 */
	// return err
	//}
-
+
	rawoff := []byte("rawoff")
	_, err := consctl.Write(rawoff)
	if err != nil {
		consctl.Close()
		return err
	}
-
+
	consctl.Close()
	return nil
 }
diff -r b0162227c921 main.go
--- a/main.go Wed Dec 12 21:43:17 2018 -0600
+++ b/main.go Thu Dec 13 14:35:15 2018 -0700
@@ -3,13 +3,14 @@
 package main

 import (
+ "bitbucket.org/henesy/disco/DiscordState"
+ "bufio"
	"flag"
+ "fmt"
	"log"
+ "os"
	"regexp"
- "bitbucket.org/henesy/disco/DiscordState"
- "fmt"
- "bufio"
- "os"
+ "strings"
 )

 //Global Message Types
@@ -88,9 +89,9 @@
		line = ParseForCommands(line)

		line = ParseForMentions(line)
-
+
		if line != "" {
- _ ,err := State.Session.DiscordGo.ChannelMessageSend(State.Channel.ID, line)
+ _, err := State.Session.DiscordGo.ChannelMessageSend(State.Channel.ID, line)
			if err != nil {
				fmt.Print("Error: ", err, "\n")
			}
@@ -110,7 +111,7 @@
	ShowContent()
 }

-//ShowContent shows defaulth Channel content
+//ShowContent shows default Channel content
 func ShowContent() {
	Header()
	if Config.MessageDefault {
@@ -122,31 +123,54 @@
 //ShowEmptyContent shows an empty channel
 func ShowEmptyContent() {
	Header()
+
 }

 //ParseForMentions parses input string for mentions
 func ParseForMentions(line string) string {
- r, err := regexp.Compile("\\@\\w+")
+ r, err := regexp.Compile("@\\w+")
	if err != nil {
		Msg(ErrorMsg, "Regex Error: ", err)
	}

- lineByte := r.ReplaceAllFunc([]byte(line), ReplaceMentions)
+ lineByte := r.ReplaceAllStringFunc(line, ReplaceMentions)

- return string(lineByte[:])
+ return lineByte
 }

-//ReplaceMentions replaces mentions to ID
-func ReplaceMentions(input []byte) []byte {
- var OutputString string
+//ReplaceMentions replaces mentions to ID
+func ReplaceMentions(input string) string {
+ // Check for guild members that match
+ channel := State.Guild.Members
+ for _, member := range channel {
+ if member.Nick == input[1:] {
+ return member.User.Mention()
+ }
+ if strings.HasPrefix(member.User.Username, input[1:]) {
+ return member.User.Mention()
+ }
+ }
+ // Walk all PM channels
+ userChannels, err := Session.DiscordGo.UserChannels()
+ if err != nil {
+ return input
+ }
+ for _, channel := range userChannels {
+ for _, recipient := range channel.Recipients {
+ if strings.HasPrefix(input[1:], recipient.Username) {
+ fmt.Println("usermatch")
+ return recipient.Mention()
+ }
+ }
+ }
+ return input
+}

- SizeByte := len(input)
- InputString := string(input[1:SizeByte])
-
- if Member, ok := State.Members[InputString]; ok {
- OutputString = "<@" + Member.User.ID + ">"
- } else {
- OutputString = "@" + InputString
+//Parse for guild-specific emoji
+func ParseForEmoji(line string) string {
+ r, err := regexp.Compile("<(:\\w+:)[0-9]+>")
+ if err != nil {
+ Msg(ErrorMsg, "Regex Error: ", err)
	}
- return []byte(OutputString)
+ return r.ReplaceAllString(line, "$1")
 }
diff -r b0162227c921 menu.go
--- a/menu.go Wed Dec 12 21:43:17 2018 -0600
+++ b/menu.go Thu Dec 13 14:35:15 2018 -0700
@@ -1,20 +1,20 @@
 package main

 import (
+ "bufio"
	"fmt"
	"log"
+ "os"
	"strconv"
- "bufio"
- "os"
 )
-/* FIXME -- PM's broken
+
 //SelectPrivateMenu is a menu item that changes to a private channel
 func SelectPrivateMenu() {

 Start:

	Msg(InfoMsg, "Select a Member:\n")
-
+ // List of PMs
	UserChannels, err := Session.DiscordGo.UserChannels()

	if err != nil {
@@ -26,7 +26,18 @@

	for _, user := range UserChannels {
		UserMap[SelectID] = user.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, UserChannels[SelectID].Recipient.Username)
+ // We have to loop through all recipients
+ recipients := UserChannels[SelectID].Recipients
+ for _, recipient := range recipients {
+ if recipient.ID == user.ID {
+ continue
+ }
+ if recipient.Username == "" {
+ continue
+ }
+ Msg(TextMsg, "[%d] %s\n", SelectID, recipient.Username)
+ break
+ }
		SelectID++
	}
	Msg(TextMsg, "[b] Extra Options\n")
@@ -78,9 +89,8 @@
	State.Channel = UserChannels[ResponseInteger]
	ShowContent()
 End:
-}*/
+}

-/* FIXME -- PM's broken
 //SelectDeletePrivateMenu deletes a user channel
 func SelectDeletePrivateMenu() {

@@ -99,7 +109,18 @@

	for _, user := range UserChannels {
		UserMap[SelectID] = user.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, UserChannels[SelectID].Recipient.Username)
+ // We have to loop through all recipients
+ recipients := UserChannels[SelectID].Recipients
+ for _, recipient := range recipients {
+ if recipient.ID == user.ID {
+ continue
+ }
+ if recipient.Username == "" {
+ continue
+ }
+ Msg(TextMsg, "[%d] %s\n", SelectID, recipient.Username)
+ break
+ }
		SelectID++
	}
	var response string
@@ -118,7 +139,7 @@

	Session.DiscordGo.ChannelDelete(UserChannels[ResponseInteger].ID)

-} */
+}

 //SelectGuildMenu is a menu item that creates a new State on basis of Guild
 selection
 func SelectGuildMenu() {
@@ -245,7 +266,7 @@
		response, _ := reader.ReadString('\n')
		response = response[:len(response)-1]
		fmt.Println(response, " ", len(response))
-
+
		//fmt.Scanf("%s\n", &response)
		if response == "y" {
			Session.DiscordGo.InviteAccept(Invite.Code)
@@ -281,44 +302,44 @@

 //AddUserChannelMenu takes a user from the current guild and adds them to a
 private message.  WILL RETURN ERROR IF IN USER CHANNEL.
 func AddUserChannelMenu() {
- /* FIXME -- PM's broken
- if State.Channel.IsPrivate {
+
+ if State.Channel.GuildID == "" {
		Msg(ErrorMsg, "Currently in a user channel, move to a guild with
		:g\n")
- } else {*/
- SelectMap := make(map[int]string)
- Start:
- SelectID := 0
- for _, Member := range State.Members {
- SelectMap[SelectID] = Member.User.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, Member.User.Username)
- SelectID++
- }
- var response string
- fmt.Scanf("%s\n", &response)
+ } else {
+ SelectMap := make(map[int]string)
+Start:
+ SelectID := 0
+ for _, Member := range State.Members {
+ SelectMap[SelectID] = Member.User.ID
+ Msg(TextMsg, "[%d] %s\n", SelectID, Member.User.Username)
+ SelectID++
+ }
+ var response string
+ fmt.Scanf("%s\n", &response)

- if response == "b" {
- return
- }
+ if response == "b" {
+ return
+ }

- ResponseInteger, err := strconv.Atoi(response)
- if err != nil {
- Msg(ErrorMsg, "(CH) Conversion Error: %s\n", err)
- goto Start
- }
+ ResponseInteger, err := strconv.Atoi(response)
+ if err != nil {
+ Msg(ErrorMsg, "(CH) Conversion Error: %s\n", err)
+ goto Start
+ }

- if ResponseInteger > SelectID-1 || ResponseInteger < 0 {
- Msg(ErrorMsg, "(CH) Error: ID is out of bound\n")
- goto Start
- }
- Chan, err := Session.DiscordGo.UserChannelCreate(SelectMap[ResponseInteger])
+ if ResponseInteger > SelectID-1 || ResponseInteger < 0 {
+ Msg(ErrorMsg, "(CH) Error: ID is out of bound\n")
+ goto Start
+ }
+ Chan, err := Session.DiscordGo.UserChannelCreate(SelectMap[ResponseInteger])

- if Chan.LastMessageID == "" {
- var firstMessage string
- fmt.Scanf("%s\n", &firstMessage)
- Session.DiscordGo.ChannelMessageSend(Chan.ID, "Test")
- }
- State.Channel = Chan
- /*}*/
+ if Chan.LastMessageID == "" {
+ var firstMessage string
+ fmt.Scanf("%s\n", &firstMessage)
+ Session.DiscordGo.ChannelMessageSend(Chan.ID, "Test")
+ }
+ State.Channel = Chan
+ }
 }

 //LeaveServerMenu is a copy of SelectGuildMenu that leaves instead of selects


Thu Dec 13 13:37:45 EST 2018
diff -r b0162227c921 TODO
--- a/TODO Wed Dec 12 21:43:17 2018 -0600
+++ b/TODO Thu Dec 13 13:38:14 2018 -0700
@@ -2,7 +2,7 @@

 :r -- register via Register(email)

-:u -- change username via UserUpdate
+:u [done] -- change username via UserUpdate

 :d [n] [file] -- dump backlog of last 'n' msgs to a file 'file'

@@ -20,7 +20,7 @@

 * if ``` entered, allow multi-line message (composition)

-* replace <:emoji:3lk4j12:> garbage with :emoji:
+* [done] replace <:emoji:3lk4j12:> garbage with :emoji:

 * fix @'s

@@ -28,9 +28,9 @@

 * CAPTCHA solution -- http-proxy is a bad one

-* change > to → or whtever desired
+* [done] change > to → or whtever desired

-* fix pm's
+* [done] fix pm's

 * aux/statusmsg backgrounds and doesn't steal input

diff -r b0162227c921 commands.go
--- a/commands.go Wed Dec 12 21:43:17 2018 -0600
+++ b/commands.go Thu Dec 13 13:38:14 2018 -0700
@@ -41,7 +41,17 @@
		PrintMessages(Amount)
		line = ""
	}
-
+ if strings.HasPrefix(line, ":u") {
+ session := State.Session
+ user := session.User
+ newName := strings.TrimPrefix(line, ":u ")
+ _, err := State.Session.DiscordGo.UserUpdate(user.Email, session.Password,
newName, user.Avatar, "")
+ if err != nil {
+ Msg(ErrorMsg, "[:u] Argument Error: %s\n", err)
+ }
+ line = ""
+ }
+
	return line
 }

@@ -49,10 +59,8 @@
 func SelectGuild() {
	State.Enabled = false
	SelectGuildMenu()
- /* this causes a segfault, investigate later */
- //if !State.Channel.IsPrivate {
+ // Segfaults would happen here
	SelectChannelMenu()
- //}
	State.Enabled = true
	ShowContent()
 }
@@ -76,18 +84,15 @@
 //SelectPrivate a private channel
 func SelectPrivate() {
	State.Enabled = false
- /* FIXME -- PM's broken
- SelectPrivateMenu()*/
+ SelectPrivateMenu()
	State.Enabled = true
+ ShowContent()
 }

 //SelectDeletePrivate a private channel
 func SelectDeletePrivate() {
	State.Enabled = false
- /* FIXME -- PM's broken
- SelectDeletePrivateMenu()*/
+ SelectDeletePrivateMenu()
	State.Enabled = true
- if State.Channel != nil {
- ShowContent()
- }
+ ShowContent()
 }
diff -r b0162227c921 config.go
--- a/config.go Wed Dec 12 21:43:17 2018 -0600
+++ b/config.go Thu Dec 13 13:38:14 2018 -0700
@@ -7,8 +7,7 @@
	"log"
	"os"
	"os/user"
-
-// "golang.org/x/crypto/ssh/terminal"
+ // "golang.org/x/crypto/ssh/terminal"
 )

 //Configuration is a struct that contains all configuration fields
@@ -17,6 +16,8 @@
	Password string `json:"password"`
	MessageDefault bool `json:"messagedefault"`
	Messages int `json:"messages"`
+ CompletionChar string `json:"completionchar"`
+ TimeCompChar string `json:"timecompchar"`
 }

 // Config is the global configuration of discord-cli
@@ -24,7 +25,7 @@

 //GetConfig retrieves configuration file from $home/lib/disco.cfg, if it doesn't
 exist it calls CreateConfig()
 func GetConfig() {
-//Get User
+ //Get User
 Start:
	usr, err := user.Current()
	if err != nil {
@@ -65,7 +66,7 @@
	EmptyStruct.Username = scan.Text()
	fmt.Print("Input your password: ")
	//password, err := terminal.ReadPassword(0)
-
+
	plan9 := true
	/* Plan 9 raw mode for rio */
	consctl, err := Rawon()
@@ -73,13 +74,13 @@
		fmt.Println("Failed to set rawon")
		plan9 = false
	}
-
- password := "";
-
+
+ password := ""
+
	if plan9 {
-
+
		password = GetCons()
-
+
		err = RawOff(consctl)
		if err != nil {
			fmt.Println("\nFailed to set rawoff")
@@ -89,13 +90,15 @@
		/* Maybe put linux terminal raw mode in here one day */
		fmt.Println("Skipping raw input for Plan 9")
	}
-
+
	EmptyStruct.Password = string(password)
	EmptyStruct.Messages = 10
	EmptyStruct.MessageDefault = true
+ EmptyStruct.CompletionChar = ">"
+ EmptyStruct.TimeCompChar = ">"

	//Create File
- os.Mkdir(usr.HomeDir + "/lib", 0775)
+ os.Mkdir(usr.HomeDir+"/lib", 0775)
	file, err := os.Create(usr.HomeDir + "/lib/disco.cfg")
	if err != nil {
		log.Fatalln(err)
diff -r b0162227c921 helper.go
--- a/helper.go Wed Dec 12 21:43:17 2018 -0600
+++ b/helper.go Thu Dec 13 13:38:14 2018 -0700
@@ -1,6 +1,9 @@
 package main

 import (
+ "bufio"
+ "fmt"
+ "github.com/bwmarrin/discordgo"
	"io"
	"log"
	"os"
@@ -8,16 +11,13 @@
	"runtime"
	"strings"
	"time"
- "fmt"
- "github.com/bwmarrin/discordgo"
- "bufio"
 )

 //HexColor is a struct gives RGB values
 type HexColor struct {
- R int
- G int
- B int
+ R int
+ G int
+ B int
 }

 //Msg is a composition of Color.New printf functions
@@ -28,13 +28,18 @@
 //Header simply prints a header containing state/session information
 func Header() {
	Msg(InfoMsg, "Welcome, %s!\n\n", State.Session.User.Username)
- /* FIXME -- PM's won't work
- if State.Channel.IsPrivate {
- Msg(InfoMsg, "Channel: %s\n", State.Channel.Recipient.Username)
- } else {
- */
+ switch State.Channel.Type {
+ case discordgo.ChannelTypeGuildText:
		Msg(InfoMsg, "Guild: %s, Channel: %s\n", State.Guild.Name,
		State.Channel.Name)
- /*}*/
+ case discordgo.ChannelTypeDM:
+ Msg(InfoMsg, "Channel: %s\n", State.Channel.Recipients[0].Username)
+ case discordgo.ChannelTypeGroupDM:
+ var nicklist string
+ for _, user := range State.Channel.Recipients {
+ nicklist += user.Username
+ }
+ Msg(InfoMsg, "Channel: %s\n", nicklist)
+ }
 }

 //ReceivingMessageParser parses receiving message for mentions, images and
 MultiLine and returns string array
@@ -57,7 +62,6 @@
	for Key, m := range State.Messages {
		if Key >= len(State.Messages)-Amount {
			Messages := ReceivingMessageParser(m)
-
			for _, Msg := range Messages {
				//log.Printf("> %s > %s\n",
				UserName(m.Author.Username), Msg)
				MessagePrint(string(m.Timestamp),
				m.Author.Username, Msg)
@@ -72,15 +76,21 @@
	if *enableNotify == false {
		return
	}
- Channel, err := State.Session.DiscordGo.Channel(m.ChannelID)
- if err != nil {
- Msg(ErrorMsg, "(NOT) Channel Error: %s\n", err)
+ var Title string
+ switch State.Channel.Type {
+ case discordgo.ChannelTypeGuildText:
+ Channel, err := State.Session.DiscordGo.Channel(m.ChannelID)
+ if err != nil {
+ Msg(ErrorMsg, "(NOT) Channel Error: %s\n", err)
+ }
+ Guild, err := State.Session.DiscordGo.Guild(Channel.GuildID)
+ if err != nil {
+ Msg(ErrorMsg, "(NOT) Guild Error: %s\n", err)
+ }
+ Title = "@" + m.Author.Username + " : " + Guild.Name + "/" + Channel.Name
+ case discordgo.ChannelTypeDM:
+ Title = fmt.Sprintf("%s (pm)\n", m.Author.Username)
	}
- Guild, err := State.Session.DiscordGo.Guild(Channel.GuildID)
- if err != nil {
- Msg(ErrorMsg, "(NOT) Guild Error: %s\n", err)
- }
- Title := "@" + m.Author.Username + " : " + Guild.Name + "/" + Channel.Name
	switch runtime.GOOS {
	case "plan9":
		pr, pw := io.Pipe()
@@ -91,32 +101,33 @@
			fmt.Fprintf(pw, "%s\n", m.ContentWithMentionsReplaced())
			cmd.Wait()
		}()
- err = cmd.Start()
+ err := cmd.Start()
		if err != nil {
			Msg(ErrorMsg, "%s\n", err)
		}
-
+
	default:
		cmd := exec.Command("notify-send", Title,
		m.ContentWithMentionsReplaced())
- err = cmd.Start()
+ err := cmd.Start()
		if err != nil {
			Msg(ErrorMsg, "(NOT) Check if libnotify is installed, or
			disable notifications.\n")
		}
	}

-
 }

 //MessagePrint prints one correctly formatted Message to stdout
 func MessagePrint(Time, Username, Content string) {
+ //Clean up emoji
+ content := ParseForEmoji(Content)
	//var Color color.Attribute
	log.SetFlags(0)
	if *hideTimeStamp {
- log.Printf("%s > %s\n", Username, Content)
+ log.Printf("%s %s %s\n", Username, Config.CompletionChar, content)
	} else {
		TimeStamp, _ := time.Parse(time.RFC3339, Time)
		LocalTime := TimeStamp.Local().Format("2006/01/02 15:04:05")
- log.Printf("%s > %s > %s\n", LocalTime, Username, Content)
+ log.Printf("%s %s %s %s %s\n", LocalTime, Config.TimeCompChar, Username,
Config.CompletionChar, content)

	}
	log.SetFlags(log.LstdFlags)
@@ -126,21 +137,21 @@
	return float64((a - b) * (a - b))
 }

-func Rawon() (*os.File, error){
+func Rawon() (*os.File, error) {
	consctl, err := os.OpenFile("/dev/consctl", os.O_WRONLY, 0200)
	if err != nil {
		/* not on Plan 9 */
		fmt.Println("\nNot running on Plan 9")
		return consctl, err
	}
-
+
	rawon := []byte("rawon")
	_, err = consctl.Write(rawon)
	if err != nil {
		consctl.Close()
		return consctl, err
	}
-
+
	return consctl, nil
 }

@@ -150,14 +161,14 @@
	// /* not on Plan 9 */
	// return err
	//}
-
+
	rawoff := []byte("rawoff")
	_, err := consctl.Write(rawoff)
	if err != nil {
		consctl.Close()
		return err
	}
-
+
	consctl.Close()
	return nil
 }
diff -r b0162227c921 main.go
--- a/main.go Wed Dec 12 21:43:17 2018 -0600
+++ b/main.go Thu Dec 13 13:38:14 2018 -0700
@@ -3,13 +3,14 @@
 package main

 import (
+ "bitbucket.org/henesy/disco/DiscordState"
+ "bufio"
	"flag"
+ "fmt"
	"log"
+ "os"
	"regexp"
- "bitbucket.org/henesy/disco/DiscordState"
- "fmt"
- "bufio"
- "os"
+ //"strings"
 )

 //Global Message Types
@@ -88,9 +89,9 @@
		line = ParseForCommands(line)

		line = ParseForMentions(line)
-
+
		if line != "" {
- _ ,err := State.Session.DiscordGo.ChannelMessageSend(State.Channel.ID, line)
+ _, err := State.Session.DiscordGo.ChannelMessageSend(State.Channel.ID, line)
			if err != nil {
				fmt.Print("Error: ", err, "\n")
			}
@@ -110,7 +111,7 @@
	ShowContent()
 }

-//ShowContent shows defaulth Channel content
+//ShowContent shows default Channel content
 func ShowContent() {
	Header()
	if Config.MessageDefault {
@@ -122,31 +123,47 @@
 //ShowEmptyContent shows an empty channel
 func ShowEmptyContent() {
	Header()
+
 }

 //ParseForMentions parses input string for mentions
 func ParseForMentions(line string) string {
- r, err := regexp.Compile("\\@\\w+")
+ r, err := regexp.Compile("@\\w+")
	if err != nil {
		Msg(ErrorMsg, "Regex Error: ", err)
	}

- lineByte := r.ReplaceAllFunc([]byte(line), ReplaceMentions)
+ lineByte := r.ReplaceAllStringFunc(line, ReplaceMentions)

- return string(lineByte[:])
+ return lineByte
 }

 //ReplaceMentions replaces mentions to ID
-func ReplaceMentions(input []byte) []byte {
- var OutputString string
+func ReplaceMentions(input string) string {
+ // Check for guild members
+ for _, member := range State.Members {
+ if strings.HasPrefix(member.User.Username, input[1:]) {
+ return member.User.Mention()
+ }
+ }
+ // Walk all PM channels
+ for _, channel := range State.UserChannels {
+ for _, recipient := range channel.Recipients {
+ fmt.Println(recipient.Username)
+ if recipient.Username == input[1:] {
+ fmt.Println("usermatch")
+ return recipient.Mention()
+ }
+ }
+ }
+ return input
+}

- SizeByte := len(input)
- InputString := string(input[1:SizeByte])
-
- if Member, ok := State.Members[InputString]; ok {
- OutputString = "<@" + Member.User.ID + ">"
- } else {
- OutputString = "@" + InputString
+//Parse for guild-specific emoji
+func ParseForEmoji(line string) string {
+ r, err := regexp.Compile("<(:\\w+:)[0-9]+>")
+ if err != nil {
+ Msg(ErrorMsg, "Regex Error: ", err)
	}
- return []byte(OutputString)
+ return r.ReplaceAllString(line, "$1")
 }
diff -r b0162227c921 menu.go
--- a/menu.go Wed Dec 12 21:43:17 2018 -0600
+++ b/menu.go Thu Dec 13 13:38:14 2018 -0700
@@ -1,20 +1,20 @@
 package main

 import (
+ "bufio"
	"fmt"
	"log"
+ "os"
	"strconv"
- "bufio"
- "os"
 )
-/* FIXME -- PM's broken
+
 //SelectPrivateMenu is a menu item that changes to a private channel
 func SelectPrivateMenu() {

 Start:

	Msg(InfoMsg, "Select a Member:\n")
-
+ // List of PMs
	UserChannels, err := Session.DiscordGo.UserChannels()

	if err != nil {
@@ -26,7 +26,18 @@

	for _, user := range UserChannels {
		UserMap[SelectID] = user.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, UserChannels[SelectID].Recipient.Username)
+ // We have to loop through all recipients
+ recipients := UserChannels[SelectID].Recipients
+ for _, recipient := range recipients {
+ if recipient.ID == user.ID {
+ continue
+ }
+ if recipient.Username == "" {
+ continue
+ }
+ Msg(TextMsg, "[%d] %s\n", SelectID, recipient.Username)
+ break
+ }
		SelectID++
	}
	Msg(TextMsg, "[b] Extra Options\n")
@@ -78,9 +89,8 @@
	State.Channel = UserChannels[ResponseInteger]
	ShowContent()
 End:
-}*/
+}

-/* FIXME -- PM's broken
 //SelectDeletePrivateMenu deletes a user channel
 func SelectDeletePrivateMenu() {

@@ -99,7 +109,18 @@

	for _, user := range UserChannels {
		UserMap[SelectID] = user.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, UserChannels[SelectID].Recipient.Username)
+ // We have to loop through all recipients
+ recipients := UserChannels[SelectID].Recipients
+ for _, recipient := range recipients {
+ if recipient.ID == user.ID {
+ continue
+ }
+ if recipient.Username == "" {
+ continue
+ }
+ Msg(TextMsg, "[%d] %s\n", SelectID, recipient.Username)
+ break
+ }
		SelectID++
	}
	var response string
@@ -118,7 +139,7 @@

	Session.DiscordGo.ChannelDelete(UserChannels[ResponseInteger].ID)

-} */
+}

 //SelectGuildMenu is a menu item that creates a new State on basis of Guild
 selection
 func SelectGuildMenu() {
@@ -245,7 +266,7 @@
		response, _ := reader.ReadString('\n')
		response = response[:len(response)-1]
		fmt.Println(response, " ", len(response))
-
+
		//fmt.Scanf("%s\n", &response)
		if response == "y" {
			Session.DiscordGo.InviteAccept(Invite.Code)
@@ -281,44 +302,44 @@

 //AddUserChannelMenu takes a user from the current guild and adds them to a
 private message.  WILL RETURN ERROR IF IN USER CHANNEL.
 func AddUserChannelMenu() {
- /* FIXME -- PM's broken
- if State.Channel.IsPrivate {
+
+ if State.Channel.GuildID == "" {
		Msg(ErrorMsg, "Currently in a user channel, move to a guild with
		:g\n")
- } else {*/
- SelectMap := make(map[int]string)
- Start:
- SelectID := 0
- for _, Member := range State.Members {
- SelectMap[SelectID] = Member.User.ID
- Msg(TextMsg, "[%d] %s\n", SelectID, Member.User.Username)
- SelectID++
- }
- var response string
- fmt.Scanf("%s\n", &response)
+ } else {
+ SelectMap := make(map[int]string)
+Start:
+ SelectID := 0
+ for _, Member := range State.Members {
+ SelectMap[SelectID] = Member.User.ID
+ Msg(TextMsg, "[%d] %s\n", SelectID, Member.User.Username)
+ SelectID++
+ }
+ var response string
+ fmt.Scanf("%s\n", &response)

- if response == "b" {
- return
- }
+ if response == "b" {
+ return
+ }

- ResponseInteger, err := strconv.Atoi(response)
- if err != nil {
- Msg(ErrorMsg, "(CH) Conversion Error: %s\n", err)
- goto Start
- }
+ ResponseInteger, err := strconv.Atoi(response)
+ if err != nil {
+ Msg(ErrorMsg, "(CH) Conversion Error: %s\n", err)
+ goto Start
+ }

- if ResponseInteger > SelectID-1 || ResponseInteger < 0 {
- Msg(ErrorMsg, "(CH) Error: ID is out of bound\n")
- goto Start
- }
- Chan, err := Session.DiscordGo.UserChannelCreate(SelectMap[ResponseInteger])
+ if ResponseInteger > SelectID-1 || ResponseInteger < 0 {
+ Msg(ErrorMsg, "(CH) Error: ID is out of bound\n")
+ goto Start
+ }
+ Chan, err := Session.DiscordGo.UserChannelCreate(SelectMap[ResponseInteger])

- if Chan.LastMessageID == "" {
- var firstMessage string
- fmt.Scanf("%s\n", &firstMessage)
- Session.DiscordGo.ChannelMessageSend(Chan.ID, "Test")
- }
- State.Channel = Chan
- /*}*/
+ if Chan.LastMessageID == "" {
+ var firstMessage string
+ fmt.Scanf("%s\n", &firstMessage)
+ Session.DiscordGo.ChannelMessageSend(Chan.ID, "Test")
+ }
+ State.Channel = Chan
+ }
 }

 //LeaveServerMenu is a copy of SelectGuildMenu that leaves instead of selects


next