Example #1
0
func onCommand(bot *telebot.Bot, command string, args []string) {
	if command == "msg" && len(args) > 1 {
		user := config.GetUser(args[0])
		if user.UID == config.NilUser.UID {
			log.Errorf("[Syscmds] Couldn't get an user with the name or UID %s", args[0])
		}

		msg := connect(args[1:])
		bot.SendMessage(user, "*[Sysadmin]* "+msg, util.Markdown)
		log.Infof("[Syscmds] Sent message %[1]s to %[2]s", msg, user.Name)
	} else if command == "broadcast" && len(args) > 0 {
		msg := connect(args)
		for _, user := range config.GetAllUsers() {
			bot.SendMessage(user, "*[Sysadmin Broadcast]* "+msg, util.Markdown)
		}
		log.Infof("[Syscmds] Broadcasted message %[1]s", msg)
	} else if command == "config" && len(args) > 0 {
		if strings.EqualFold(args[0], "save") {
			if !config.IndentConfig && len(args) > 1 && strings.EqualFold(args[0], "pretty") {
				config.IndentConfig = true
				config.Save()
				config.IndentConfig = false
			} else {
				config.Save()
			}
		} else if strings.EqualFold(args[0], "load") {
			config.Load()
		}
	} else if command == "stop" {
		Shutdown("Sysadmin")
	}
}
Example #2
0
// Loop is an infinite loop that checks for new Ranssi posts
func Loop(bot *telebot.Bot, noNotifAtInit bool) {
	for {
		readNow := config.GetConfig().LastReadPost + 1

		node := getPost(readNow)
		if node != nil {
			topic := strings.TrimSpace(node.FirstChild.FirstChild.Data)

			log.Infof("[Posts] New post detected: %s (ID %d)", topic, readNow)

			if !noNotifAtInit {
				config.GetUsersWithSettingAndRun(func(u config.User) {
					bot.SendMessage(u, lang.Translatef(u, "posts.new", topic, readNow), util.Markdown)
				}, subSetting)
			}

			config.GetConfig().LastReadPost = readNow
			config.ASave()
			updateNews()
			time.Sleep(5 * time.Second)
			continue
		}
		noNotifAtInit = false
		time.Sleep(1 * time.Minute)
	}
}
Example #3
0
// HandleCommand handles a /language command
func HandleCommand(bot *telebot.Bot, message telebot.Message, args []string) {
	sender := config.GetUserWithUID(message.Sender.ID)
	if len(args) > 0 {
		lang := GetLanguage(args[0])
		if lang == nil {
			bot.SendMessage(message.Chat, Translatef(sender, "lang.notfound", lang.Name), util.Markdown)
			return
		}

		if len(args) > 1 {
			user := config.GetUser(args[1])
			if user.UID != config.NilUser.UID && !sender.HasPermission(langChangeOtherPerm) {
				bot.SendMessage(message.Chat, Translatef(sender, "error.noperms", langChangeOtherPerm), util.Markdown)
				return
			}

			user.SetSetting("language", lang.Name)
			bot.SendMessage(message.Chat, Translatef(sender, "lang.changed.other", lang.Name, user.Name), util.Markdown)
		} else {
			sender.SetSetting("language", lang.Name)
			bot.SendMessage(message.Chat, Translatef(sender, "lang.changed", lang.Name), util.Markdown)
		}
	} else {
		bot.SendMessage(message.Chat, Translatef(sender, "lang.usage"), util.Markdown)
	}
}
Example #4
0
func sendSecondYear(day int, bot *telebot.Bot, message telebot.Message) {
	sender := config.GetUserWithUID(message.Sender.ID)
	bot.SendMessage(message.Chat,
		lang.Translatef(sender, "timetable.generic",
			secondyear[day][0].Subject, secondyear[day][1].Subject, secondyear[day][2].Subject, secondyear[day][3].Subject,
			util.DateToString(secondyear[day][0].Date))+"\n"+lang.Translatef(sender, "timetable.other", other[day].Subject),
		util.Markdown)
}
Example #5
0
func (m *NorrisPlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {

	if message.Text == config.CommandPrefix+"norris" {
		res, _ := getJoke("http://api.icndb.com/jokes/random")
		bot.SendMessage(message.Chat, res.Value.Joke, nil)

	}

}
Example #6
0
// sends a fixer message to a single ID.
func sendTo(ID int, bot *telebot.Bot, fa *fixrdb.FixrDB) error {
	var err error
	rates, err := fa.GetRates(ID)
	base, err := fa.GetSetting(ID, "base")
	FixerData, err := fixerio.GetFixerData(base, rates)
	if err != nil {
		return err
	}
	bot.SendMessage(telebot.User{ID: ID}, FixerData.String(), nil)
	return nil
}
Example #7
0
File: net.go Project: piguet/yatzie
func SendPhoto(url string, message telebot.Message, bot *telebot.Bot) error {
	imagefile, err := SaveImage(url)
	if err != nil {
		log.Println("Error fetching ")
		log.Println(err)
		bot.SendMessage(message.Chat, url, nil)

		return err
	}
	defer os.Remove(imagefile)

	var photo = telebot.Photo{}
	photo.Thumbnail.File, err = telebot.NewFile(imagefile)
	if err != nil {
		log.Println("Error creating the new file ")
		log.Println(err)
		bot.SendMessage(message.Chat, url, nil)

		return err
	}
	//photo.filename=imagefile

	err = bot.SendPhoto(message.Chat, &photo, nil)
	if err != nil {
		log.Println("Error sending photo")
		log.Println(err)
		bot.SendMessage(message.Chat, url, nil)

		return err
	}
	return err
}
Example #8
0
func (m *GooglePlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {
	if strings.Contains(message.Text, config.CommandPrefix+"imgsearch") {
		imgsearch := message.Text
		log.Println("Searching " + imgsearch)
		imgsearch = strings.Replace(imgsearch, config.CommandPrefix+"imgsearch ", "", -1)
		imgsearch = strings.Replace(imgsearch, " ", "%20", -1)

		util.DecodeJson("https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q="+imgsearch, func(body io.ReadCloser) bool {
			var data Response
			err := json.NewDecoder(body).Decode(&data)

			for _, i := range data.Response.Results {
				util.SendPhoto(i.Url, message, bot)
				log.Println("Found " + i.Title)
			}

			if err != nil {
				return false
			} else {
				return true
			}
		})

	}

	if strings.Contains(message.Text, config.CommandPrefix+"search") {
		websearch := message.Text
		log.Println("Searching " + websearch)
		websearch = strings.Replace(websearch, config.CommandPrefix+"search ", "", -1)
		websearch = strings.Replace(websearch, " ", "%20", -1)

		util.DecodeJson("https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q="+websearch, func(body io.ReadCloser) bool {
			var data Response
			err := json.NewDecoder(body).Decode(&data)

			for _, i := range data.Response.Results {
				bot.SendMessage(message.Chat, i.Title+" - "+i.Url, nil)
				log.Println("Found " + i.Title)
			}
			if err != nil {
				return false
			} else {
				return true
			}
		})

	}

}
Example #9
0
// loc - search building number by name
func handler_loc(bot *telebot.Bot, msg telebot.Message, args []string) {
	if len(args) == 0 {
		bot.SendMessage(msg.Chat, msgfmt("loc_noarg"), nil)
		return
	}

	data := get_data("loc")
	arr := strings.Split(data, ",")
	result := ""
	for _, v := range arr {
		if strings.Contains(v, args[0]) {
			result += v + "\n"
		}
	}
	bot.SendMessage(msg.Chat, msgfmt("loc", result), nil)
}
Example #10
0
File: web.go Project: worg/hookah
func processHook(ctx webhooks.Context) {
	h := ctx.Hook()
	branch := strings.TrimPrefix(h.Ref, `refs/heads/`)

	for _, r := range cfg.Repos {
		go func(r repo) {
			if r.Name != h.Repo.Name ||
				(r.Branch != `*` && r.Branch != branch) {
				return
			}

			go r.Tasks.Run() //execute tasks
			if r.Notify.Telegram.ChatID != 0 &&
				r.Notify.Telegram.Token != `` {
				var (
					buf bytes.Buffer
					bot *telebot.Bot
					err error
				)

				err = tmpl.Execute(&buf, map[string]interface{}{
					`hook`:   h,
					`branch`: branch,
				})
				if err != nil {
					log.Println(`Template ERR:`, err)
					return
				}

				if bot, err = telebot.NewBot(r.Notify.Telegram.Token); err != nil {
					log.Println(`Telegram ERR:`, err)
					return
				}

				err = bot.SendMessage(telebot.User{ID: r.Notify.Telegram.ChatID}, buf.String(), &sendOpts)
				if err != nil {
					log.Println(`Telegram ERR:`, err)
					return
				}

				log.Println(`Message Sent`)
			}
		}(r)
	}
}
Example #11
0
File: main.go Project: Xe/trolling
func inlineHandler(bot *telebot.Bot) {
	for query := range bot.Queries {
		log.Printf("Helped @%s with printer facts!", query.From.Username)

		fact, err := GetPrinterFact()
		if err != nil {
			panic(err)
		}

		results := []telebot.Result{
			fact,
		}

		// And finally respond to the query:
		if err := bot.Respond(query, results); err != nil {
			log.Println("ouch:", err)
		}
	}
}
Example #12
0
func (m *HelpPlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {
	if message.Text == config.CommandPrefix+"help" || message.Text == config.CommandPrefix+"start" {
		mk := make([]string, len(plugin_registry.Commands))
		i := 0
		for k, _ := range plugin_registry.Commands {
			mk[i] = k
			i++
		}
		sort.Strings(mk)
		var buffer bytes.Buffer

		for _, v := range mk {
			buffer.WriteString(config.CommandPrefix + v + " - " + plugin_registry.Commands[v] + "\n")
		}

		bot.SendMessage(message.Chat,
			util.RandomFromArray(quips)+", "+message.Sender.FirstName+"\n Those are my commands: \n"+buffer.String(), nil)
	}
}
Example #13
0
func (img *Image) Send(bot *telebot.Bot, msg telebot.Message) (err error) {
	if img == nil {
		warning := "You are trying to call a method of inexistent object :-)"
		bot.SendMessage(msg.Chat, warning, nil)
		return errors.New(warning)
	}

	img.Filename = fmt.Sprint("assets/", msg.ID, img.Ext)
	if img.Filename == "" {
		bot.SendMessage(msg.Chat, "There's any filename associated to this query.", nil)
		return errors.New("There's any filename associated to this query.")
	}

	i, err := telebot.NewFile(img.Filename)
	if err != nil {
		return err
	}

	caption := img.Caption[:int(math.Min(float64(len(img.Caption)), MaxCaption))]
	photo := telebot.Photo{Thumbnail: telebot.Thumbnail{File: i, Width: img.Width, Height: img.Height}, Caption: caption}

	err = bot.SendPhoto(msg.Chat, &photo, &telebot.SendOptions{ReplyTo: msg})
	if err != nil {
		return err
	}

	return nil
}
Example #14
0
func (m *IMDBPlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {
	if strings.Contains(message.Text, config.CommandPrefix+"imdb") {
		imdbsearch := message.Text
		log.Println("Searching " + imdbsearch)
		imdbsearch = strings.Replace(imdbsearch, config.CommandPrefix+"imdb ", "", -1)
		imdbsearch = strings.Replace(imdbsearch, " ", "%20", -1)

		util.DecodeJson("http://www.imdbapi.com/?t="+imdbsearch, func(body io.ReadCloser) bool {
			var imdb Movie
			err := json.NewDecoder(body).Decode(&imdb)

			bot.SendMessage(message.Chat, imdb.Title+" - "+imdb.Year+"\n"+imdb.Genre+" - "+imdb.Duration+"\n"+imdb.Image+"\n"+"http://imdb.com/title/"+imdb.Id, nil)

			if err != nil {
				return false
			} else {
				return true
			}
		})

	}

}
Example #15
0
func (m *XkcdPlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {
	if strings.Contains(message.Text, config.CommandPrefix+"xkcd") {
		xkcd := message.Text
		log.Println("Searching " + xkcd)
		xkcd = strings.Replace(xkcd, config.CommandPrefix+"xkcd ", "", -1)

		util.DecodeJson("https://xkcd.com/"+xkcd+"/info.0.json", func(body io.ReadCloser) bool {
			var data Result
			err := json.NewDecoder(body).Decode(&data)
			bot.SendMessage(message.Chat, strconv.Itoa(data.Id)+" - "+data.Img+" - "+data.Title, nil)
			log.Println("Found " + data.Title)

			if err != nil {
				return false
			} else {
				return true
			}
		})

	}

	if message.Text == config.CommandPrefix+"xkcd" {
		util.DecodeJson("https://xkcd.com/info.0.json", func(body io.ReadCloser) bool {
			var data Result
			err := json.NewDecoder(body).Decode(&data)
			bot.SendMessage(message.Chat, strconv.Itoa(data.Id)+" - "+data.Img+" - "+data.Title, nil)
			log.Println("Found " + data.Title)

			if err != nil {
				return false
			} else {
				return true
			}
		})
	}

}
Example #16
0
// weather - get weather information of Daejon
func handler_weather(bot *telebot.Bot, msg telebot.Message, args []string) {
	bot.SendChatAction(msg.Chat, "typing")

	if !check_external("weather", "2") {
		bot.SendMessage(msg.Chat, "Fatal(0x4)", nil)
		return
	}

	bot.SendMessage(msg.Chat, datafmt("weather", get_data("weather")), nil)
}
Example #17
0
// food - get menu of north, east, west cafe
func handler_food(bot *telebot.Bot, msg telebot.Message, args []string) {
	if len(args) == 0 {
		bot.SendMessage(msg.Chat, msgfmt("food_noarg"), nil)
		return
	}

	if args[0] != "n" && args[0] != "w" && args[0] != "e" {
		bot.SendMessage(msg.Chat, msgfmt("food_invarg"), nil)
		return
	}

	iname := "food_" + args[0]
	if !check_external(iname, "d") {
		bot.SendMessage(msg.Chat, "Fatal(0x4)", nil)
		return
	}

	bot.SendMessage(msg.Chat, msgfmt(iname, get_data(iname)), nil)
}
Example #18
0
func ListPlugins(message telebot.Message, bot *telebot.Bot) {
	var loaded bytes.Buffer
	var unloaded bytes.Buffer

	for k, _ := range plugin_registry.Plugins {
		loaded.WriteString("\t" + k + "\n")

	}

	for k, _ := range plugin_registry.DisabledPlugins {
		unloaded.WriteString("\t" + k + "\n")
	}
	bot.SendMessage(message.Chat, "Enabled plugins: ", nil)

	bot.SendMessage(message.Chat, loaded.String(), nil)
	bot.SendMessage(message.Chat, "Disabled plugins: ", nil)

	bot.SendMessage(message.Chat, unloaded.String(), nil)
}
Example #19
0
// rand - get random integer in [0, n)
func handler_rand(bot *telebot.Bot, msg telebot.Message, args []string) {
	if len(args) == 0 {
		bot.SendMessage(msg.Chat, msgfmt("rand_noarg"), nil)
		return
	}

	num, err := strconv.Atoi(args[0])
	if err != nil || num <= 0 {
		bot.SendMessage(msg.Chat, msgfmt("rand_invarg"), nil)
		return
	}

	result := rand.Intn(num)
	bot.SendMessage(msg.Chat, msgfmt("rand", num, result), nil)
}
Example #20
0
func (m *HalPlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {
	if !strings.HasPrefix(message.Text, config.CommandPrefix) && !util.MatchAnyURL(message.Text) {
		text := strings.Replace(message.Text, "@"+bot.Identity.Username, "", -1)
		// then call hal for random answers
		if len(text) >= MarkovChainOrder {
			m.brainIn <- text
			res := <-m.brainOut
			if res == "" && config.Eloquens == true {
				bot.SendMessage(message.Chat, util.RandomFromArray(quips), nil)

			} else {
				bot.SendMessage(message.Chat,
					res, nil)

			}
		} else {
			bot.SendMessage(message.Chat, util.RandomFromArray(quips), nil)
		}
	}
}
Example #21
0
func (m *MagicBallPlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {
	if strings.Contains(message.Text, config.CommandPrefix+"8ball") {
		bot.SendMessage(message.Chat,
			util.RandomFromArray(quips), nil)
	}
}
Example #22
0
func (m *HelloPlugin) Run(bot *telebot.Bot, config util.Config, message telebot.Message) {
	if message.Text == config.CommandPrefix+"hi" {
		bot.SendMessage(message.Chat,
			"Hello, "+message.Sender.FirstName+"!", nil)
	}
}
Example #23
0
// store - get store opening time
func handler_store(bot *telebot.Bot, msg telebot.Message, args []string) {
	bot.SendMessage(msg.Chat, get_data("store"), nil)
}
Example #24
0
// unknown - default handler for unknown command
func handler_unknown(bot *telebot.Bot, msg telebot.Message, args []string) {
	bot.SendMessage(msg.Chat, msgfmt("unknown"), nil)
}
Example #25
0
// HandleCommand handles a /timetable command
func HandleCommand(bot *telebot.Bot, message telebot.Message, args []string) {
	sender := config.GetUserWithUID(message.Sender.ID)
	if util.Timestamp() > lastupdate+600 {
		bot.SendMessage(message.Chat, lang.Translatef(sender, "timetable.update"), util.Markdown)
		Update()
	}

	day := today
	year := sender.Year
	if len(args) == 1 {
		if util.CheckArgs(args[0], lang.Translate(sender, "timetable.year.first")) {
			year = 1
		} else if util.CheckArgs(args[0], lang.Translate(sender, "timetable.year.second")) {
			year = 2
		} else if util.CheckArgs(args[0], "update") {
			Update()
			bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.update.success"), util.Markdown)
		} else {
			dayNew, err := shift(day, args[0], 0, len(other))
			if err != nil {
				if err.Error() == "OOB" {
					bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.nodata"), util.Markdown)
				} else if err.Error() == "PARSEINT" {
					bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.usage"), util.Markdown)
				}
				return
			}
			day = dayNew
		}
	} else if len(args) == 2 {
		if util.CheckArgs(args[0], lang.Translate(sender, "timetable.year.first")) {
			year = 1
		} else if util.CheckArgs(args[0], lang.Translate(sender, "timetable.year.second")) {
			year = 2
		} else {
			bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.usage"), util.Markdown)
		}
		dayNew, err := shift(day, args[1], 0, len(other))
		if err != nil {
			if err.Error() == "OOB" {
				bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.nodata"), util.Markdown)
			} else if err.Error() == "PARSEINT" {
				bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.usage"), util.Markdown)
			}
			return
		}
		day = dayNew
	}

	if day < 0 || day >= len(other) {
		bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.nodata"), util.Markdown)
		return
	}

	if year == 1 {
		sendFirstYear(day, bot, message)
	} else if year == 2 {
		sendSecondYear(day, bot, message)
	} else {
		bot.SendMessage(message.Chat, lang.Translate(sender, "timetable.noyeargroup"), util.Markdown)
	}
}
Example #26
0
// Handles the message currently received.
// TODO: refactor.
func HandleAction(message telebot.Message, bot *telebot.Bot, fixrAccessor *fixrdb.FixrDB) error {
	var err error
	if message.Text == "/start" {
		if subscribed, err := fixrAccessor.Subscribe(message.Chat.ID); err != nil && !subscribed {
			bot.SendMessage(message.Chat, "You are already subscribed.", nil)
		} else {
			bot.SendMessage(message.Chat, "You were subscribed to daily notifications. Send /stop if you don't want that.", nil)
		}
	}

	if message.Text == "/stop" {
		if unsubscribed, err := fixrAccessor.Unsubscribe(message.Chat.ID); err != nil && !unsubscribed {
			bot.SendMessage(message.Chat, "You are already unsubscribed.", nil)
		} else {
			bot.SendMessage(message.Chat, "You were unsubscribed from daily notifications. Send /start to subscribe again", nil)
		}
	}

	if message.Text == "/get" {
		err = sendTo(message.Chat.ID, bot, fixrAccessor)
	}

	if msgs := strings.Split(message.Text, " "); len(msgs) == 2 && msgs[0] == "/del" {
		fixrAccessor.RemoveRate(message.Chat.ID, msgs[1])
		bot.SendMessage(message.Chat, fmt.Sprintf("Removed currency %s", msgs[1]), nil)
	}

	if message.Text == "/help" {
		bot.SendMessage(message.Chat, GetCommands(), nil)
	}

	if len(message.Text) > len("/setbase") && message.Text[:len("/setbase")] == "/setbase" {
		base := message.Text[len("/setbase")+1:]
		if altered, err := fixrAccessor.SetBase(message.Chat.ID, base); altered {
			bot.SendMessage(message.Chat, "Base altered to "+fixerio.Currencies[base], nil)
		} else if err != nil {
			if err == fixrdb.ErrInvalidBase {
				bot.SendMessage(message.Chat, "Base \""+base+"\" is not recognized.", nil)
			}
		}
	}

	if message.Text == "/iso" {
		bot.SendMessage(message.Chat, fixerio.GetIsoNames(), nil)
	}

	if message.Text == "/clear" {
		fixrAccessor.ClearRates(message.Chat.ID)
		bot.SendMessage(message.Chat, "Cleared all rates. Showing everything now.", nil)
	}

	// if we receive a lonely /add command
	if message.Text == "/add" {
		lastCommand = addingCommand
		rates = []string{}
		bot.SendMessage(message.Chat, "Okay, let's add some currencies. Tell me which are they. You can search some of them with /iso before /add'ing them.", nil)
	} else if message.Text == "/done" || message.Text == "/cancel" {
		// if we're done, set the rates, clear commands and hide any custom keyboards.
		if len(rates) > 0 && message.Text != "/cancel" {
			fixrAccessor.SetRates(message.Chat.ID, rates)
		}

		if lastCommand != addingCommand && message.Text == "/cancel" {
			bot.SendMessage(message.Chat, "I wasn't really doing anything...", nil)
		}

		lastCommand = noop
		rates = []string{}
		bot.SendMessage(message.Chat, "Done adding rates.", &telebot.SendOptions{
			ReplyMarkup: telebot.ReplyMarkup{
				HideCustomKeyboard: true,
			},
		})
	} else if lastCommand == addingCommand {
		// if we're adding, append to the rates if it is a valid
		if validBase := fixerio.IsValidBase(message.Text); validBase {
			rates = append(rates, message.Text)
			bot.SendMessage(message.Chat, fmt.Sprintf("Rates added so far: %s\nWhen you're done adding currencies, send me /done to save them.", strings.Join(rates, ",")), nil)
		} else {
			bot.SendMessage(message.Chat, "Invalid ISO code. Please, see /iso to inspect valid currencies and add them here. Go check, I'll wait. I'll only finish this up when you send me /done", nil)
		}
	}

	// if we receive a /add command with stuff after it AND we are not adding anything,
	if msgs := strings.Split(message.Text, " "); len(msgs) > 0 && msgs[0] == "/add" && lastCommand == noop {
		// strip them off the command, and insert them.
		rates = msgs[1:]
		fixrAccessor.SetRates(message.Chat.ID, rates)
		bot.SendMessage(message.Chat, fmt.Sprintf("Added the following rates: %s", strings.Join(rates, ",")), nil)
		rates = []string{}
	}

	// if there was any error, return it.
	if err != nil {
		return err
	}

	return nil
}
Example #27
0
// SECTION - HANDLER FUNCTION
// about - display bot infos
func handler_about(bot *telebot.Bot, msg telebot.Message, args []string) {
	bot.SendMessage(msg.Chat, get_data("about"), nil)
}
Example #28
0
File: doofus.go Project: nf/doofus
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)
}