Ejemplo n.º 1
0
func Register(b *bot.Bot) {
	if len(*chans) == 0 {
		log.Printf("skipping paste init: no channels to notify")
		return
	}

	b.OnConnect(addServer)
	b.OnDisconnect(delServer)

	go pasteloop()
}
Ejemplo n.º 2
0
func Register(b *bot.Bot) {
	if len(*chans) == 0 {
		log.Printf("skipping paste init: no channels to notify")
	}

	b.OnConnect(addServer)
	b.OnDisconnect(delServer)

	url, err := url.Parse(*psrvurl)
	if err != nil {
		log.Fatalf("paste: bad url %q: %s", *psrvurl, err)
	}

	psrv := proto.NewGoPasteWebClient(webrpc.ProtoBuf, url)
	go waitloop(psrv)
}
Ejemplo n.º 3
0
// Run creates the proper bindings on the bot and listens for commands on its
// servers.  This function does not exit, and so it should be called in its own
// goroutine if further work needs to be done.
func Run(b *bot.Bot, startchar byte, cmds []*Command) {
	// Handy local type for bundling data
	type event struct {
		name string
		srv  *bot.Server
		msg  *bot.Message
	}

	// Make the event handler
	events := make(chan event, 10)
	handle := func(evname string, srv *bot.Server, msg *bot.Message) {
		events <- event{evname, srv, msg}
	}

	// Listen for the events we want
	for _, evname := range []string{
		bot.ON_CHANMSG,
		bot.ON_PRIVMSG,
		bot.ON_NOTICE,
	} {
		b.OnEvent(evname, handle)
	}

	// Sort the commands for help
	sort.Sort(commandSorter(cmds))

	// Map the commands for easy access
	cmdmap := make(map[string][]*Command, len(cmds))
	cmdlen := 0
	for _, cmd := range cmds {
		cmd.name = strings.ToUpper(cmd.name)
		cmdmap[cmd.name] = append(cmdmap[cmd.name], cmd)
		if l := len(cmd.name); l > cmdlen {
			cmdlen = l
		}
	}

	log.Printf("Command length: %d", cmdlen)

	// Add ping
	if _, ok := cmdmap["PING"]; !ok {
		c := &Command{
			name: "PING",
			help: "Built-in CTCP PING handler",
			priv: true,
			hook: func(s *Source, r *Response, cmd string, args []string) {
				r.Private()
				r.Printf("PING %s", strings.Join(args, " "))
			},
		}
		cmdmap["PING"] = append(cmdmap["PING"], c)
		cmds = append(cmds, c)
	}

	// Add the help command
	if _, ok := cmdmap["HELP"]; !ok {
		c := &Command{
			name: "HELP",
			help: "Online help",
			priv: false,
		}
		cmdmap["HELP"] = append(cmdmap["HELP"], c)
		cmds = append(cmds, c)
		c.hook = genhelp(cmds, cmdlen)
	}

	// Wait for events and handle them
	for e := range events {
		// Ignore malformatted messages
		if len(e.msg.Args) < 2 || len(e.msg.Args[1]) == 0 {
			continue
		}

		// Determine if it is a command (CTCP or with the leader char)
		text, ctcp := e.msg.Args[1], false
		switch text[0] {
		case 0x01:
			text, ctcp = DecodeCTCP(text), true
		case startchar:
			text = text[1:]
		default:
			if e.name == bot.ON_CHANMSG {
				continue
			}
		}

		if text == "" {
			continue
		}

		// Parse the command into arguments
		command, args := "", strings.Fields(text)
		command, args = args[0], args[1:]

		// Look up the command
		cmd, ok := cmdmap[strings.ToUpper(command)]
		if !ok {
			continue
		}

		// Build the reply
		replies := make(chan *bot.Message, 10)
		go func() {
			if ctcp {
				for m := range replies {
					switch m.Command {
					case bot.CMD_PRIVMSG:
						fallthrough
					case bot.CMD_NOTICE:
						if len(m.Args) > 1 {
							m.Args[1] = EncodeCTCP(m.Args[1])
						}
					}
					e.srv.WriteMessage(m)
				}
				return
			}
			for m := range replies {
				e.srv.WriteMessage(m)
			}
		}()
		resp := &Response{
			out: replies,
		}
		src := &Source{
			server:  e.srv,
			message: e.msg,
		}

		// Set the public/private responses
		nick := e.msg.ID().Nick
		switch e.name {
		case bot.ON_CHANMSG:
			resp.public = e.msg.Args[0]
			resp.private = nick
		case bot.ON_PRIVMSG:
			resp.public = nick
			resp.private = nick
		case bot.ON_NOTICE:
			resp.public = ""
			resp.private = ""
		}

		// Call the hook
		for _, cmd := range cmd {
			cmd.hook.call(src, resp, command, args)
		}
	}
}