func (e *StatusCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if s.Client != nil && s.Client.Connected() { client.StatusMessage(v, "Status: Connected.") } else { client.StatusMessage(v, "Status: Disconnected.") } return nil }) return nil }
func (e *WindowCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } if len(args) == 2 { i := common.StringTo(args[1]).MustInt() Server.CurrentChannel = Server.Channels[i].Name Server.Gui.SetViewOnTop(Server.CurrentChannel) c := Server.GetCurrentChannel() if _, err := g.SetCurrentView(c.Name); err != nil { return err } c.Unread = false if _, err := g.SetCurrentView("input"); err != nil { return err } ui.UpdateMenuView(g) } return nil }) return nil }
func (e *QueryCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } if len(args) >= 2 && len(args[1]) > 0 { CurrentChannel = args[1] s.CurrentChannel = args[1] s.NewChannel(args[1], true) if len(args[2]) > 0 { go Server.Client.Privmsg(args[1], strings.Replace(args[2], "\x00", "", -1)) } } return nil }) return nil }
func (e *VersionCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { client.StatusMessage(v, ui.VersionLine) return nil }) return nil }
func (e *EmptyCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { client.StatusMessage(v, fmt.Sprintf("Unknow Command: %s", args[0])) return nil }) return nil }
func (e *HelpCmd) Exec(args []string) error { Server.Exec(Server.CurrentChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { client.StatusMessage(v, "==================== HELP COMMANDS ====================") for _, command := range Commands { metadata := command.Metadata() client.StatusMessage(v, fmt.Sprintf("/%s %s - %s", metadata.Name(), metadata.Args(), metadata.Description())) } client.StatusMessage(v, "==================== HELP COMMANDS ====================\n") return nil }) return nil }
func (e *ConnectCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if s.Client.Connected() { client.StatusMessage(v, "Already Connecting and/or Connected...") return nil } client.StatusMessage(v, "Connecting... please wait.") if err := s.Client.Connect(); err != nil { log.Fatal(err) } go func() { ticker := time.NewTicker(8000 * time.Microsecond) for { select { case <-ticker.C: fmt.Fprint(v, ".") case msg := <-ui.LoadingChannel.Recv: if msg == "done" { fmt.Fprint(v, "\n") ticker.Stop() break } } } }() return nil }) return nil }
func (e *PartCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } if len(args) >= 2 { if args[1] == client.StatusChannel { return nil } s.Client.Part(args[1]) index, err := s.RemoveChannel(args[1]) if len(s.Channels) <= 1 { CurrentChannel = client.StatusChannel Server.CurrentChannel = client.StatusChannel Server.Gui.SetViewOnTop(client.StatusChannel) } else { Server.CurrentChannel = Server.Channels[index-1].Name Server.Gui.SetViewOnTop(Server.CurrentChannel) c := Server.GetCurrentChannel() if _, err := g.SetCurrentView(c.Name); err != nil { return err } c.Unread = false } if _, err := g.SetCurrentView("input"); err != nil { return err } ui.UpdateMenuView(g) return err } return nil }) return nil }
func (e *RawCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } cmd := strings.Join(args[1:], " ") logger.Logger.Printf("RAW COMMAND %s\n", cmd) s.Client.Raw(cmd) return nil }) return nil }
func (e *TopicCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } if len(args) == 3 && strings.HasPrefix(args[1], "#") { s.Client.Topic(args[1], args[2]) } else if len(args) == 2 { s.Client.Topic(Server.CurrentChannel, args[1]) } return nil }) return nil }
func (e *PassCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } logger.Logger.Printf("pass %s \n", args) if len(args) == 2 && len(args[1]) > 0 { s.Client.Pass(args[1]) } return nil }) return nil }
func (e *NamesCmd) Exec(args []string) error { Server.Exec(Server.CurrentChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } channel := Server.GetCurrentChannel() if channel != nil { channel.NickListString(v) } return nil }) return nil }
func (e *JoinCmd) Exec(args []string) error { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if !s.Client.Connected() { client.StatusMessage(v, "Not connected") return nil } if len(args) >= 2 && len(args[1]) > 0 { s.Client.Join(args[1]) CurrentChannel = args[1] s.CurrentChannel = args[1] return s.NewChannel(args[1], false) } return nil }) return nil }
func GetLine(g *gocui.Gui, v *gocui.View) error { // _, cy := v.Cursor() // if line, err = v.Line(0); err != nil { // line = "" // } line := v.Buffer() // logger.Logger.Printf("LINE %s\n", line) if len(line) <= 0 { // return errors.New("input line empty") v.Clear() v.SetCursor(0, 0) return nil } line = strings.Replace(line, "\x00", "", -1) line = strings.Replace(line, "\n", "", -1) InputHistory.Add(line) if strings.HasPrefix(line, "//") || !strings.HasPrefix(line, "/") { if len(Server.CurrentChannel) > 0 { Server.Exec(Server.CurrentChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if Server.Client.Connected() { // logger.Logger.Println("SEND:::", spew.Sdump(line)) go Server.Client.Privmsg(Server.CurrentChannel, line) } return nil }) if mainView, err := g.View(Server.CurrentChannel); err != nil { return err } else { if mainView.Name() != client.StatusChannel { c := Server.FindChannel(Server.CurrentChannel) timestamp := time.Now().Format("03:04") fmt.Fprintf(mainView, "[%s] -> %s: %s\n", ui.ColorString(ui.TimestampColor, timestamp), myNickColor(c.FindUser(Server.Client.Me().Nick).String(false)), myTextColor(line)) } } } // send text } else { split := strings.Split(strings.Replace(line[1:], "\x00", "", -1), " ") // logger.Logger.Println("IN COMMAND!!!", line, spew.Sdump(split)) // mainView, _ := g.View(client.StatusChannel) // fmt.Fprintln(mainView, "$ COMMAND = ", split[0], len(split)) // TODO: what was this? if len(split) <= 1 { if split[0] == "p" || split[0] == "part" { command.Run(split[0], []string{"", Server.CurrentChannel}) v.Clear() v.SetCursor(0, 0) return nil } } if err := command.Run(split[0], split); err != nil { client.StatusMessage(v, err.Error()) } } // idleInputText := fmt.Sprintf("[%s] ", client.StatusChannel) // if len(command.CurrentChannel) > 0 { // idleInputText = fmt.Sprintf("[%s] ", command.CurrentChannel) // } // fmt.Fprint(v, idleInputText) // v.SetCursor(len(idleInputText), 0) v.Clear() v.SetCursor(0, 0) inCacheTab = false cacheTabSearch = "" cacheTabResults = []string{} FocusAndResetAll(g, v) return nil }
func BindHandlers() { for _, code := range client.IrcCodes { Server.Client.HandleFunc(code, func(conn *irc.Conn, line *irc.Line) { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { // client.StatusMessage(v, fmt.Sprintf("%s (CODE: %s)", line.Text(), line.Cmd)) client.StatusMessage(v, fmt.Sprintf("%s", line.Text())) return nil }) }) } Server.Client.HandleFunc("WHOIS", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("WHOIS -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("WHO", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("WHO -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("NOTICE", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("NOTICE -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("NICK", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("NICK -----------------------------", spew.Sdump(line)) for _, c := range Server.Channels { u := c.FindUser(line.Nick) if u != nil { u.Nick = line.Args[0] Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { fmt.Fprintf(v, "[%s] %s has changed nick to %s\n", color.GreenString("+NICK"), line.Nick, line.Args[0]) return nil }) } } }) Server.Client.HandleFunc("KICK", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("KICK -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("AWAY", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("AWAY -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("ACTION", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("ACTION -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("REGISTER", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("REGISTER -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("QUIT", func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Println("QUIT -----------------------------", spew.Sdump(line)) for _, c := range Server.Channels { u := c.FindUser(line.Nick) if u != nil { c.RemoveNick(line.Nick) Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { fmt.Fprintf(v, "[%s] %s [%s@%s] has quit [%s]\n", color.RedString("-EXIT"), line.Nick, line.Ident, line.Host, line.Text()) return nil }) } } }) Server.Client.HandleFunc("USER", func(conn *irc.Conn, line *irc.Line) { logger.Logger.Println("USER -----------------------------", spew.Sdump(line)) }) Server.Client.HandleFunc("TOPIC", func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Println("TOPIC -----------------------------", spew.Sdump(line)) if c, _, has := Server.HasChannel(line.Args[0]); has { Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { c.Topic = line.Args[1] fmt.Fprintf(v, "%s %s changed the topic of %s to: %s\n", color.GreenString("**"), line.Nick, line.Nick, c.Topic) return nil }) } }) Server.Client.HandleFunc("JOIN", func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Println("JOIN -----------------------------", line.Text()) // logger.Logger.Println("JOIN -----------------------------", spew.Sdump(line)) if c, _, has := Server.HasChannel(line.Text()); has { Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if line.Nick != Server.Client.Me().Nick { c.AddNick(line.Nick) } fmt.Fprintf(v, "[%s] %s [%s@%s] has joined %s\n", color.GreenString("+JOIN"), line.Nick, line.Ident, line.Host, c.Name) return nil }) } }) Server.Client.HandleFunc("PART", func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Println("PART -----------------------------", line.Text()) if c, _, has := Server.HasChannel(line.Text()); has { Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { c.RemoveNick(line.Nick) fmt.Fprintf(v, "[%s] %s [%s@%s] has quit [%s]\n", color.RedString("-PART"), line.Nick, line.Ident, line.Host, line.Text()) return nil }) } }) // nick in use Server.Client.HandleFunc("433", func(conn *irc.Conn, line *irc.Line) { Server.Exec(Server.CurrentChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { fmt.Fprintf(v, "%s %s\n", color.RedString("=="), fmt.Sprintf("Nick %s is already in use.", line.Nick)) return nil }) }) // op needed Server.Client.HandleFunc("482", func(conn *irc.Conn, line *irc.Line) { if c, _, has := Server.HasChannel(line.Args[1]); has { Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { fmt.Fprintf(v, "%s %s\n", color.RedString("=="), line.Text()) return nil }) } else { Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { fmt.Fprintf(v, "%s %s\n", color.RedString("=="), line.Text()) return nil }) } }) Server.Client.HandleFunc("331", func(conn *irc.Conn, line *irc.Line) { if c, _, has := Server.HasChannel(line.Args[1]); has { c.Topic = "N/A" } }) // // TOPIC // https://www.alien.net.au/irc/irc2numerics.html // Server.Client.HandleFunc("332", func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Println("TOPIC........", spew.Sdump(line)) Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if c, _, has := Server.HasChannel(line.Args[1]); has { c.Topic = line.Args[2] fmt.Fprintf(v, "%s Topic of %s: %s\n", color.GreenString("**"), line.Args[1], c.Topic) } return nil }) }) // names list done Server.Client.HandleFunc("366", func(conn *irc.Conn, line *irc.Line) { Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error { // v.Clear() // v.SetCursor(0, 0) // logger.Logger.Println("NICK LIST DONE") if c, _, has := s.HasChannel(line.Args[1]); has { go func(c *client.Channel) { for { select { case <-c.Loading.Recv: // logger.Logger.Println("INSIDE THE NAMES AND STUFF...") if !c.NickListReady { c.NickListReady = true c.NickListString(v) c.NickMetricsString(v) } break } } }(c) // var topic string // if len(c.Topic) <= 0 { // topic = "N/A" // } else { // topic = c.Topic // } // fmt.Fprintf(v, "⣿ CHANNEL: %s\n", c.Name) // fmt.Fprintf(v, "⣿ Users: %d\n", len(c.Names)) // fmt.Fprintf(v, "⣿ TOPIC: %s\n", topic) // fmt.Fprint(v, "⣿ NAMES: \n") // w := tabwriter.NewWriter(v, 0, 8, 3, ' ', tabwriter.DiscardEmptyColumns) // count := 1 // current := "" // for _, u := range c.Names { // if count < 7 { // current = current + fmt.Sprintf("%s\t", u) // count += 1 // } else { // fmt.Fprintln(w, current) // current = "" // count = 1 // } // } // if current != "" { // fmt.Fprintln(w, current) // } // w.Flush() // fmt.Fprint(v, "\n") } return nil }) }) // nick list Server.Client.HandleFunc("353", func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Printf("NICK LIST %s\n", spew.Sdump(line)) Server.Exec(line.Args[2], func(g *gocui.Gui, v *gocui.View, s *client.Server) error { if c, _, has := Server.HasChannel(line.Args[2]); has { nicks := strings.Split(line.Args[len(line.Args)-1], " ") for _, nick := range nicks { // UnrealIRCd's coders are lazy and leave a trailing space if nick == "" { continue } // logger.Logger.Printf("ADD NICK %s\n", spew.Sdump(nick)) user := &client.User{} switch c := nick[0]; c { case '~', '&', '@', '%', '+': nick = nick[1:] fallthrough default: switch c { case '~': // conn.st.ChannelModes(ch.Name, "+q", nick) case '&': // conn.st.ChannelModes(ch.Name, "+a", nick) case '@': user.Mode = "@" // conn.st.ChannelModes(ch.Name, "+o", nick) // fmt.Fprintf(v, "@%s ", nick) case '%': // conn.st.ChannelModes(ch.Name, "+h", nick) user.Mode = "%" case '+': user.Mode = "+" // conn.st.ChannelModes(ch.Name, "+v", nick) // fmt.Fprintf(v, "+%s ", nick) default: { // fmt.Fprintf(v, "+%s ", nick) } } } // logger.Logger.Printf("ADD NICK %s\n", spew.Sdump(nick)) if u := c.FindUser(nick); u == nil { user.Nick = nick user.Color = client.ANSIColors[rand.Intn(len(client.ANSIColors))] c.Users = append(c.Users, user) } } c.Loading.Send <- nil } return nil }) }) // Server.Client.HandleFunc("315", func(conn *irc.Conn, line *irc.Line) { // Server.Exec(line.Args[1], func(v *gocui.View, s *client.Server) error { // return nil // }) // }) // 328 // 331 -- no topic // 333 -- topic set by Server.Client.HandleFunc("333", func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Printf("TOPIC SET BY %s\n", spew.Sdump(line)) Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error { i, err := strconv.ParseInt(line.Args[3], 10, 64) if err != nil { logger.Logger.Printf(err.Error()) } tm := time.Unix(i, 0) if strings.Contains(line.Args[2], "!") { ss := strings.Split(line.Args[2], "!") fmt.Fprintf(v, "%s Topic set by %s [%s] [%s]\n", color.GreenString("**"), ss[0], ss[1], tm.Format(time.RFC822)) } else { fmt.Fprintf(v, "%s Topic set by %s [%s]\n", color.GreenString("**"), line.Args[2], tm.Format(time.RFC822)) } return nil }) }) Server.Client.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) { ircChan := line.Args[0] // logger.Logger.Printf("MSG %s %s %s %s\n", ircChan, line.Nick, line.Host, line.Args) if ircChan == Server.Client.Me().Nick { if c, _, has := Server.HasChannel(line.Nick); !has { Server.NewChannel(line.Nick, true) } else { if Server.CurrentChannel != line.Nick { c.Unread = true } } Server.Exec(line.Nick, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { timestamp := time.Now().Format("03:04") fmt.Fprintf(v, "[%s] <- %s: %s\n", timestampColor(timestamp), nickColor(line.Nick), line.Text()) notify.Push(fmt.Sprintf("Private message from %s", line.Nick), line.Text(), "", notificator.UR_NORMAL) return nil }) } else { if c, _, has := Server.HasChannel(ircChan); has { if Server.CurrentChannel != c.Name { c.Unread = true } Server.Exec(ircChan, func(g *gocui.Gui, v *gocui.View, s *client.Server) error { timestamp := time.Now().Format("03:04") var highlight bool if strings.Contains(line.Text(), Server.Client.Me().Nick) { highlight = true notify.Push(fmt.Sprintf("Highlight from %s", line.Nick), line.Text(), "", notificator.UR_NORMAL) } text := line.Text() style := "<-" if highlight { text = color.YellowString(text) style = color.YellowString("!!") } fmt.Fprintf(v, "[%s] %s %s: %s\n", timestampColor(timestamp), style, c.FindUser(line.Nick).String(true), text) return nil }) } } }) Server.Client.HandleFunc("464", func(conn *irc.Conn, line *irc.Line) { LoadingChannel.Send <- "done" }) Server.Client.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { // logger.Logger.Printf("LINE %s\n", spew.Sdump(line)) LoadingChannel.Send <- "done" }) Server.Client.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { LoadingChannel.Send <- "done" }) }
func Layout(g *gocui.Gui) error { maxX, maxY := g.Size() notify = notificator.New(notificator.Options{ AppName: Name, }) // if _, err := g.SetView("sidebar", -1, -1, int(0.2*float32(maxX)), maxY-3); err != nil { // if err != gocui.ErrorUnkView { // return err // } // } if err := HeaderView(g, -1, -1, maxX, 1); err != nil { panic(err) } if _, _, ok := Server.HasChannel(client.StatusChannel); !ok { status := client.Channel{ Status: true, Name: client.StatusChannel, MaxX: maxX, MaxY: maxY, RenderHandler: func(channel *client.Channel, view *gocui.View) error { view.Autoscroll = true view.Wrap = true view.Frame = false // view.FgColor = gocui.ColorGreen view.BgColor = gocui.ColorDefault fmt.Fprintln(view, "") fmt.Fprintln(view, Logo) fmt.Fprintln(view, color.GreenString(VersionLine)) client.StatusMessage(view, fmt.Sprintf("Welcome to the %s IRC client.", Name)) client.StatusMessage(view, "Type /help for a list of commands.\n") return nil }, } Server.AddChannel(&status) logger.Logger.Printf("LAYOUT %p %p\n", g, Server.Gui) if err := status.Render(false); err != nil { return err } BindHandlers() } else { for _, c := range Server.Channels { c.Update() } } if err := MenuView(g, maxX, maxY); err != nil { return err } // if err := InputView(g, 20, maxY-2, maxX, maxY); err != nil { // return err // } return nil }