228 lines
4.6 KiB
Go
228 lines
4.6 KiB
Go
package state
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"gitlab.com/whom/bingobot/internal/config"
|
|
"gitlab.com/whom/bingobot/internal/logging"
|
|
)
|
|
|
|
type VoteEvent map[string]string
|
|
|
|
const (
|
|
VoteMissingKeyError = "vote data not found: "
|
|
VoteCreatedKey = "created"
|
|
VoteRequesterKey = "requester"
|
|
VoteActionKey = "action"
|
|
|
|
VoteResultKey = "result"
|
|
VoteResultPass = "pass"
|
|
VoteResultFail = "fail"
|
|
VoteResultTie = "tie"
|
|
VoteResultTimeout = "timeout"
|
|
VoteBadResultError = "vote has invalid result: "
|
|
VoteNotFinishedError = "vote has result but isnt finished"
|
|
VoteMissingResultError = "vote finished but missing result"
|
|
|
|
VoteStatusKey = "status"
|
|
VoteStatusInProgress = "in_progress"
|
|
VoteStatusFinalized = "finalized"
|
|
VoteStatusTimeout = "timed_out"
|
|
VoteBadStatusError = "vote has invalid status: "
|
|
|
|
VeryOldVote = "1990-01-01T00:00:00Z"
|
|
)
|
|
|
|
func (ve VoteEvent) Type() EventType {
|
|
return Vote
|
|
}
|
|
|
|
func (ve VoteEvent) Time() time.Time {
|
|
t, e := time.Parse(time.RFC3339, ve[VoteCreatedKey])
|
|
if e != nil {
|
|
// we have a corrupted event
|
|
// return old time so that this event gets
|
|
// pruned from cache
|
|
logging.Warn(
|
|
"pruning corrupted vote event",
|
|
"event",
|
|
fmt.Sprintf("%+v", ve),
|
|
)
|
|
tooOld, _ := time.Parse(
|
|
time.RFC3339,
|
|
VeryOldVote,
|
|
)
|
|
return tooOld
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (ve VoteEvent) Data() map[string]string {
|
|
return map[string]string(ve)
|
|
}
|
|
|
|
func (ve VoteEvent) Validate() error {
|
|
// make sure action, requester, and created are set
|
|
for _, key := range []string{
|
|
VoteActionKey,
|
|
VoteRequesterKey,
|
|
VoteCreatedKey,
|
|
VoteStatusKey,
|
|
} {
|
|
if _, found := ve[key]; !found {
|
|
return errors.New(VoteMissingKeyError + key)
|
|
}
|
|
}
|
|
|
|
status := ve[VoteStatusKey]
|
|
if status != VoteStatusTimeout &&
|
|
status != VoteStatusInProgress &&
|
|
status != VoteStatusFinalized {
|
|
return errors.New(VoteBadStatusError + status)
|
|
}
|
|
|
|
result, hasResult := ve[VoteResultKey]
|
|
if hasResult && status == VoteStatusInProgress {
|
|
return errors.New(VoteNotFinishedError)
|
|
}
|
|
if status != VoteStatusInProgress && !hasResult {
|
|
return errors.New(VoteMissingResultError)
|
|
}
|
|
|
|
if hasResult &&
|
|
(result != VoteResultPass &&
|
|
result != VoteResultFail &&
|
|
result != VoteResultTie &&
|
|
result != VoteResultTimeout) {
|
|
|
|
return errors.New(VoteBadResultError + result)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ve VoteEvent) Disposable() bool {
|
|
// will be implemented with democracy module
|
|
logging.Warn("unimplemented: VoteEvent::Disposable")
|
|
return false
|
|
}
|
|
|
|
type UserEvent struct {
|
|
uid string
|
|
created time.Time
|
|
}
|
|
|
|
const (
|
|
UserEventUserKey = "user"
|
|
UserEventCreatedKey = "created"
|
|
UserEventBadUserError = "event has bad user"
|
|
)
|
|
|
|
func (ue UserEvent) Time() time.Time {
|
|
return ue.created
|
|
}
|
|
|
|
func (ue UserEvent) Data() map[string]string {
|
|
return map[string]string{
|
|
UserEventUserKey: ue.uid,
|
|
UserEventCreatedKey: ue.created.Format(time.RFC3339),
|
|
}
|
|
}
|
|
|
|
func (ue UserEvent) Validate() error {
|
|
// empty for now, we may do some validation later.
|
|
return nil
|
|
}
|
|
|
|
func (ue UserEvent) Disposable() bool {
|
|
// when I make a module for challenges, restorations, and UserActives
|
|
// then I should implement this
|
|
logging.Warn("unimplemented: UserEvent::Disposable")
|
|
return false
|
|
}
|
|
|
|
type ChallengeEvent struct {
|
|
UserEvent
|
|
}
|
|
|
|
func (ce ChallengeEvent) Type() EventType {
|
|
return Challenge
|
|
}
|
|
|
|
func NewChallengeEvent(user string) ChallengeEvent {
|
|
return ChallengeEvent{UserEvent{
|
|
uid: user,
|
|
created: time.Now(),
|
|
}}
|
|
}
|
|
|
|
type RestorationEvent struct {
|
|
UserEvent
|
|
}
|
|
|
|
func (re RestorationEvent) Type() EventType {
|
|
return Restoration
|
|
}
|
|
|
|
func NewRestorationEvent(user string) RestorationEvent {
|
|
return RestorationEvent{UserEvent{
|
|
uid: user,
|
|
created: time.Now(),
|
|
}}
|
|
}
|
|
|
|
type UserActiveEvent struct {
|
|
UserEvent
|
|
}
|
|
|
|
func (ua UserActiveEvent) Type() EventType {
|
|
return UserActive
|
|
}
|
|
|
|
func (ua UserActiveEvent) Disposable() bool {
|
|
return (time.Since(ua.created).Hours() / 24) >= float64(config.Get().UserEventLifespanDays)
|
|
}
|
|
|
|
func NewUserActiveEvent(user string) UserActiveEvent {
|
|
return UserActiveEvent{UserEvent{
|
|
uid: user,
|
|
created: time.Now(),
|
|
}}
|
|
}
|
|
|
|
const (
|
|
TestEventDisposeKey = "dispose"
|
|
TestEventIDKey = "id"
|
|
)
|
|
|
|
type TestEvent struct {
|
|
Dispose bool
|
|
ID int
|
|
}
|
|
|
|
func (te TestEvent) Type() EventType {
|
|
return Test
|
|
}
|
|
|
|
func (te TestEvent) Time() time.Time {
|
|
return time.Now()
|
|
}
|
|
|
|
func (te TestEvent) Data() map[string]string {
|
|
m := map[string]string{}
|
|
if te.Dispose {
|
|
m[TestEventDisposeKey] = "t"
|
|
}
|
|
m[TestEventIDKey] = fmt.Sprintf("%d", te.ID)
|
|
return m
|
|
}
|
|
|
|
func (te TestEvent) Validate() error {
|
|
return nil
|
|
}
|
|
|
|
func (te TestEvent) Disposable() bool {
|
|
return te.Dispose
|
|
}
|