Documentation ¶
Index ¶
- Constants
- Variables
- func CompletedStatusLine(vote *model.Vote) string
- func HandleVotesOnInitialLoad(s api.DiscordSession, modelHelper *ModelHelper, clock model.UTCClock, ...) error
- func StatusLine(clock model.UTCClock, vote *model.Vote) string
- func TimeString(clock model.UTCClock, timestampEnd time.Time) string
- type BallotExecutor
- type BallotParser
- type ConcludeExecutor
- type Feature
- type ModelHelper
- func (h *ModelHelper) CastBallot(channelID model.Snowflake, userID model.Snowflake, inFavor bool) (*model.Vote, error)
- func (h *ModelHelper) IsVoteActive(channelID model.Snowflake) (bool, error)
- func (h *ModelHelper) MostRecentVote(channelID model.Snowflake) (*model.Vote, error)
- func (h *ModelHelper) MostRecentVoteID(channelID model.Snowflake) (int, error)
- func (h *ModelHelper) MostRecentVotes() ([]*model.Vote, error)
- func (h *ModelHelper) SetVoteOutcome(channelID model.Snowflake, voteOutcome int) error
- func (h *ModelHelper) StartNewVote(channelID, userID model.Snowflake, message string) (*model.Vote, error)
- type StartVoteExecutor
- type StartVoteParser
- type StatusExecutor
- type StatusParser
Constants ¶
const ( // MsgAlreadyVoted returns that the user already voted MsgAlreadyVoted = "%v already voted" // MsgVotedAgainst returns that the user voted against the vote MsgVotedAgainst = "%v voted no" // MsgVotedInFavor returns that the user voted for the vote MsgVotedInFavor = "%v voted yes" )
const ( // MsgHelpBallotInFavor is help text for ?yes MsgHelpBallotInFavor = "Casts a ballot in favor of the current vote, if one is active" // MsgHelpBallotAgainst is help text for ?no MsgHelpBallotAgainst = "Casts a ballot against the current vote, if one is active" )
const ( // KeyMostRecentVoteID is the key/value store key for the vote KeyMostRecentVoteID = "most-recent-vote-id-channel-%v" // RedisMostRecentVoteID is the vote id of the most recent vote RedisMostRecentVoteID = "most-recent-vote-id-channel-*" // KeyVoteTemplate is the map from vote to channel KeyVoteTemplate = "vote-%v-channel-%v" // VoteDuration is the duration of a vote VoteDuration = time.Duration(30) * time.Minute )
const ( // MsgActiveVote prints that a vote is already active MsgActiveVote = "Cannot start a vote while another is in progress. Type `?votestatus` for more info" // MsgBroadcastNewVote prints that a new vote is happening MsgBroadcastNewVote = "@everyone -- %s started a new vote: %s\n\nType `?yes` or `?no` to vote. 30 minutes remaining." )
const ( // MsgNoActiveVote prints that there was no active vote MsgNoActiveVote = "No active vote" // MsgOneVoteAgainst is the unpluralized message for vote against MsgOneVoteAgainst = "1 vote against" // MsgOneVoteFor is the unpluralized message for vote for MsgOneVoteFor = "1 vote for" // MsgSpacer is used to separate parts of the output string MsgSpacer = "-----" // MsgStatusInconclusive prints that a vote was inconclusive MsgStatusInconclusive = "Not enough votes were cast." // MsgStatusVoteFailed prints that a vote has failed MsgStatusVoteFailed = "Vote Failed." // MsgStatusVoteFailing prints that a vote is currently failing MsgStatusVoteFailing = "Vote is failing" // MsgStatusVotePassed indicates that the vote has passed MsgStatusVotePassed = "Vote Passed!" // MsgStatusVotePassing prints whether the vote is passing MsgStatusVotePassing = "Vote is passing" // MsgStatusVotesNeeded prints how many votes are needed MsgStatusVotesNeeded = "5 votes must be cast before vote can pass" // MsgVoteOwner prints who started the vote MsgVoteOwner = "Vote started by %s: " // MsgVotesAgainst prints the votes against MsgVotesAgainst = "%d votes against" // MsgVotesFor prints the votes for MsgVotesFor = "%d votes for" )
const ( // MsgNoTimeRemaining prints that there is no time left MsgNoTimeRemaining = "No time remaining in vote" // MsgMinutesRemaining prints the minutes remaining MsgMinutesRemaining = "%v minutes remaining" // MsgSecondsRemaining prints the seconds remaining MsgSecondsRemaining = "%v seconds remaining" // MsgMillisecondsRemaining is a time output for a few milliseconds remaining MsgMillisecondsRemaining = "%v milliseconds remaining" )
const (
// MsgHelpStatus is the help text for ?votestatus
MsgHelpStatus = "Prints the status of the current vote, or a message indicating that no vote is active"
)
const ( // MsgHelpVote is the help text for ?vote MsgHelpVote = "" /* 222-byte string literal not displayed */ )
const (
// MsgVoteConcluded is the header for a concluded vote
MsgVoteConcluded = "@here -- Vote started by %s has concluded"
)
Variables ¶
var ErrorAlreadyVoted = errors.New("user already voted")
ErrorAlreadyVoted indicates that the user can't vote twice
var ErrorNoVoteActive = errors.New("cannot vote when there is no active vote")
ErrorNoVoteActive indicates that the user can't vote if no vote is active
var ErrorOnlyOneVote = errors.New("tried to start vote when one is already active")
ErrorOnlyOneVote indicates that a second vote cannot be started
var ErrorVoteHasOutcome = errors.New("cannot change vote outcome")
ErrorVoteHasOutcome indicates that the application already set the vote outcome, and to give up
Functions ¶
func CompletedStatusLine ¶
CompletedStatusLine generates the full status line of a concluded vote.
func HandleVotesOnInitialLoad ¶
func HandleVotesOnInitialLoad(s api.DiscordSession, modelHelper *ModelHelper, clock model.UTCClock, timer model.UTCTimer, commandChannel chan<- *model.Command) error
HandleVotesOnInitialLoad iterates through active vote pointers to see if any require timers to be re-fired.
func StatusLine ¶
StatusLine returns the full status line of an in-progress vote.
Types ¶
type BallotExecutor ¶
type BallotExecutor struct {
// contains filtered or unexported fields
}
BallotExecutor executes a vote
func NewBallotExecutor ¶
func NewBallotExecutor(modelHelper *ModelHelper) *BallotExecutor
NewBallotExecutor works as advertised
func (*BallotExecutor) Execute ¶
func (e *BallotExecutor) Execute(s api.DiscordSession, channelID model.Snowflake, command *model.Command)
Execute runs the command
func (*BallotExecutor) GetType ¶
func (e *BallotExecutor) GetType() int
GetType returns the type of this feature.
func (*BallotExecutor) PublicOnly ¶
func (e *BallotExecutor) PublicOnly() bool
PublicOnly returns whether the executor should be intercepted in a private channel.
type BallotParser ¶
type BallotParser struct { // The message that the parser looks for. Message string // Whether this message is in favor or against the measure. InFavor bool }
BallotParser parses a vote for or against
func NewBallotParser ¶
func NewBallotParser(message string, inFavor bool) *BallotParser
NewBallotParser works as advertised.
func (*BallotParser) GetName ¶
func (p *BallotParser) GetName() string
GetName returns the named type.
func (*BallotParser) HelpText ¶
func (p *BallotParser) HelpText(command string) (string, error)
HelpText returns the help text.
func (*BallotParser) Parse ¶
func (p *BallotParser) Parse(splitContent []string, m *discordgo.MessageCreate) (*model.Command, error)
Parse parses the given list command.
type ConcludeExecutor ¶
type ConcludeExecutor struct {
// contains filtered or unexported fields
}
ConcludeExecutor concludes the active vote and prints the results
func NewConcludeExecutor ¶
func NewConcludeExecutor(modelHelper *ModelHelper) *ConcludeExecutor
NewConcludeExecutor works as advertised
func (*ConcludeExecutor) Execute ¶
func (e *ConcludeExecutor) Execute(s api.DiscordSession, channelID model.Snowflake, command *model.Command)
Execute executes the command
func (*ConcludeExecutor) GetType ¶
func (e *ConcludeExecutor) GetType() int
GetType returns the type of this feature.
func (*ConcludeExecutor) PublicOnly ¶
func (e *ConcludeExecutor) PublicOnly() bool
PublicOnly returns whether the executor should be intercepted in a private channel. Since the vote is pinned to a channel, it should have been filtered then. If somehow the channel went private at that point, allow it to conclude.
type Feature ¶
type Feature struct {
// contains filtered or unexported fields
}
Feature registers feature-specific things for moderation.
func NewFeature ¶
func NewFeature(featureRegistry *feature.Registry, voteMap stringmap.StringMap, clock model.UTCClock, timer model.UTCTimer, commandChannel chan<- *model.Command) *Feature
NewFeature returns a new Feature.
func (*Feature) CommandInterceptors ¶
func (f *Feature) CommandInterceptors() []feature.CommandInterceptor
CommandInterceptors returns command interceptors.
func (*Feature) FallbackParser ¶
FallbackParser returns nil.
func (*Feature) OnInitialLoad ¶
func (f *Feature) OnInitialLoad(s api.DiscordSession) error
OnInitialLoad cleans up from any votes that were already active when crbot shut down.
type ModelHelper ¶
ModelHelper adds helper functions for using votes with a stringmap. Currently, it handles a majority of business logic. However, if functionality is ever added to allow a moderator to edit a vote after it has happened, the business logic will need to be pulled of here and leave this to be strictly a data structure that only validates its own sanity. The only logic that seems like it should be handled but isn't is the logic for when a vote outcome is recorded, because that is handled in an evented manner (i.e. when a timer ends).
func NewModelHelper ¶
func NewModelHelper(stringMap stringmap.StringMap, utcClock model.UTCClock) *ModelHelper
NewModelHelper works as advertised.
func (*ModelHelper) CastBallot ¶
func (h *ModelHelper) CastBallot(channelID model.Snowflake, userID model.Snowflake, inFavor bool) (*model.Vote, error)
CastBallot casts a ballot against the current poll for the given user. On success, it returns the vote with the ballot incorporated. Returns ErrorNoVoteActive if there is no active poll, or the inner error if a component errored. Returns ErrorAlreadyVoted if the user is present in either list.
func (*ModelHelper) IsVoteActive ¶
func (h *ModelHelper) IsVoteActive(channelID model.Snowflake) (bool, error)
IsVoteActive returns whether there is a most-recent, active vote.
func (*ModelHelper) MostRecentVote ¶
MostRecentVote returns the active vote, or nil if none present. Returns an error on i/o problems.
func (*ModelHelper) MostRecentVoteID ¶
func (h *ModelHelper) MostRecentVoteID(channelID model.Snowflake) (int, error)
MostRecentVoteID returns the most recent ID. Returns `0, nil` if no vote has ever been executed.
func (*ModelHelper) MostRecentVotes ¶
func (h *ModelHelper) MostRecentVotes() ([]*model.Vote, error)
MostRecentVotes returns every most recent vote in the database.
func (*ModelHelper) SetVoteOutcome ¶
func (h *ModelHelper) SetVoteOutcome(channelID model.Snowflake, voteOutcome int) error
SetVoteOutcome terminates an active vote with the given outcome
func (*ModelHelper) StartNewVote ¶
func (h *ModelHelper) StartNewVote(channelID, userID model.Snowflake, message string) (*model.Vote, error)
StartNewVote starts and returns a new vote. Returns ErrorOnlyOneVote if another vote was active when trying to start this one.
type StartVoteExecutor ¶
type StartVoteExecutor struct {
// contains filtered or unexported fields
}
StartVoteExecutor executes a vote begin command
func NewStartVoteExecutor ¶
func NewStartVoteExecutor(modelHelper *ModelHelper, commandChannel chan<- *model.Command, utcTimer model.UTCTimer) *StartVoteExecutor
NewStartVoteExecutor works as advertised
func (*StartVoteExecutor) Execute ¶
func (e *StartVoteExecutor) Execute(s api.DiscordSession, channelID model.Snowflake, command *model.Command)
Execute starts a new vote if one is not already active. It also starts a timer to use to conclude the vote.
func (*StartVoteExecutor) GetType ¶
func (e *StartVoteExecutor) GetType() int
GetType returns the type of this feature.
func (*StartVoteExecutor) PublicOnly ¶
func (e *StartVoteExecutor) PublicOnly() bool
PublicOnly returns whether the executor should be intercepted in a private channel.
type StartVoteParser ¶
type StartVoteParser struct { }
StartVoteParser parses ?vote commands.
func NewStartVoteParser ¶
func NewStartVoteParser() *StartVoteParser
NewStartVoteParser works as advertised.
func (*StartVoteParser) GetName ¶
func (p *StartVoteParser) GetName() string
GetName returns the named type of this feature.
func (*StartVoteParser) HelpText ¶
func (p *StartVoteParser) HelpText(command string) (string, error)
HelpText explains how to use ?vote.
func (*StartVoteParser) Parse ¶
func (p *StartVoteParser) Parse(splitContent []string, m *discordgo.MessageCreate) (*model.Command, error)
Parse parses the given vote command.
type StatusExecutor ¶
type StatusExecutor struct {
// contains filtered or unexported fields
}
StatusExecutor allows the user to check on the progress of the current vote
func NewStatusExecutor ¶
func NewStatusExecutor(modelHelper *ModelHelper) *StatusExecutor
NewStatusExecutor works as advertised
func (*StatusExecutor) Execute ¶
func (e *StatusExecutor) Execute(s api.DiscordSession, channel model.Snowflake, command *model.Command)
Execute prints the status of the current vote.
func (*StatusExecutor) GetType ¶
func (e *StatusExecutor) GetType() int
GetType returns the type of this feature.
func (*StatusExecutor) PublicOnly ¶
func (e *StatusExecutor) PublicOnly() bool
PublicOnly returns whether the executor should be intercepted in a private channel.
type StatusParser ¶
type StatusParser struct { }
StatusParser parses ?votestatus commands
func (*StatusParser) GetName ¶
func (p *StatusParser) GetName() string
GetName returns the named type.
func (*StatusParser) HelpText ¶
func (p *StatusParser) HelpText(command string) (string, error)
HelpText returns the help text.
func (*StatusParser) Parse ¶
func (p *StatusParser) Parse(splitContent []string, m *discordgo.MessageCreate) (*model.Command, error)
Parse parses the given list command.