Skip to content

Instantly share code, notes, and snippets.

@FSX
Last active December 20, 2015 11:39
Show Gist options
  • Save FSX/6125218 to your computer and use it in GitHub Desktop.
Save FSX/6125218 to your computer and use it in GitHub Desktop.

Revisions

  1. FSX revised this gist Jul 31, 2013. No changes.
  2. FSX created this gist Jul 31, 2013.
    10 changes: 10 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    Installation

    ```
    $ mkdir Go && cd Go
    $ mkdir -p {bin,pkg,src,src/pikabot,src/pikachu}
    # Put content of pikachu.go in src/pikachu
    # Put content of pikabot.go in src/pikabot and edit pikabot.go
    $ go install pikabot
    $ ./bin/pikabot
    ```
    108 changes: 108 additions & 0 deletions pikabot.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@
    package main

    import (
    "fmt"
    "math/rand"
    "os"
    "os/signal"
    "pikachu"
    "strings"
    "time"
    )

    // https://en.wikiquote.org/wiki/Pok%C3%A9mon
    // http://www.pokemonquotes.com/brock-quotes/
    var QUOTES []string = []string{
    // Pikachu
    "“PIKA!” — Pikachu",
    "“Pika Pika” — Pikachu",
    "“Pika Pi” — Pikachu",
    "“Chuuuuu” — Pikachu",
    "“Pi-pi-pi” — Pikachu",
    "“PIKA-CHU-UUUUUUU!” — Pikachu",
    "“Pi Pikachu!” — Pikachu",

    // Brock
    "“Hey I know! I'll use my trusty frying pan as a drying pan!” — Brock",
    "“How about some prune juice!?” — Brock",
    "“I believe in rock-hard defense and determination!” — Brock",
    "“Her temper could sure use a little evolution.” — Brock",
    "“Don't you worry, Totodile, I'm gonna teach you how to be successful in love, just like me!” — Brock",
    "“When you have lemons, you make lemonade; and when you have rice, you make rice balls.” — Brock",
    "“For me, summer means bathing suits and girls to wear them!” — Brock",
    "“DON'T YOU GET IT?!! If two Butterfree fall in love, their trainers can meet, and THEY CAN FALL IN LOVE, TOO!” — Brock",
    "“AHH! I wasted a donut!” — Brock",
    "“Ash and Misty, sittin' in a tree... Ha ha ha ha ha!” — Brock",
    "“Time to dry up, water girl!” — Brock",
    "“I never forget the face of a pretty girl! This book helps me remember their names.” — Brock",
    "“This is the only song I know.” — Brock",

    // Misty
    "“If I want your opinion I'LL ASK FOR IT!!!” — Misty",
    "“HE'S NOT MY BOYFRIEND!” — Misty",
    "“Well, Ash Ketchum... finally, I know how you feel about me.” — Misty",
    "“Pikachu, you're a Pika-pal!” — Misty",
    "“Well, my name.....My name is Anne Chovie.” — Misty",

    // Ash Ketchum
    "“Choose it or lose it!” — Ash Ketchum",
    "“I'm twice as good as Gary!” — Ash Ketchum",
    "“It was an egg-cident! Get it? 'Egg?'” — Ash Ketchum",
    "“I have my own method of bending spoons. (bends the spoon with his hands) Ha! Muscle over mind!” — Ash Ketchum",
    "“Please don't eat my hat.” — Ash Ketchum",
    "“I'm having a major hat crisis. Could you try to steal Pikachu some other time?” — Ash Ketchum",
    "“Uh, my... name... is... Ketchup! No, wait! My name is really Tom Ato!” — Ash Ketchum",
    "“Let's eat fast so we can eat again!” — Ash Ketchum",
    "“That mini-Misty is even more scary than she is.” — Ash Ketchum",
    "“You look like a guy anyway!” — Ash Ketchum",
    "“Please don't stare at me like that! I'm a very shy little girl!” — Ash Ketchum",
    "“You guys go, I'll be fine. Just don't bring my mom home too late.” — Ash Ketchum",
    "“Yo, Brocko!” — Ash Ketchum",
    "“I choose you pikachu!” — Ash Ketchum",

    // Prof. Oak
    "“So, tell me about yourself. Are you a boy or a girl?” — Prof. Oak",
    "“This is my grandson. He's been your rival since you were both babies. Err... what was his name again...?” — Prof. Oak",
    "“You look more like you're ready for bed than Pokémon training.” — Prof. Oak",
    "“There's an ongoing debate in the academic community as to whether these Pidgey represent evolution, devolution, or some mutated strain.” — Prof. Oak",
    }

    func main() {
    rand.Seed(time.Now().UnixNano())
    l := len(QUOTES)

    // Setup IRC bot
    p, err := pikachu.Connect(
    "irc.zeronode.net:6667",
    "Pikachu",
    "Pikachu", "",
    "#Hive5")
    if err != nil {
    panic(err)
    }
    defer p.Close()

    // Graceful shutdown for Ctrl+C
    go func() {
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)
    <-c

    p.Close()
    os.Exit(0)
    }()

    // Listen to receiving channel
    for {
    message, ok := <-p.Receive
    if ok == false {
    break
    }

    fmt.Println("IN: ", message)

    if message.Command == "PRIVMSG" && strings.HasPrefix(message.Final, "!pokemon") {
    p.Privmsg(message.Arguments[0], QUOTES[rand.Intn(l)])
    }
    }
    }
    154 changes: 154 additions & 0 deletions pikachu.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,154 @@
    package pikachu

    import (
    "bufio"
    "fmt"
    "net"
    "strings"
    )

    type Message struct {
    Prefix string
    Command string
    Arguments []string
    Final string
    }

    type Pikachu struct {
    address string
    nickname string
    username string
    password string
    channel string // Maybe list?
    connection net.Conn
    Send chan string // Messages to the server
    Receive chan Message // Messages from the server
    }

    func Connect(address, nickname, username, password, channel string) (p *Pikachu, err error) {
    p = &Pikachu{address, nickname, username, password, channel, nil, nil, nil}
    err = p.Connect()
    return
    }

    func (p *Pikachu) Connect() (err error) {
    p.Send = make(chan string)
    p.Receive = make(chan Message)

    if p.connection, err = net.Dial("tcp", p.address); err != nil {
    return
    }

    go func() {
    var (
    message Message
    init bool = true
    )
    reader := bufio.NewReader(p.connection)

    for {
    line, err := reader.ReadString('\n')
    if err != nil {
    break
    }

    message = p.ParseMessage(line)
    p.Receive <- message

    if message.Command == "PING" {
    p.Pong(message.Final)
    }

    if init {
    if message.Command == "266" {
    init = false
    p.Join(p.channel)
    }
    }
    }
    }()

    p.User(p.username, p.nickname)
    p.Nick(p.nickname)

    return
    }

    // [:prefix ](command )[arguments ]*[ :final_argument]
    func (p *Pikachu) ParseMessage(line string) Message {
    var (
    prefix string
    command string
    arguments []string
    final string
    )

    if pos := strings.Index(line, " :"); pos != -1 {
    arguments, final = strings.Split(line[:pos], " "), line[pos+2:len(line)-2]
    } else {
    arguments = strings.Split(line, " ")
    }

    if arguments[0][0] == ':' && len(arguments) >= 2 {
    prefix = arguments[0]
    command = arguments[1]
    arguments = arguments[2:]
    } else {
    command = arguments[0]
    arguments = arguments[1:]
    }

    return Message{prefix, command, arguments, final}
    }

    // server_or_nick[!user[@hostname]]
    func (p *Pikachu) ParsePrefix(source string) (server_or_nick, user, host string) {
    if n := strings.IndexRune(source, '!'); n != -1 {
    server_or_nick = source[:n]
    if m := strings.IndexRune(source, '@'); m != -1 {
    user = source[n:m]
    host = source[m:]
    }
    } else {
    server_or_nick = source
    }

    return
    }

    func (p *Pikachu) Close() {
    p.connection.Close()
    close(p.Send)
    close(p.Receive)
    }

    func (p *Pikachu) Write(data string) {
    fmt.Println("OUT: ", data)
    if _, err := p.connection.Write([]byte(data + "\r\n")); err != nil {
    panic(err)
    }
    }

    func (p *Pikachu) User(username, realname string) {
    p.Write(fmt.Sprintf("USER %s +iw * :%s", username, realname))
    }

    func (p *Pikachu) Nick(nickname string) {
    p.Write(fmt.Sprintf("NICK %s", nickname))
    }

    func (p *Pikachu) Join(channel string) {
    p.Write(fmt.Sprintf("JOIN %s", channel))
    }

    func (p *Pikachu) Pong(payload string) {
    p.Write(fmt.Sprintf("PONG :%s", payload))
    }

    func (p *Pikachu) Privmsg(target, message string) {
    p.Write(fmt.Sprintf("PRIVMSG %s :%s", target, message))
    }

    func (p *Pikachu) Quit(message string) {
    p.Write(fmt.Sprintf("QUIT :%s", message))
    }