From 18a149335b6c5f187e65a374d18ce69ec2c17d22 Mon Sep 17 00:00:00 2001 From: Chris Rhodes Date: Sat, 16 Feb 2013 19:57:54 -0800 Subject: [PATCH] Add a listener for YouTube and URLs, and spit out the Video Name or Title back to the sourc. --- client.go | 3 +++ client/funcs.go | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ client/line.go | 23 ++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 client/funcs.go diff --git a/client.go b/client.go index 0ff9d18..af65da9 100644 --- a/client.go +++ b/client.go @@ -26,6 +26,9 @@ func main() { c.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) + c.HandleFunc(irc.PRIVMSG, YouTubeFunc) + c.HandleFunc(irc.PRIVMSG, UrlFunc) + // set up a goroutine to read commands from stdin in := make(chan string, 4) reallyquit := false diff --git a/client/funcs.go b/client/funcs.go new file mode 100644 index 0000000..65b4164 --- /dev/null +++ b/client/funcs.go @@ -0,0 +1,71 @@ +package client + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "regexp" + "strings" +) + +type youTubeVideo struct { + Entry struct { + Info struct { + Title struct { + Text string `json:"$t"` + } `json:"media$title"` + Description struct { + Text string `json:"$t"` + } `json:"media$description"` + } `json:"media$group"` + Rating struct { + Likes string `json:"numLikes"` + Dislikes string `json:"numDislikes"` + } `json:"yt$rating"` + Statistics struct { + Views string `json:"viewCount"` + } `json:"yt$statistics"` + } `json:entry` +} + +func UrlFunc(conn *Conn, line *Line) { + text := line.Message() + if regex, err := regexp.Compile(`(\s|^)(http://|https://)(.*?)(\s|$)`); err == nil { + url := strings.TrimSpace(regex.FindString(text)) + if url != "" { + if resp, err := http.Get(url); err == nil { + if strings.HasPrefix(resp.Header.Get("Content-Type"), "text/html") { + defer resp.Body.Close() + if content, err := ioutil.ReadAll(resp.Body); err == nil { + if regex, err := regexp.Compile(`(.*?)`); err == nil { + if regex.Match([]byte(content)) { + conn.Privmsg(line.Target(), strings.TrimSpace(regex.FindStringSubmatch(string(content))[1])) + } + } + } + } + } + } + } +} + +func YouTubeFunc(conn *Conn, line *Line) { + text := line.Message() + if regex, err := regexp.Compile(`(\s|^)(http://|https://)?(www.)?(youtube.com/watch\?v=|youtu.be/)(.*?)(\s|$|\&|#)`); err == nil { + if regex.Match([]byte(text)) { + matches := regex.FindStringSubmatch(text) + id := matches[len(matches)-2] + url := fmt.Sprintf("https://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=json", id) + if resp, err := http.Get(url); err == nil { + defer resp.Body.Close() + if contents, err := ioutil.ReadAll(resp.Body); err == nil { + var data youTubeVideo + if err := json.Unmarshal(contents, &data); err == nil { + conn.Privmsg(line.Target(), fmt.Sprintf("%s - %s views (%s likes, %s dislikes)", data.Entry.Info.Title.Text, data.Entry.Statistics.Views, data.Entry.Rating.Likes, data.Entry.Rating.Dislikes)) + } + } + } + } + } +} diff --git a/client/line.go b/client/line.go index b29a8fe..2cb53e1 100644 --- a/client/line.go +++ b/client/line.go @@ -88,3 +88,26 @@ func parseLine(s string) *Line { } return line } + +// Return the contents of the message portion of a line. +// This only really makes sense for messages with a :message portion, but there +// are a lot of them. +func (line *Line) Message() string { + if len(line.Args) > 0 { + return line.Args[len(line.Args)-1] + } + return "" +} + +// Return the target of the line. This only really makes sense for PRIVMSG. +// If the line was broadcast from a channel, the target will be that channel. +// If the line was broadcast by a user, the target will be that user. +func (line *Line) Target() string { + if line.Cmd == PRIVMSG { + if !strings.HasPrefix(line.Args[0], "#") { + return line.Nick + } + return line.Args[0] + } + return "" +}