summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lor.go17
-rw-r--r--main.go132
-rw-r--r--weather.go33
3 files changed, 182 insertions, 0 deletions
diff --git a/lor.go b/lor.go
new file mode 100644
index 0000000..011d03a
--- /dev/null
+++ b/lor.go
@@ -0,0 +1,17 @@
+package main
+
+import "dim13.org/rss"
+
+const newsRss = `https://www.linux.org.ru/section-rss.jsp?section=1`
+
+func FetchNews(n int) (s []string) {
+ news, _ := rss.Fetch(newsRss)
+ items := news.Channel.Items
+ if n > 0 {
+ items = items[:n]
+ }
+ for _, i := range items {
+ s = append(s, i.Title)
+ }
+ return
+}
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..1517f2d
--- /dev/null
+++ b/main.go
@@ -0,0 +1,132 @@
+package main
+
+import (
+ "container/ring"
+ "fmt"
+ "log"
+ "strconv"
+ "strings"
+ "time"
+
+ "dim13.org/theo"
+ "github.com/thoj/go-ircevent"
+)
+
+const (
+ server = "irc.rusnet.org.ru:6660"
+ room = "#lor"
+ name = "theo"
+)
+
+var (
+ buffer = ring.New(10)
+ cmds = make(map[string]CmdFn)
+ dscr []string
+ lastNews time.Time
+)
+
+type CmdFn func(*irc.Event, []string)
+
+func last(e *irc.Event, _ []string) {
+ conn := e.Connection
+ nick := e.Nick
+ buffer.Do(func(v interface{}) {
+ if v != nil {
+ ev := v.(*irc.Event)
+ conn.Privmsgf(nick, "%v: %v", ev.Nick, ev.Message())
+ }
+ })
+}
+
+func metar(e *irc.Event, arg []string) {
+ conn := e.Connection
+ metar, err := FetchMetar(arg[0])
+ if err != nil {
+ conn.Privmsg(room, err.Error())
+ } else {
+ conn.Privmsg(room, metar[1])
+ }
+}
+
+func help(e *irc.Event, _ []string) {
+ for _, m := range dscr {
+ e.Connection.Privmsg(room, m)
+ }
+}
+
+func news(e *irc.Event, arg []string) {
+ conn := e.Connection
+ n := 5
+ if len(arg) > 0 {
+ i, err := strconv.Atoi(arg[0])
+ if err == nil {
+ n = i
+ }
+ }
+ if time.Since(lastNews) > time.Minute {
+ for _, n := range FetchNews(n) {
+ conn.Privmsg(room, n)
+ lastNews = time.Now()
+ }
+ } else {
+ conn.Privmsg(room, e.Nick+", me just said it")
+ }
+}
+
+func register(cmd string, f func(*irc.Event, []string), help string) {
+ cmds[cmd] = f
+ h := fmt.Sprintf("!%v %v", cmd, help)
+ dscr = append(dscr, h)
+}
+
+func privmsg(e *irc.Event) {
+ conn := e.Connection
+ msg := e.Message()
+ nick := e.Nick
+
+ log.Println(nick, msg)
+
+ switch msg[0] {
+ case '!':
+ arg := strings.Fields(msg[1:])
+ if cmd, ok := cmds[arg[0]]; ok {
+ go cmd(e, arg[1:])
+ }
+ default:
+ if strings.Contains(msg, name) {
+ conn.Privmsg(room, theo.Theo())
+ }
+ buffer.Value = e
+ buffer = buffer.Next()
+ }
+}
+
+func init() {
+ register("last", last, "shows last 10 messages")
+ register("metar", metar, "<arg> shows weather report")
+ register("help", help, "shows this message")
+ register("top", news, "shows top 10 news")
+}
+
+// 001 Welcome
+// 332 Topic
+// 333 Unix Time
+// 353 Names list
+// 366 End of NAMES List
+// JOIN
+// CTCP_ACTION /me
+// PRIVMSG
+
+func main() {
+ con := irc.IRC(name, name)
+ err := con.Connect(server)
+ if err != nil {
+ log.Fatal(err)
+ }
+ con.AddCallback("001", func(e *irc.Event) {
+ e.Connection.Join(room)
+ log.Println("joined", room)
+ })
+ con.AddCallback("PRIVMSG", privmsg)
+ con.Loop()
+}
diff --git a/weather.go b/weather.go
new file mode 100644
index 0000000..ed4a139
--- /dev/null
+++ b/weather.go
@@ -0,0 +1,33 @@
+package main
+
+import (
+ "io/ioutil"
+ "net/http"
+ "strings"
+ "errors"
+)
+
+const (
+ noaa = `http://weather.noaa.gov/pub/data/observations/metar/`
+ noaaDecoded = noaa + `decoded/`
+ noaaStations = noaa + `stations/`
+)
+
+var notFound = errors.New("not found")
+
+func FetchMetar(s string) ([]string, error) {
+ loc := noaaStations + strings.ToUpper(s[:4]) + ".TXT"
+ resp, err := http.Get(loc)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode == http.StatusNotFound {
+ return nil, notFound
+ }
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+ return strings.Split(strings.TrimSpace(string(body)), "\n"), nil
+}