package main import ( "flag" "fmt" "os" "os/signal" "strings" "syscall" "github.com/bwmarrin/discordgo" ) var ( dg *discordgo.Session token string gitCommit string ghostTypes []Spookster games = make(map[string]Game) fingeyEmoji = "🖐️" freezingEmoji = "❄️" spiritBoxEmoji = "📻" ghostWritingEmoji = "📖" emf5Emoji = "🚥" ghostOrbsEmoji = "⚪" deleteEmoji = "❌" ) func init() { flag.StringVar(&token, "t", "", "Bot Token") flag.Parse() } func main() { if token == "" { fmt.Println("No token provided. Please run: phasmobot -t ") } go setupGhostTypes() var err error dg, err = discordgo.New("Bot " + token) if err != nil { fmt.Println("Unable to create bot using token.") } err = dg.Open() if err != nil { fmt.Println("Unable to create bot using token.") } dg.AddHandler(ready) dg.AddHandler(messageCreate) dg.AddHandler(readReactions) sc := make(chan os.Signal, 1) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) <-sc dg.Close() } func ready(s *discordgo.Session, event *discordgo.Ready) { // Set the playing status. s.UpdateGameStatus(0, fmt.Sprintf("PhasmoBot %+v", gitCommit)) } func readReactions(s *discordgo.Session, m *discordgo.MessageReactionAdd) { if m.UserID == s.State.User.ID { return } if m.Emoji.Name == deleteEmoji { msg, _ := s.ChannelMessage(m.ChannelID, m.MessageID) if msg.Author.ID == s.State.User.ID { s.ChannelMessageDelete(m.ChannelID, m.MessageID) } return } if _, ok := games[m.ChannelID]; !ok { return } fmt.Println("Checking reaction from ", m.UserID) g := games[m.ChannelID] if m.Emoji.Name == fingeyEmoji { g.Evidence = append(g.Evidence, EMF5) } else if m.Emoji.Name == freezingEmoji { g.Evidence = append(g.Evidence, FreezingTemps) } else if m.Emoji.Name == spiritBoxEmoji { g.Evidence = append(g.Evidence, SpiritBox) } else if m.Emoji.Name == ghostWritingEmoji { g.Evidence = append(g.Evidence, GhostWriting) } else if m.Emoji.Name == emf5Emoji { g.Evidence = append(g.Evidence, EMF5) } else if m.Emoji.Name == ghostOrbsEmoji { g.Evidence = append(g.Evidence, GhostOrbs) } else { go s.MessageReactionRemove(m.ChannelID, g.PostID, m.Emoji.ID, m.UserID) } s.MessageReactionRemove(m.ChannelID, g.PostID, fingeyEmoji, "@me") s.MessageReactionRemove(m.ChannelID, g.PostID, freezingEmoji, "@me") s.MessageReactionRemove(m.ChannelID, g.PostID, spiritBoxEmoji, "@me") s.MessageReactionRemove(m.ChannelID, g.PostID, ghostWritingEmoji, "@me") s.MessageReactionRemove(m.ChannelID, g.PostID, emf5Emoji, "@me") s.MessageReactionRemove(m.ChannelID, g.PostID, ghostOrbsEmoji, "@me") g.EliminateGhosts(g.Evidence[len(g.Evidence)-1]) for _, v := range g.PossibleEvidence { switch v { case 0: s.MessageReactionAdd(m.ChannelID, g.PostID, emf5Emoji) case 1: s.MessageReactionAdd(m.ChannelID, g.PostID, freezingEmoji) case 2: s.MessageReactionAdd(m.ChannelID, g.PostID, spiritBoxEmoji) case 3: s.MessageReactionAdd(m.ChannelID, g.PostID, ghostWritingEmoji) case 4: s.MessageReactionAdd(m.ChannelID, g.PostID, fingeyEmoji) case 5: s.MessageReactionAdd(m.ChannelID, g.PostID, ghostOrbsEmoji) } } if len(g.Evidence) == 3 { s.GuildMemberNickname(m.GuildID, "@me", "") msg, _ := s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("%+v was a %+v", g.Ghost.GhostName, g.PossibleGhosts[0].GhostType)) s.MessageReactionAdd(m.ChannelID, g.PostID, deleteEmoji) s.MessageReactionAdd(m.ChannelID, msg.ID, deleteEmoji) } games[m.ChannelID] = g } func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { if m.Author.ID == s.State.User.ID { return } if !strings.HasPrefix(m.Content, "!") { return } if _, ok := games[m.ChannelID]; !ok || strings.HasPrefix(m.Content, "!reset") { games[m.ChannelID] = Game{ Identifier: m.ChannelID, } } g := games[m.ChannelID] parts := strings.Split(m.Content, " ") if strings.HasPrefix(m.Content, "!name") { g.Ghost.GhostName = strings.Join(parts[1:], " ") s.GuildMemberNickname(m.GuildID, "@me", g.Ghost.GhostName) } if strings.HasPrefix(m.Content, "!room") { if len(parts) == 2 { g.RoomID = parts[1] } else { if g.RoomID != "" { msg, _ := s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("The room code is `%+v`", g.RoomID)) s.MessageReactionAdd(m.ChannelID, msg.ID, deleteEmoji) } } } if strings.HasPrefix(m.Content, "!o") { if strings.Contains(m.Content, "emf") { g.Objective = append(g.Objective, EMF) } if strings.Contains(m.Content, "photo") { g.Objective = append(g.Objective, Photo) } if strings.Contains(m.Content, "event") { g.Objective = append(g.Objective, Event) } if strings.Contains(m.Content, "crucifix") { g.Objective = append(g.Objective, Crucifix) } if strings.Contains(m.Content, "motion") { g.Objective = append(g.Objective, Motion) } if strings.Contains(m.Content, "clean") { g.Objective = append(g.Objective, SmudgeCleanse) } if strings.Contains(m.Content, "hunt") { g.Objective = append(g.Objective, SmudgeHunt) } if strings.Contains(m.Content, "salt") { g.Objective = append(g.Objective, Salt) } if strings.Contains(m.Content, "candle") { g.Objective = append(g.Objective, Candle) } if strings.Contains(m.Content, "sanity") { g.Objective = append(g.Objective, LowSanity) } if strings.Contains(m.Content, "escape") { g.Objective = append(g.Objective, MemberEscape) } if strings.Contains(m.Content, "death") { g.Objective = append(g.Objective, NoDeaths) } } if strings.HasPrefix(m.Content, "!c") { if strings.Contains(m.Content, "emf") { g.CompleteObjective(EMF, s) } if strings.Contains(m.Content, "photo") { g.CompleteObjective(Photo, s) } if strings.Contains(m.Content, "event") { g.CompleteObjective(Event, s) } if strings.Contains(m.Content, "crucifix") { g.CompleteObjective(Crucifix, s) } if strings.Contains(m.Content, "motion") { g.CompleteObjective(Motion, s) } if strings.Contains(m.Content, "clean") { g.CompleteObjective(SmudgeCleanse, s) } if strings.Contains(m.Content, "hunt") { g.CompleteObjective(SmudgeHunt, s) } if strings.Contains(m.Content, "salt") { g.CompleteObjective(Salt, s) } if strings.Contains(m.Content, "candle") { g.CompleteObjective(Candle, s) } if strings.Contains(m.Content, "sanity") { g.CompleteObjective(LowSanity, s) } if strings.Contains(m.Content, "escape") { g.CompleteObjective(MemberEscape, s) } if strings.Contains(m.Content, "death") { g.CompleteObjective(NoDeaths, s) } } if len(g.Objective) == 3 && g.PostID == "" { post, _ := s.ChannelMessageSend(m.ChannelID, "The investigation begins! Click below to log evidence.") g.PossibleGhosts = append(g.PossibleGhosts, ghostTypes...) g.PostID = post.ID go s.MessageReactionAdd(m.ChannelID, post.ID, fingeyEmoji) go s.MessageReactionAdd(m.ChannelID, post.ID, freezingEmoji) go s.MessageReactionAdd(m.ChannelID, post.ID, spiritBoxEmoji) go s.MessageReactionAdd(m.ChannelID, post.ID, ghostWritingEmoji) go s.MessageReactionAdd(m.ChannelID, post.ID, emf5Emoji) go s.MessageReactionAdd(m.ChannelID, post.ID, ghostOrbsEmoji) } games[m.ChannelID] = g } func (g *Game) CompleteObjective(objective int, s *discordgo.Session) { var tasks []int ret := "Current objectives: ``` \n" for _, v := range g.Objective { if v != objective { tasks = append(tasks, v) ret += fmt.Sprintf("%+v\n", objectiveToStr(v)) } } ret += "```" msg, err := s.ChannelMessageSend(g.Identifier, ret) if err == nil { s.MessageReactionAdd(g.Identifier, msg.ID, deleteEmoji) } else { fmt.Println(err) fmt.Println(ret) } g.Objective = tasks games[g.Identifier] = *g }