Documentation ¶
Index ¶
Constants ¶
View Source
const DICE_USAGE = "Usage: [num dice]d[sides](+/-num) (opt: if fudging)"
View Source
const SourceRepo string = "https://github.com/bbriggs/bitbot"
Variables ¶
View Source
var ( GitTag string // Dockerhub appears to use shallow clones which drop tag info. Set this as a default." GitCommit string GitBranch string )
View Source
var AbyssTrigger = NamedTrigger{ ID: "abyss", Help: "State of the art advanced Abyss simulator. Non-interactive.", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && rand.Intn(1000) < 2 }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.Reply(m, "0.0") return true }, }
View Source
var BeefyTrigger = NamedTrigger{ ID: "beefy", Help: "It's big. It's beefy. It triggers any time someone says \"beefy\" in a message.", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { match, _ := regexp.MatchString(`(?i)beefy`, m.Trailing) return m.Command == "PRIVMSG" && match }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { responses := []string{ "BEEFY", "it's what's for dinner", "https://i.imgur.com/VbC5GLl.jpg", "mmmmmm", } irc.Reply(m, responses[b.Random.Intn(len(responses))]) return true }, }
View Source
var ChannelPopGaugeTrigger = NamedTrigger{ ID: "channelPopGauge", Help: "Updates a Prometheus gauge with the value of a channel's population", Condition: func(bot *hbot.Bot, m *hbot.Message) bool { return m.Command == "JOIN" || m.Command == "PART" || m.Command == "QUIT" }, Action: func(bot *hbot.Bot, m *hbot.Message) bool { switch m.Command { case "JOIN": b.gauges["channel_pop"].WithLabelValues(m.To).Inc() case "QUIT": for _, c := range b.Bot.Channels { bot.Send("LIST " + c) } default: b.gauges["channel_pop"].WithLabelValues(m.To).Dec() } return true }, }
View Source
var Covid19Trigger = NamedTrigger{ ID: "covid19", Help: "Fetch stats on Coronavirus by region", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Trailing, "!covid") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { data, ok := getCovid19Data() if !ok { irc.Reply(m, "Unable to get data at this time") return true } resp := parseCovid19Trigger(strings.Split(m.Trailing, " "), &data) irc.Reply(m, resp) return true }, }
View Source
var DecisionsTrigger = NamedTrigger{ ID: "decisions", Help: "Let the bot decide something for you. Usage: ${bot_name} choose option option [option...]", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { prefix := fmt.Sprintf("%s choose", irc.Nick) return m.Command == "PRIVMSG" && strings.HasPrefix(m.Content, prefix) }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { prefix := fmt.Sprintf("%s choose", irc.Nick) msg := strings.TrimPrefix(m.Content, prefix) r := choose(msg) if r == "" { r = "Choose what?" } irc.Reply(m, r) return true }, }
View Source
var EpeenTrigger = NamedTrigger{ ID: "epeen", Help: "epeen returns the length of the requesters epeen. Usage: !epeen", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.TrimSpace(m.Content) == "!epeen" }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { var epeen = makeEpeenAnswer(m.From) irc.Reply(m, epeen) return true }, }
View Source
var HandleListReplyTrigger = NamedTrigger{ ID: "handleListReply", Help: "Sets the gauge for a channel pop when an RPL_LIST command is detected", Condition: func(bot *hbot.Bot, m *hbot.Message) bool { return m.Command == irc.RPL_LIST }, Action: func(bot *hbot.Bot, m *hbot.Message) bool { log.Println("List Reply Received") channel := m.Params[1] pop, err := strconv.Atoi(m.Params[2]) if err != nil { log.Println("RPL_LIST returned invalid reply") } b.gauges["channel_pop"].WithLabelValues(channel).Set(float64(pop)) return true }, }
View Source
var HelpTrigger = NamedTrigger{ ID: "help", Help: "Usage: !help [trigger name]", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Content, "!help") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { splitMsg := strings.Split(m.Trailing, " ") triggers := b.ListTriggers() if len(splitMsg) < 2 { irc.Reply(m, "Currently loaded plugins: "+strings.Join(triggers, ", ")) return true } for _, t := range triggers { if splitMsg[1] == t { t, ok := b.FetchTrigger(splitMsg[1]) if ok && t.Help != "" { irc.Reply(m, t.Help) } else { irc.Reply(m, "Trigger found but help unavailalbe") } return true } } irc.Reply(m, "Help text unavailable") return true }, }
View Source
var IPinfoTrigger = NamedTrigger{ ID: "ipinfo", Help: "!ipinfo <valid IP>", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Content, "!ipinfo") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { var resp string cmd := strings.Split(m.Content, " ") if len(cmd) > 1 { resp = query(cmd[1]) } else { resp = "please provide an ip...ya twatsicle" } irc.Reply(m, resp) return true }, }
View Source
var InfoTrigger = NamedTrigger{ ID: "info", Help: "Get version and repo information about this bot. Usage: !info", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.TrimSpace(m.Content) == "!info" }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { resp := fmt.Sprintf("Bitbot version %s (%s/%s) | %s", GitTag, GitBranch, GitCommit, SourceRepo) irc.Reply(m, resp) return true }, }
View Source
var InviteTrigger = NamedTrigger{ ID: "invite", Help: "Follow invites to other channels. Usage: /invite [bot nick]", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "INVITE" }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.Join(m.Content) return true }, }
View Source
var Magic8BallTrigger = NamedTrigger{ ID: "8ball", Help: "Beseech the magic 8ball. Usage: !8ball [question]", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Trailing, "!8ball") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.Reply(m, make8BallAnswer()) return true }, }
View Source
var MarkovInitTrigger = NamedTrigger{ ID: "markovInit", Help: "Resets markov chain to a fresh chain, or bootstraps it with sample texts. Usage: !markov reset, !markov init", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Content, "!markov ") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { cmd := strings.Split(m.Content, " ") if len(cmd) < 2 { irc.Reply(m, "Usage: !markov reset, !markov init") return true } switch cmd[1] { case "reset": b.mChain = gomarkov.NewChain(1) case "init": b.mChain = gomarkov.NewChain(1) if markovInit(b.mChain) { irc.Reply(m, "Markov initialization succeeded.") } else { irc.Reply(m, "Markov initialization failed.") } default: return true } return true }, }
View Source
var MarkovResponseTrigger = NamedTrigger{ ID: "markovResponse", Help: "Returns a randomly generated markov string. Usage: !babble", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && (m.Content == "!babble" || rand.Intn(1000) == 0) }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.Reply(m, generateBabble(b.mChain)) return false }, }
View Source
var MarkovTrainerTrigger = NamedTrigger{ ID: "markovTrainer", Help: "Incrementally trains bitbot's markov model on every new privmsg", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { if b.mChain == nil { b.mChain = gomarkov.NewChain(1) } markovAdd(m.Content, b.mChain) return false }, }
View Source
var MessageCounterTrigger = NamedTrigger{ ID: "messageCounter", Help: "Increments a counter for every message it sees in chat.", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { b.counters["messageCounter"].WithLabelValues(m.To, m.Name).Inc() return false }, }
View Source
var NickTakenTrigger = NamedTrigger{ ID: "nick", Help: "Avoids nick collisions by renaming the bot if the nick is already taken.", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { /* get the host's name by cutting the port number, and making sure that the message comes from host */ var comesFromHost = (m.From == strings.Split(irc.Host, ":")[0]) var nickTaken = strings.Contains(m.Content, "Nickname is already in use") return comesFromHost && nickTaken }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.SetNick(irc.Nick + "_") return false }, }
View Source
var OperLogin = hbot.Trigger{ func(bot *hbot.Bot, m *hbot.Message) bool { return m.Command == irc.RPL_MYINFO }, func(bot *hbot.Bot, m *hbot.Message) bool { ns, ok := b.NickservLogin() if ok { bot.Msg("NickServ", ns) } time.Sleep(5 * time.Second) op, ok := b.OperLogin() if ok { bot.Send(op) time.Sleep(5 * time.Second) b.GetOper() } return true }, }
View Source
var PartTrigger = NamedTrigger{ ID: "part", Help: "Command the bot to leave the channel. Usage: [bot nick] part [channel]", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { isPartMessage, err := regexp.MatchString("^"+irc.Nick+".*part", m.Content) if err != nil { log.Error(err.Error()) } return m.Command == "PRIVMSG" && isPartMessage }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { splitMsg := strings.Split(m.Content, " ") fmt.Println(splitMsg) if len(splitMsg) == 2 { irc.Part(m.Params[0], irc.Nick) return true } else if len(splitMsg) > 2 { irc.Part(splitMsg[2], irc.Nick) return true } return false }, }
View Source
var RaiderQuoteTrigger = NamedTrigger{ ID: "raider", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && b.Random.Intn(1000) == 1 }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { r, ok := getQuote("/fallout/raider") if ok { irc.Reply(m, r.Quote) } return false }, }
View Source
var ReminderTrigger = NamedTrigger{ ID: "reminder", Help: "Set up events and remind them to concerned people. Usage: !remind list|time|add|remove|join|part", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Trailing, "!remind") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { timeFormat = "2006-01-02 15:04" splitMSG := strings.Split(m.Content, " ") if len(splitMSG) < 2 { irc.Reply(m, "Not enough arguments provided") return true } switch splitMSG[1] { case "time": irc.Reply(m, getTime()) case "add": irc.Reply(m, addEvent(m, irc)) case "remove": irc.Reply(m, removeEvent(m)) case "list": irc.Reply(m, listEvents(m, irc)) case "join": irc.Reply(m, joinEvent(m)) case "part": irc.Reply(m, partEvent(m)) default: irc.Reply(m, "Wrong argument") } return true }, Init: func() error { var err error location, err = time.LoadLocation("UTC") if err != nil { log.Error("Reminder : Couldn't load UTC timezone", err.Error()) return err } b.DB.AutoMigrate(&ReminderEvent{}) return nil }, }
View Source
var RollTrigger = NamedTrigger{ ID: "roll", Help: "!roll " + DICE_USAGE, Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Content, "!roll") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { var resp string cmd := strings.Split(m.Content, " ") if len(cmd) > 1 { resp = roll(cmd[1]) } else { resp = DICE_USAGE } irc.Reply(m, resp) return true }, }
View Source
var SetChanPopGaugeTrigger = NamedTrigger{ ID: "setChannelPopGauge", Help: "Sets the gauge for a channel's population when the bot joins", Condition: func(bot *hbot.Bot, m *hbot.Message) bool { return m.Command == irc.RPL_NAMREPLY }, Action: func(bot *hbot.Bot, m *hbot.Message) bool { names := strings.Split(strings.TrimSpace(m.Content), " ") channel := m.Params[len(m.Params)-1] b.gauges["channel_pop"].WithLabelValues(channel).Set(float64(len(names))) return true }, }
View Source
var ShrugTrigger = NamedTrigger{ ID: "shrug", Help: "Usage: !shrug", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.TrimSpace(m.Content) == "!shrug" }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.Reply(m, `¯\_(ツ)_/¯`) return true }, }
View Source
var SkipTrigger = NamedTrigger{ ID: "skip", Help: "Prevents a message from being processed by other triggers. Usage: !skip <something that would have invoked a trigger>", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Content, "!skip") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { return true }, }
SkipTrigger sets a message prefix that instructs bitbot not to process the message Should be set before any "skippable" triggers and after any triggers that run on all messages (unskippable)
View Source
var TableFlipTrigger = NamedTrigger{ ID: "tableflip", Help: "Flip a table. Usage: !tableflip", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { match := (m.Content == "!tableflip") return m.Command == "PRIVMSG" && match }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.Reply(m, "(╯°□°)╯︵ ┻━┻") return true }, }
View Source
var TableUnflipTrigger = NamedTrigger{ ID: "unflip", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { match := (m.Content == "!unflip") return m.Command == "PRIVMSG" && match }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { irc.Reply(m, "┬─┬ ノ( ゜-゜ノ)") return true }, }
View Source
var TarotTrigger = NamedTrigger{ ID: "Tarot", Help: "Request tarot cards, default 1. Usage !tarot [num cards].", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Trailing, "!tarot") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { if len(m.Content) < 7 { resp := tarotCards[rand.Intn(len(tarotCards)-1)] irc.Reply(m, resp) } else { deck := rand.Perm(len(tarotCards)) msg := strings.TrimPrefix(m.Content, "!tarot ") if num, err := strconv.Atoi(msg); err == nil { if num < 1 || num > len(tarotCards) { num = 1 } if num > 5 { for i := 0; i < num; i++ { irc.Msg(m.From, tarotCards[deck[i]]) } irc.Reply(m, "I have PMed you your reading.") } else { for i := 0; i < num; i++ { irc.Reply(m, tarotCards[deck[i]]) } } } else { irc.Reply(m, "Try again..") } } return true }, }
View Source
var TrollLauncherTrigger = NamedTrigger{ ID: "troll", Help: "Launches a random number of trolls for a random amount of damage. Usage: !troll <nick>", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Content, "!troll ") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { var damage_type = [13]string{"bludgeoning", "piercing", "slashing", "cold", "fire", "acid", "poison", "psychic", "necrotic", "radiant", "lightning", "thunder", "force"} cmd := strings.Split(m.Content, " ") if len(cmd) < 2 { irc.Reply(m, "Usage: !troll <nick>") return true } var nick = cmd[1] var trolls = rand.Intn(10) if trolls == 0 { irc.Reply(m, "The troll launcher malfunctioned.") } else { reply := fmt.Sprintf("Firing %d trolls at %s! You take %d points of %s damage!", trolls, nick, rand.Intn(20), damage_type[rand.Intn(12)]) irc.Reply(m, reply) } return true }, }
View Source
var URLReaderTrigger = NamedTrigger{ ID: "urls", Help: "Looks up URLs in chat and returns the page title as a message.", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && isURL(m.Content) }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { resp := lookupPageTitle(m.Content) if resp != "" { title := lookupPageTitle(m.Content) if len(m.Content) > 70 { short := shortenURL(m.Content) short = strings.TrimRight(short, "\n") title = fmt.Sprintf("%s %s", short, title) } title = cleanTitle(title) irc.Reply(m, title) } return true }, }
View Source
var UrbanDictionaryTrigger = NamedTrigger{ ID: "urbandict", Help: "Get an urban dictionary issued definition. Usage: !urbd [term]", Condition: func(irc *hbot.Bot, m *hbot.Message) bool { return m.Command == "PRIVMSG" && strings.HasPrefix(m.Trailing, "!ud") }, Action: func(irc *hbot.Bot, m *hbot.Message) bool { resp := urbanDefinition(m.Content) irc.Reply(m, resp) return true }, }
Functions ¶
Types ¶
type ACL ¶ added in v1.1.0
type ACL struct { // Defines users explicitly allowed in this ACL Permitted []string // Defines users explicitly rejected by this ACL Rejected []string }
ACL defines access lists the bot may use to check Authorization to use a trigger
type Bot ¶
type Bot struct { Bot *hbot.Bot DB *gorm.DB Random *rand.Rand // Initialized PRNG Config Config // contains filtered or unexported fields }
func (*Bot) DropTrigger ¶ added in v1.2.1
func (b *Bot) DropTrigger(t NamedTrigger) bool
func (*Bot) FetchTrigger ¶ added in v1.1.0
func (b *Bot) FetchTrigger(name string) (NamedTrigger, bool)
func (*Bot) ListTriggers ¶ added in v1.2.1
ListTriggers gets all trigger IDs currently registered to the bot
func (Bot) NickservLogin ¶
func (*Bot) RegisterTrigger ¶ added in v1.1.0
func (b *Bot) RegisterTrigger(t NamedTrigger)
type Config ¶
type Config struct { NickservPass string // Nickserv password OperUser string // Username for server oper OperPass string // Password for server oper Channels []string // slice of channels to connect to (must include #) Nick string // nick to use Server string // server:port for connections SSL bool // Enable SSL for the connection Admins ACL // slice of masks representing administrators Plugins []NamedTrigger // Plugins to start with Prometheus bool // Enable Prometheus PromAddr string // Listen address for prometheus endpoint DBConfig DBConfig // Configuration settings for Database connection }
type Coordinates ¶ added in v1.3.1
type Covid19Data ¶ added in v1.3.1
type Locations ¶ added in v1.3.1
type Locations struct { Coordinates Coordinates `json:"coordinates"` Country string `json:"country"` CountryCode string `json:"country_code"` Latest int `json:"latest"` Province string `json:"province"` }
type NamedTrigger ¶ added in v1.1.0
type NamedTrigger struct { ID string // Name of trigger, to use used to registering, searching, and deregistering Help string // Help text Condition func(*hbot.Bot, *hbot.Message) bool Action func(*hbot.Bot, *hbot.Message) bool Init func() error }
NamedTrigger is a local re-implementation of hbot.Trigger to support unique names
func (NamedTrigger) Handle ¶ added in v1.1.0
func (t NamedTrigger) Handle(b *hbot.Bot, m *hbot.Message) bool
Handle executes the trigger action if the condition is satisfied
func (NamedTrigger) Name ¶ added in v1.1.0
func (t NamedTrigger) Name() string
Name satisfies the hbot.Handler interface
Source Files ¶
- 8ball.go
- abyss.go
- admins.go
- beefy.go
- bot.go
- channelPopGauge.go
- channels.go
- covid19.go
- db.go
- decisions.go
- dice.go
- epeen.go
- flipTable.go
- help.go
- info.go
- ipinfo.go
- links.go
- loadtest.go
- login.go
- markov.go
- messageCounter.go
- nick.go
- prom.go
- quotes.go
- reminder.go
- shrug.go
- skip.go
- tarot.go
- trollLauncher.go
- urbandict.go
- util.go
- version.go
Click to show internal directories.
Click to hide internal directories.