//A barebones IRC 'client' in the loosest sense of the word. //Takes input from console. If command starts with a '/', everything after is sent as a raw IRC command. //Otherwise the first argument is considered the channel/username, and the rest of the line is the message to send // as a privmsg. func main() { flag.Parse() fmt.Print("Simple Text-Based IRC Test Client\n\n") fmt.Printf("Connecting to %s . . . \n", *address) //LogClientHandler will handle printing out to stdio unless we change the default logger client, err := irc.NewClient(*address, *ssl, irc.LogHandler) if err != nil { log.Fatalf("Error: %s", err.Error()) } fmt.Print("Connected.\n\n") client.Send(irc.UserMessage(*username, "host", "domain", "realname")) client.Send(irc.NickMessage(*nick)) client.Send(irc.JoinMessage("#go_test")) //Listen for input. go readInput(client) for { //Continuously read from the client until an error occurs _, err := client.Read() if err != nil { fmt.Printf("ERROR: %s\n", err.Error()) fmt.Print("Exiting...") return } } }
//Join adds a webclient to the list of active clients. It blocks until webclient socket closes or chat ends func (c ircchat) Join(sessionID string, webclient irc.Conn) error { if !c.Active() { return errors.New("The chat session is not active or enabled. Check settings") } webclient.Write(irc.NickMessage(c.settings.Login.Nick)) //Send open channels to client for _, ch := range c.client.ChannelNames() { webclient.Write(irc.JoinMessage(ch)) //Send users in the rooms as a names reply commands (353 to indicate start, 366 to indicate end) //Webclient doesn't care about length, but a traditional IRC client will //TODO: Indicate if channel is public, private or secret ( "=" / "*" / "@" ), current sends as pub //:tepper.freenode.net 353 goirctest @ #gotest :goirctest @Oooska //:tepper.freenode.net 366 goirctest #gotest :End of /NAMES list. users, _ := c.client.Users(ch) namesRepl := fmt.Sprintf("353 %s = %s :%s", c.settings.Login.Nick, ch, strings.Join(users, " ")) namesEndRepl := fmt.Sprintf("366 %s %s", c.settings.Login.Nick, ch) webclient.Write(irc.NewMessage(namesRepl)) webclient.Write(irc.NewMessage(namesEndRepl)) messages, err := persistenceInstance.messages(c.account, ch, time.Now(), 200) if err != nil { log.Printf("Error retrieving message logs: %s", err.Error()) } for _, msg := range messages { webclient.Write(msg) } } //Register as a listener c.registerClient(sessionID, webclient) for { select { case <-c.quit: fmt.Println("Exiting ircClientListener") return errors.New("IRC Session has ended") default: msg, err := webclient.Read() if err != nil { c.unregisterClient(sessionID) return err } c.toServer <- clientMessage{SessionID: sessionID, Message: msg} } } }
func startSession(user iwcUser) error { //Start the IRC connection... //TODO: Move this elsewhere. conn, err := irc.NewIRCConnection(user.profile.address, false) if err != nil { return err } //Channel to accept new http clients logging in var newClients chan *ircClient = make(chan *ircClient) conn.Write(irc.UserMessage(user.username, "servername", "hostname", user.profile.realname)) conn.Write(irc.NickMessage(user.profile.nick.name)) conn.Write(irc.NewMessage("join #gotest")) go ircManager(conn, newClients) log.Println("Starting session for ", user.username) sessionNewClientsMap[user.username] = newClients return nil }
//Start connects to the IRC server, authenticates, and then starts a goroutine to manage the chat func (c *ircchat) Start() error { var err error if !c.running { saveHandler := func(msg irc.Message) { cmd := msg.Command() //Check to make sure it's a message worth saving if cmd == "PRIVMSG" || cmd == "ACTION" { err := persistenceInstance.saveMessage(c.account, msg) if err != nil { log.Printf("Error saving message: %s", err.Error()) } } } var client irc.Client client, err = irc.NewClient(fmt.Sprintf("%s:%d", c.settings.Address, c.settings.Port), c.settings.SSL) if err != nil { log.Printf("Error starting chat for %s: %s", c.account.Username(), err.Error()) return err } client.AddHandler(irc.Both, saveHandler) c.client = client err = client.Write(irc.UserMessage(c.account.Username(), "ircwebchathost", "somewhere", "quack")) login := c.settings.Login if err == nil && login.Nick != "" { err = client.Write(irc.NickMessage(c.settings.Login.Nick)) if err == nil && login.Password != "" { err = client.Write(irc.PrivMessage("NickServ", "identify "+login.Password)) } } //TODO: Auto join rooms if err == nil { c.running = true go ircManager(*c) } else { c.Stop() } } return err }