func (t *triviaChannel) Message(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) { if strings.ToLower(message.Message()) == t.Answer { t.Lock() defer t.Unlock() if !t.Active { return } ts := t.Scores[message.UserID()] if ts == nil { ts = &triviaScore{} t.Scores[message.UserID()] = ts } ts.Name = message.UserName() ts.Score++ service.SendMessage(message.Channel(), fmt.Sprintf("%s got it! The answer was %s.", message.UserName(), t.Answer)) service.SendMessage(message.Channel(), fmt.Sprintf("%s answered in %d seconds and their score is now %d.", message.UserName(), int(time.Now().Sub(t.Asked).Seconds()), ts.Score)) t.Unanswered = 0 if t.hintChan != nil { close(t.hintChan) t.hintChan = nil } } }
func (p *comicPlugin) makeComic(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message, script *comicgen.Script) { p.Comics++ comic := comicgen.NewComicGen("arial", service.Name() != bruxism.DiscordServiceName) image, err := comic.MakeComic(script) if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, there was an error creating the comic. %s", message.UserName(), err)) } else { go func() { if service.Name() == bruxism.DiscordServiceName { discord := service.(*bruxism.Discord) p, err := discord.UserChannelPermissions(message.UserID(), message.Channel()) if err == nil && p&discordgo.PermissionAttachFiles != 0 { b := &bytes.Buffer{} err = png.Encode(b, image) if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, there was a problem creating your comic.", message.UserName())) return } if err := service.SendFile(message.Channel(), "comic.png", b); err == nil { return } } } b := &bytes.Buffer{} err = png.Encode(b, image) if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, there was a problem creating your comic.", message.UserName())) return } url, err := bot.UploadToImgur(b, "comic.png") if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, there was a problem uploading the comic to imgur.", message.UserName())) log.Println("Error uploading comic: ", err) return } if service.Name() == bruxism.DiscordServiceName { service.SendMessage(message.Channel(), fmt.Sprintf("Here's your comic <@%s>: %s", message.UserID(), url)) } else { service.SendMessage(message.Channel(), fmt.Sprintf("Here's your comic %s: %s", message.UserName(), url)) } runtime.GC() }() } }
func (p *ReminderPlugin) Message(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) { if !service.IsMe(message) { if bruxism.MatchesCommand(service, "remind", message) || bruxism.MatchesCommand(service, "reminder", message) { _, parts := bruxism.ParseCommand(service, message) if len(parts) < 2 { service.SendMessage(message.Channel(), fmt.Sprintf("Invalid reminder, no time or message. eg: %s", p.randomReminder(service))) return } t, r, err := p.parseReminder(parts) now := time.Now() if err != nil || t.Before(now) || t.After(now.Add(time.Hour*24*365+time.Hour)) { service.SendMessage(message.Channel(), fmt.Sprintf("Invalid time. eg: %s", strings.Join(randomTimes, ", "))) return } if r == "" { service.SendMessage(message.Channel(), fmt.Sprintf("Invalid reminder, no message. eg: %s", p.randomReminder(service))) return } requester := message.UserName() if service.Name() == bruxism.DiscordServiceName { requester = fmt.Sprintf("<@%s>", message.UserID()) } err = p.AddReminder(&Reminder{ StartTime: now, Time: t, Requester: requester, Target: message.Channel(), Message: r, IsPrivate: service.IsPrivate(message), }) if err != nil { service.SendMessage(message.Channel(), err.Error()) return } service.SendMessage(message.Channel(), fmt.Sprintf("Reminder set for %s.", humanize.Time(t))) } } }
func makeScriptFromMessages(service bruxism.Service, message bruxism.Message, messages []bruxism.Message) *comicgen.Script { speakers := make(map[string]int) avatars := make(map[int]string) script := []*comicgen.Message{} for _, message := range messages { speaker, ok := speakers[message.UserName()] if !ok { speaker = len(speakers) speakers[message.UserName()] = speaker avatars[speaker] = message.UserAvatar() } script = append(script, &comicgen.Message{ Speaker: speaker, Text: message.Message(), Author: message.UserName(), }) } return &comicgen.Script{ Messages: script, Author: fmt.Sprintf(service.UserName()), Avatars: avatars, Type: comicgen.ComicTypeChat, } }
// Message handler. func (p *comicPlugin) Message(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) { if service.IsMe(message) { return } p.Lock() defer p.Unlock() log, ok := p.log[message.Channel()] if !ok { log = []bruxism.Message{} } if bruxism.MatchesCommand(service, "customcomic", message) || bruxism.MatchesCommand(service, "customcomicsimple", message) { ty := comicgen.ComicTypeChat if bruxism.MatchesCommand(service, "customcomicsimple", message) { ty = comicgen.ComicTypeSimple } service.Typing(message.Channel()) str, _ := bruxism.ParseCommand(service, message) messages := []*comicgen.Message{} splits := strings.Split(str, "|") for _, line := range splits { line := strings.Trim(line, " ") text := "" speaker := 0 author := "" if strings.Index(line, ":") != -1 { lineSplit := strings.Split(line, ":") author = strings.ToLower(strings.Trim(lineSplit[0], " ")) var err error speaker, err = strconv.Atoi(author) if err != nil { speaker = -1 } text = strings.Trim(lineSplit[1], " ") } else { text = line } messages = append(messages, &comicgen.Message{ Speaker: speaker, Text: text, Author: author, }) } if len(messages) == 0 { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, you didn't add any text.", message.UserName())) return } p.makeComic(bot, service, message, &comicgen.Script{ Messages: messages, Author: fmt.Sprintf(service.UserName()), Type: ty, }) } else if bruxism.MatchesCommand(service, "comic", message) { if len(log) == 0 { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, I don't have enough messages to make a comic yet.", message.UserName())) return } service.Typing(message.Channel()) lines := 0 linesString, parts := bruxism.ParseCommand(service, message) if len(parts) > 0 { lines, _ = strconv.Atoi(linesString) } if lines <= 0 { lines = 1 + int(math.Floor((math.Pow(2*rand.Float64()-1, 3)/2+0.5)*float64(5))) } if lines > len(log) { lines = len(log) } p.makeComic(bot, service, message, makeScriptFromMessages(service, message, log[len(log)-lines:])) } else { // Don't append commands. if bruxism.MatchesCommand(service, "", message) { return } switch message.Type() { case bruxism.MessageTypeCreate: if len(log) < 10 { log = append(log, message) } else { log = append(log[1:], message) } case bruxism.MessageTypeUpdate: for i, m := range log { if m.MessageID() == message.MessageID() { log[i] = message break } } case bruxism.MessageTypeDelete: for i, m := range log { if m.MessageID() == message.MessageID() { log = append(log[:i], log[i+1:]...) break } } } p.log[message.Channel()] = log } }
// enqueue a song/playlest to a VoiceConnections Queue func (p *MusicPlugin) enqueue(vc *voiceConnection, url string, service bruxism.Service, message bruxism.Message) (err error) { if vc == nil { return fmt.Errorf("Cannot enqueue to nil voice connection.") } if url == "" { return fmt.Errorf("Cannot enqueue an empty string.") } // TODO ////////////////////////////////////////////////////////////////// // need to parse the url and have a way to know what we're doing // 1) option to queue local files // 2) option to queue saved playlists // 3) option to queue URL that can be passed directly to ffmpeg without youtube-dl // 4) option to queue youtube-dl playlist // 5) option to queue youtube-dl song // 6) option to queue youtube-dl search result // right now option 4 and 5 work, only. ////////////////////////////////////////////////////////////////////////// cmd := exec.Command("./youtube-dl", "-i", "-j", "--youtube-skip-dash-manifest", url) if vc.debug { cmd.Stderr = os.Stderr } output, err := cmd.StdoutPipe() if err != nil { log.Println(err) service.SendMessage(message.Channel(), fmt.Sprintf("Error adding song to playlist.")) return } err = cmd.Start() if err != nil { log.Println(err) service.SendMessage(message.Channel(), fmt.Sprintf("Error adding song to playlist.")) return } defer func() { go cmd.Wait() }() scanner := bufio.NewScanner(output) for scanner.Scan() { s := song{} err = json.Unmarshal(scanner.Bytes(), &s) if err != nil { log.Println(err) continue } s.AddedBy = message.UserName() vc.Lock() vc.Queue = append(vc.Queue, s) vc.Unlock() } return }
func (p *chartPlugin) messageFunc(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) { if service.IsMe(message) { return } if bruxism.MatchesCommand(service, "chart", message) { query, parts := bruxism.ParseCommand(service, message) if len(parts) == 0 { service.SendMessage(message.Channel(), fmt.Sprintf("Invalid chart eg: %s", p.randomChart(service))) return } start, end := 0.5, 0.5 switch parts[0] { case "up": start, end = 0, 1 case "down": start, end = 1, 0 case "flat": case "straight": default: service.SendMessage(message.Channel(), fmt.Sprintf("Invalid chart direction. eg: %s", p.randomChart(service))) return } axes := strings.Split(query[len(parts[0]):], ",") if len(axes) != 2 { service.SendMessage(message.Channel(), fmt.Sprintf("Invalid chart axis labels eg: %s", p.randomChart(service))) return } pl, err := plot.New() if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Error making chart, sorry! eg: %s", p.randomChart(service))) return } service.Typing(message.Channel()) pl.Y.Label.Text = axes[0] pl.X.Label.Text = axes[1] num := 5 + rand.Intn(15) start *= float64(num) end *= float64(num) pts := make(plotter.XYs, num) for i := range pts { pts[i].X = float64(i) + rand.Float64()*0.5 - 0.2 pts[i].Y = start + float64(end-start)/float64(num-1)*float64(i) + rand.Float64()*0.5 - 0.25 } pl.X.Tick.Label.Color = color.Transparent pl.Y.Tick.Label.Color = color.Transparent pl.X.Min = -0.5 pl.X.Max = float64(num) + 0.5 pl.Y.Min = -0.5 pl.Y.Max = float64(num) + 0.5 lpLine, lpPoints, err := plotter.NewLinePoints(pts) if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, there was a problem creating your chart.", message.UserName())) } lpLine.Color = plotutil.Color(rand.Int()) lpLine.Width = vg.Points(1 + 0.5*rand.Float64()) lpLine.Dashes = plotutil.Dashes(rand.Int()) lpPoints.Shape = plotutil.Shape(rand.Int()) lpPoints.Color = lpLine.Color pl.Add(lpLine, lpPoints) w, err := pl.WriterTo(320, 240, "png") if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, there was a problem creating your chart.", message.UserName())) return } b := &bytes.Buffer{} w.WriteTo(b) go func() { if service.Name() == bruxism.DiscordServiceName { discord := service.(*bruxism.Discord) p, err := discord.UserChannelPermissions(message.UserID(), message.Channel()) if err == nil && p&discordgo.PermissionAttachFiles != 0 { service.SendFile(message.Channel(), "chart.png", b) return } } url, err := bot.UploadToImgur(b, "chart.png") if err != nil { service.SendMessage(message.Channel(), fmt.Sprintf("Sorry %s, there was a problem uploading the chart to imgur.", message.UserName())) log.Println("Error uploading chart: ", err) return } if service.Name() == bruxism.DiscordServiceName { service.SendMessage(message.Channel(), fmt.Sprintf("Here's your chart <@%s>: %s", message.UserID(), url)) } else { service.SendMessage(message.Channel(), fmt.Sprintf("Here's your chart %s: %s", message.UserName(), url)) } }() } }
// Message handler. func (p *triviaPlugin) Message(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) { defer bruxism.MessageRecover() if !service.IsMe(message) && !service.IsPrivate(message) { messageChannel := message.Channel() isCommand := bruxism.MatchesCommand(service, "trivia", message) if isCommand && (service.IsModerator(message) || service.IsBotOwner(message)) { p.Lock() tc := p.Channels[messageChannel] if tc == nil { tc = &triviaChannel{ Channel: messageChannel, Scores: map[string]*triviaScore{}, } p.Channels[messageChannel] = tc } p.Unlock() _, parts := bruxism.ParseCommand(service, message) if len(parts) == 0 { return } switch parts[0] { case "start": theme := "" if len(parts) >= 2 { theme = parts[1] } tc.Start(bot, service, theme) case "stop": tc.Stop(bot, service) } } else { if isCommand { _, parts := bruxism.ParseCommand(service, message) if len(parts) == 0 { return } if parts[0] == "score" { p.RLock() tc := p.Channels[messageChannel] if tc != nil { ts := tc.Scores[message.UserID()] if ts != nil { service.SendMessage(message.Channel(), fmt.Sprintf("%s's score is %d.", message.UserName(), ts.Score)) } else { service.SendMessage(message.Channel(), fmt.Sprintf("%s's score is 0.", message.UserName())) } } p.RUnlock() } return } p.RLock() tc := p.Channels[messageChannel] p.RUnlock() if tc != nil { tc.Message(bot, service, message) } } } }