/
doofus.go
153 lines (135 loc) · 3.59 KB
/
doofus.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Command doofus implements a Telegram bot that fetches Magic Card information.
package main
import (
"fmt"
"io"
"log"
"math/rand"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/broady/mtgprice/mtgprice"
"github.com/nf/doofus/deckbrew"
"github.com/tucnak/telebot"
)
const (
bot = "DoofusBot"
maxMatches = 30
)
func main() {
rand.Seed(time.Now().UnixNano())
cards, err := mtgprice.Open(mtgprice.Opts{Filename: "mtgprice.kv", CardData: "AllCards.json"})
if err != nil {
log.Fatal("loading cards:", err)
}
closeOnTerm(cards)
bot, err := telebot.NewBot(os.Getenv("TOKEN"))
if err != nil {
log.Fatal(err)
}
messages := make(chan telebot.Message)
bot.Listen(messages, 1*time.Minute)
for msg := range messages {
if err := handleMessage(cards, bot, msg); err != nil {
log.Printf("Error handling message %v: %v", msg, err)
}
}
}
func closeOnTerm(c io.Closer) {
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
go func() {
<-ch
log.Printf("shutting down...")
if err := c.Close(); err != nil {
log.Fatalf("clean up error: %v", err)
}
os.Exit(1)
}()
}
func handleMessage(cards *mtgprice.Client, bot *telebot.Bot, m telebot.Message) error {
reply := func(s string) error { return bot.SendMessage(m.Chat, s, nil) }
switch m.Text {
case "/dobis":
return reply(dobis[rand.Intn(len(dobis))])
case "/help":
return reply(helpText)
}
q, ok := isSearch(m.Text)
if !ok {
return nil
}
t0 := time.Now()
result, err := cards.Query(q)
if err != nil {
return reply("Error: " + err.Error())
}
s := ""
switch len(result) {
case 0:
s = fmt.Sprintf("I don't know what %q is.", q)
case 1:
ci := result[0]
img := make(chan string)
go func() {
m, err := deckbrew.Search(ci.Name)
if err != nil || len(m) == 0 || len(m[0].Editions) == 0 {
img <- ""
return
}
u := m[0].Editions[0].Image_URL
if u == "https://image.deckbrew.com/mtg/multiverseid/0.jpg" {
img <- ""
return
}
img <- "\n" + u
}()
c, err := cards.RichInfo(ci.Name)
if err != nil {
return reply("Error: " + err.Error())
}
s = c.Detail()
if c.TCGPrice != nil {
s += fmt.Sprintf("\nTCG %v", c.TCGPrice)
}
s += <-img
fmt.Println(time.Since(t0))
default:
if len(result) > maxMatches {
s = fmt.Sprintf("I know %v cards like %q. Be more specific.", len(result), q)
break
}
s = fmt.Sprintf("I know a few cards like %q:", q)
for _, c := range result {
s += "\n " + c.Name
}
}
return reply(s)
}
func isSearch(t string) (q string, ok bool) {
const a, b = "/card ", "@" + bot + " "
switch {
case strings.HasPrefix(t, a):
return strings.TrimPrefix(t, a), true
case strings.HasPrefix(t, b):
return strings.TrimPrefix(t, b), true
}
return "", false
}
var dobis = []string{
"Just two boys doing business.",
"We're Dobis P.R.",
"That's who we are.",
"Doing business.",
`Uh, "Dear Mr. Weebs, We are very, very, very, very excited to meet you. We are Dobis." That's all I've got so far.`,
"I'm Tim Heidecker. This is Eric Wareheim. We are Dobis P.R., and we're here to tell you about our plan to revitalize the S'wallow Valley Mall.",
"That's the pride of Dobis.",
"Dobis in the house.",
"Official Dobis reps here, stopping in for a meet-and-greet.",
"Taquito, we just had a Dobis meeting, and we've decided to let you run the mall fountain.",
"I guess I'll just stay here and work on Dobis.",
"Guys, tomorrow is our big day, and Dobis couldn't be more jazzed about it. But right now I want to have a little fun, with the permission of my best friend Tim.\nMuyo permissiono granted.",
}
const helpText = "sorry"