goirc/handler.go

228 lines
4.7 KiB
Go
Raw Normal View History

2010-10-14 01:16:16 +00:00
package main
import (
"irc"
"fmt"
2010-10-14 01:16:16 +00:00
"strings"
"http"
2010-10-16 01:07:46 +00:00
"xml"
"strconv"
2010-10-14 01:16:16 +00:00
)
var commands = map [string]func(*irc.Conn, *irc.Nick, string, string) {
2010-10-27 01:21:51 +00:00
// access
2010-10-16 19:38:40 +00:00
"flags": flags,
"add": add,
2010-10-16 22:37:29 +00:00
"remove": remove,
2010-11-03 21:17:46 +00:00
"list": accesslist,
2010-11-05 23:28:32 +00:00
// admin
"nick": nick,
2010-10-16 22:47:04 +00:00
"say": csay,
2010-10-26 21:21:08 +00:00
2010-10-27 01:21:51 +00:00
// op
2010-10-26 21:21:08 +00:00
"halfop": halfop,
"hop": halfop,
"op": op,
"deop": deop,
"dehalfop": dehalfop,
"dehop": dehalfop,
2010-10-27 05:49:57 +00:00
"voice": voice,
"devoice": devoice,
2010-10-26 21:21:08 +00:00
"kick": kick,
"k": kick,
2010-10-26 22:31:19 +00:00
"b": ban,
"ban": ban,
"unban": unban,
"u": unban,
"kb": kickban,
2010-10-27 01:21:51 +00:00
"topic": topic,
"appendtopic": appendtopic,
2010-11-04 01:15:27 +00:00
"part": part,
2010-10-14 01:16:16 +00:00
2010-10-27 01:21:51 +00:00
// google
"tr": translate,
2010-10-28 19:00:31 +00:00
"roman": roman,
"calc": calc,
2010-10-27 01:21:51 +00:00
}
2010-10-14 01:16:16 +00:00
func handlePrivmsg(conn *irc.Conn, line *irc.Line) {
nick := conn.GetNick(line.Nick)
if nick == nil {
return
2010-10-18 23:55:41 +00:00
}
nick.Host = line.Host
2010-10-18 23:55:41 +00:00
2010-10-14 01:16:16 +00:00
target := line.Args[0]
2010-10-16 19:38:40 +00:00
if isChannel(target) {
2010-10-14 01:16:16 +00:00
// message to a channel
if start := strings.Index(line.Text, "youtube.com/watch?v="); start > -1 {
video := line.Text[start+20:]
if end := strings.IndexAny(video, " &#"); end > -1 {
video = video[0:end]
2010-10-18 18:58:49 +00:00
}
youtube(conn, nick, video, target)
} else {
command(conn, nick, line.Text, target)
2010-10-16 01:07:46 +00:00
}
2010-10-15 21:13:53 +00:00
} else if target == conn.Me.Nick {
2010-10-14 01:16:16 +00:00
// message to us
command(conn, nick, line.Text, line.Nick)
2010-10-14 01:16:16 +00:00
}
}
func handleMode(conn *irc.Conn, line *irc.Line) {
if line.Args[0] == conn.Me.Nick && line.Text == "+r" {
autojoin(conn)
}
}
2010-10-27 05:49:57 +00:00
func handleJoin(conn *irc.Conn, line *irc.Line) {
// autovoice users with v flag
if line.Nick == conn.Me.Nick {
return
}
channel := conn.GetChannel(line.Text)
if channel == nil || !channel.Modes.Moderated {
return
}
privs := conn.Me.Channels[channel]
if !(privs.Op || privs.Admin || privs.HalfOp || privs.Owner) {
return
}
nick := conn.GetNick(line.Nick)
if nick == nil {
return
}
if hasAccess(conn, nick, line.Text, "v") {
conn.Mode(line.Text, "+v " + line.Nick)
}
}
func handleInvite(conn *irc.Conn, line *irc.Line) {
if line.Args[0] != conn.Me.Nick {
return
}
user := line.Src[strings.Index(line.Src, "!")+1:]
if user[0] == '~' {
user = user[1:]
}
owner, _ := auth.String(conn.Network, "owner")
if user == owner {
conn.Join(line.Text)
}
}
2010-10-16 19:38:40 +00:00
func isChannel(target string) bool {
return target[0] == '#' || target[0] == '&'
}
func command(conn *irc.Conn, nick *irc.Nick, text, target string) {
if !strings.HasPrefix(text, trigger) {
2010-10-14 01:16:16 +00:00
return
}
split := strings.Split(text, " ", 2)
if len(split[0]) < 2 {
return
}
handler := commands[split[0][1:]]
if handler != nil {
if len(split) > 1 {
handler(conn, nick, split[1], target)
} else {
handler(conn, nick, "", target)
}
}
}
func say(conn *irc.Conn, target, message string, a ...interface{}) {
2010-10-16 19:38:40 +00:00
text := strings.Replace(fmt.Sprintf(message, a...), "\n", " ", -1)
if isChannel(target) {
conn.Privmsg(target, text)
} else {
conn.Notice(target, text)
}
}
func youtube(conn *irc.Conn, nick *irc.Nick, video, channel string) {
2010-10-16 01:07:46 +00:00
url := fmt.Sprintf("http://gdata.youtube.com/feeds/api/videos/%s?v=2", video)
response, _, err := http.Get(url)
defer response.Body.Close()
if err != nil {
return
}
type duration struct {
Seconds string "attr"
}
type group struct {
Duration duration
}
type entry struct {
Title string
Group group
}
var yte = entry{"", group{duration{""}}}
err = xml.Unmarshal(response.Body, &yte)
if err != nil {
2010-10-16 01:07:46 +00:00
return
}
seconds, err := strconv.Atoui(yte.Group.Duration.Seconds)
if err == nil {
minutes := seconds / 60
seconds = seconds % 60
hours := minutes / 60
minutes = minutes % 60
var durationStr string
if hours > 0 {
durationStr = fmt.Sprintf("%d:%02d:%02d", hours, minutes, seconds)
} else {
durationStr = fmt.Sprintf("%02d:%02d", minutes, seconds)
}
say(conn, channel, "%s's video: %s, %s", nick.Nick, yte.Title, durationStr)
2010-10-16 01:07:46 +00:00
} else {
say(conn, channel, "%s's video: %s", nick.Nick, yte.Title)
2010-10-16 01:07:46 +00:00
}
}
// this allows target to be a channel or a privmsg in which the channel is the first argument
// passing a flag of "" will check if the user has any access
// returns the channel the user has access on and remaining args
// or a blank channel if the user doesn't have access on that channel
func parseAccess(conn *irc.Conn, nick *irc.Nick, target, args, flag string) (string, string) {
channel, args := parseChannel(target, args)
if channel == "" {
return "", args
}
if hasAccess(conn, nick, channel, flag) {
return channel, args
}
return "", args
}
func parseChannel(target, args string) (string, string) {
var channel string
if isChannel(target) {
channel = target
} else {
split := strings.Split(args, " ", 2)
if split[0] != "" && isChannel(split[0]) {
channel = split[0]
if len(split) == 2 {
args = split[1]
} else {
args = ""
}
} else {
return "", args
}
}
return channel, args
}