premium

package
v2.41.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2024 License: MIT Imports: 36 Imported by: 0

README

Package premium provides functionality to give guilds premium status through various sources (patreon only atm).

It maintains a list of premium users and guilds and their slots in redis, compiled from each source.

Those redis lists/sets/hashes are updated at a certain interval from the sources, that means no matter how many sources you only have to check 1 key to see if a guild is premium, it also simplifies things as a whole.

Documentation

Index

Constants

View Source
const (
	PremiumStateMaxMessags    = 10000
	PremiumStateMaxMessageAge = time.Hour * 12
)
View Source
const (
	// Hash
	// Key: guild id's
	// Value: the user id's providing the premium status
	RedisKeyPremiumGuilds          = "premium_activated_guilds"
	RedisKeyPremiumGuildsTmp       = "premium_activated_guilds_tmp"
	RedisKeyPremiumGuildLastActive = "premium_guild_last_active"
)
View Source
const (
	FeatureFlagPremiumPlus = "premium_plus"
	FeatureFlagPremiumFull = "premium_full"
)

Variables

View Source
var (
	ErrCodeExpired  = errors.New("Code expired")
	ErrCodeNotFound = errors.New("Code not found")
)
View Source
var (
	PremiumSources      []PremiumSource
	GuildPremiumSources []GuildPremiumSource
)
View Source
var (
	ErrSlotNotFound        = errors.New("premium slot not found")
	ErrGuildAlreadyPremium = errors.New("guild already assigned premium from another slot")
)
View Source
var DBSchemas = []string{`
CREATE TABLE IF NOT EXISTS premium_slots (
	id BIGSERIAL PRIMARY KEY,

	created_at TIMESTAMP WITH TIME ZONE NOT NULL,
	attached_at TIMESTAMP WITH TIME ZONE,

	user_id BIGINT NOT NULL,
	guild_id BIGINT,

	title TEXT NOT NULL,
	message TEXT NOT NULL,
	source TEXT NOT NULL,
	source_id BIGINT NOT NULL,

	full_duration BIGINT NOT NULL,
	permanent BOOLEAN NOT NULL,
	duration_remaining BIGINT NOT NULL
); 
`, `
ALTER TABLE premium_slots ADD COLUMN IF NOT EXISTS tier INT NOT NULL DEFAULT 1;
`, `
CREATE TABLE IF NOT EXISTS premium_codes (
	id BIGSERIAL PRIMARY KEY,

	code TEXT UNIQUE NOT NULL,
	message TEXT NOT NULL,

	created_at TIMESTAMP WITH TIME ZONE NOT NULL,
	used_at TIMESTAMP WITH TIME ZONE,
	slot_id BIGINT references premium_slots(id),

	user_id BIGINT,
	guild_id BIGINT,

	permanent BOOLEAN NOT NULL,
	duration BIGINT NOT NULL
);
`, `
CREATE INDEX IF NOT EXISTS premium_codes_code_idx ON premium_codes(code);
`}
View Source
var (
	ErrCodeCollision = errors.New("Code collision")
)
View Source
var PageHTML string

Functions

func AllGuildsOncePremium

func AllGuildsOncePremium() (map[int64]time.Time, error)

AllGuildsOncePremium returns all the guilds that have has premium once, and the last time that was active

func AttachSlotToGuild

func AttachSlotToGuild(ctx context.Context, slotID int64, userID int64, guildID int64) error

func ContextPremium

func ContextPremium(ctx context.Context) bool

func CreatePremiumSlot

func CreatePremiumSlot(ctx context.Context, exec boil.ContextExecutor, userID int64, source, title, message string, sourceSlotID int64, duration time.Duration, tier PremiumTier) (*models.PremiumSlot, error)

func DetachSlotFromGuild

func DetachSlotFromGuild(ctx context.Context, slotID int64, userID int64) error

func GenerateCode

func GenerateCode(ctx context.Context, message string, duration time.Duration) (*models.PremiumCode, error)

GenerateCode generates a redeemable premium code with the specified duration (-1 for permanent) and message

func HandleGetPremiumMainPage

func HandleGetPremiumMainPage(w http.ResponseWriter, r *http.Request) (tmpl web.TemplateData, err error)

func HandlePostDetachGuildSlot

func HandlePostDetachGuildSlot(w http.ResponseWriter, r *http.Request) (tmpl web.TemplateData, err error)

func HandlePostLookupCode

func HandlePostLookupCode(w http.ResponseWriter, r *http.Request) (tmpl web.TemplateData, err error)

func HandlePostRedeemCode

func HandlePostRedeemCode(w http.ResponseWriter, r *http.Request) (tmpl web.TemplateData, err error)

func HandlePostUpdateSlot

func HandlePostUpdateSlot(w http.ResponseWriter, r *http.Request) (tmpl web.TemplateData, err error)

func IsGuildPremium

func IsGuildPremium(guildID int64) (bool, error)

IsGuildPremium return true if the provided guild has the premium status or not This is a legacy function mostly as anything equal to and above plus is counted as premium if you want more granular control use the other functions

func LookupCode

func LookupCode(ctx context.Context, code string) (*models.PremiumCode, error)

func PremiumGuildMW

func PremiumGuildMW(inner http.Handler) http.Handler

PremiumGuildMW adds premium data to context and tmpl vars

func PremiumProvidedBy

func PremiumProvidedBy(guildID int64) (int64, error)

func RedeemCode

func RedeemCode(ctx context.Context, code string, userID int64) error

func RegisterGuildPremiumSource

func RegisterGuildPremiumSource(source GuildPremiumSource)

func RegisterPlugin

func RegisterPlugin()

func RegisterPremiumSource

func RegisterPremiumSource(source PremiumSource)

func RemovePremiumSlots

func RemovePremiumSlots(ctx context.Context, exec boil.ContextExecutor, userID int64, slotsToRemove []int64) error

RemovePremiumSlots removes the specifues premium slots and attempts to migrate to other permanent available ones THIS SHOULD BE USED INSIDE A TRANSACTION ONLY, AS OTHERWISE RACE CONDITIONS BE UPON THEE

func SlotDurationLeft

func SlotDurationLeft(slot *models.PremiumSlot) (duration time.Duration)

func SlotExpired

func SlotExpired(ctx context.Context, slot *models.PremiumSlot) error

func TryRetryGenerateCode

func TryRetryGenerateCode(ctx context.Context, message string, duration time.Duration) (*models.PremiumCode, error)

TryRetryGenerateCode attempts to generate codes, if it enocunters a key collision it retries, returns on all other cases

func UserPremiumSlots

func UserPremiumSlots(ctx context.Context, userID int64) (slots []*models.PremiumSlot, err error)

UserPremiumSlots returns all slots for a user

Types

type CodePremiumSource

type CodePremiumSource struct{}

func (*CodePremiumSource) Init

func (ps *CodePremiumSource) Init()

func (*CodePremiumSource) Names

func (ps *CodePremiumSource) Names() (human string, idname string)

type CtxKey

type CtxKey int
var (
	CtxKeyIsPremium   CtxKey = 1
	CtxKeyPremiumTier CtxKey = 2
)

type GuildPremiumSource

type GuildPremiumSource interface {
	Name() string
	GuildPremiumDetails(guildID int64) (tier PremiumTier, humanDetails []string, err error)
	GuildPremiumTier(guildID int64) (PremiumTier, error)
	AllGuildsPremiumTiers() (map[int64]PremiumTier, error)
}

type NewPremiumGuildListener

type NewPremiumGuildListener interface {
	OnNewPremiumGuild(guildID int64) error
}

type Plugin

type Plugin struct {
}

func (*Plugin) AddCommands

func (p *Plugin) AddCommands()

func (*Plugin) AllFeatureFlags

func (p *Plugin) AllFeatureFlags() []string

func (*Plugin) BotInit

func (p *Plugin) BotInit()

func (*Plugin) InitWeb

func (p *Plugin) InitWeb()

func (*Plugin) LoadServerHomeWidget

func (p *Plugin) LoadServerHomeWidget(w http.ResponseWriter, r *http.Request) (web.TemplateData, error)

func (*Plugin) PluginInfo

func (p *Plugin) PluginInfo() *common.PluginInfo

func (*Plugin) RunBackgroundWorker

func (p *Plugin) RunBackgroundWorker()

func (*Plugin) ServerHomeWidgetOrder

func (p *Plugin) ServerHomeWidgetOrder() int

func (*Plugin) StopBackgroundWorker

func (p *Plugin) StopBackgroundWorker(wg *sync.WaitGroup)

func (*Plugin) UpdateFeatureFlags

func (p *Plugin) UpdateFeatureFlags(guildID int64) ([]string, error)

func (*Plugin) UpdateFeatureFlagsBatch

func (p *Plugin) UpdateFeatureFlagsBatch() (map[int64][]string, error)

type PremiumSource

type PremiumSource interface {
	Init()
	Names() (human string, idname string)
}

func FindSource

func FindSource(sourceID string) PremiumSource

type PremiumTier

type PremiumTier int
const (
	PremiumTierNone    PremiumTier = 0
	PremiumTierPremium PremiumTier = 1
	PremiumTierPlus    PremiumTier = 2
)

func ContextPremiumTier

func ContextPremiumTier(ctx context.Context) PremiumTier

func GuildPremiumTier

func GuildPremiumTier(guildID int64) (PremiumTier, error)

func (PremiumTier) String

func (p PremiumTier) String() string

type RemovedPremiumGuildListener

type RemovedPremiumGuildListener interface {
	OnRemovedPremiumGuild(guildID int64) error
}

type SlotGuildPremiumSource

type SlotGuildPremiumSource struct{}

func (*SlotGuildPremiumSource) AllGuildsPremiumTiers

func (s *SlotGuildPremiumSource) AllGuildsPremiumTiers() (map[int64]PremiumTier, error)

func (*SlotGuildPremiumSource) GuildPremiumDetails

func (s *SlotGuildPremiumSource) GuildPremiumDetails(guildID int64) (tier PremiumTier, humanDetails []string, err error)

func (*SlotGuildPremiumSource) GuildPremiumTier

func (s *SlotGuildPremiumSource) GuildPremiumTier(guildID int64) (PremiumTier, error)

func (*SlotGuildPremiumSource) Name

func (s *SlotGuildPremiumSource) Name() string

type UpdateData

type UpdateData struct {
	GuildID int64
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL