GoIRCd / events.go

package main

import "sort"

type EventResult uint

const (
	Allow EventResult = iota

const (
	PRI_HIGH = iota * 10

type EventHandler interface {
	Prioritize() int

type NormalPriority struct{}
type LowPriority struct{}
type HighPriority struct{}

func (*NormalPriority) Prioritize() int { return PRI_NORMAL }
func (*LowPriority) Prioritize() int    { return PRI_LOW }
func (*HighPriority) Prioritize() int   { return PRI_HIGH }

type TargetUsers interface {
	TargetUser(*User) bool

type TargetAllUsers int

func (TargetAllUsers) TargetUser(user *User) bool { return true }

var TargetAll = TargetAllUsers(0)

type TargetLocalUsers int

func (TargetLocalUsers) TargetUser(user *User) bool {
	return user.IsLocal()

var TargetLocal = TargetLocalUsers(0)

type TargetRemoteUsers int

func (TargetRemoteUsers) TargetUser(user *User) bool {
	return user.IsRemote()

var TargetRemote = TargetRemoteUsers(0)

type TargetPropagate struct {
	Source *ServerNode

func (t *TargetPropagate) TargetUser(user *User) bool {
	return t.Source.Route != user.Server.Route

type ExceptUsers map[*User]bool

func (e ExceptUsers) TargetUser(user *User) bool {
	return !e[user]

type TargetPrefix struct {
	Channel *Channel
	Level   PrefixLevel

func (t *TargetPrefix) TargetUser(user *User) bool {
	return t.Channel.GetPrefix(user)&t.Level != 0

type TargetAnd struct {
	Left, Right TargetUsers

func (t *TargetAnd) TargetUser(user *User) bool {
	return t.Left.TargetUser(user) && t.Right.TargetUser(user)

type TargetOr struct {
	Left, Right TargetUsers

func (t *TargetOr) TargetUser(user *User) bool {
	return t.Left.TargetUser(user) || t.Left.TargetUser(user)

type Event []EventHandler

func NewEvent() Event {
	return make(Event, 0)

func (ev *Event) AddHandler(handler EventHandler) {
	*ev = append(*ev, handler)

func (ev Event) Len() int {
	return len(ev)

func (ev Event) Less(i, j int) bool {
	return ev[i].Prioritize() < ev[j].Prioritize()

func (ev Event) Swap(i, j int) {
	ev[i], ev[j] = ev[j], ev[i]

var (
	// Occurs at program start and on explicit rehash
	Configure = NewEvent()
	// Occurs when a new Channel is joined
	ChannelCreation = NewEvent()
	// Occurs for each User in a Names list output
	NamesItem = NewEvent()
	// Occurs when a User requests numeric 005
	Numeric005 = NewEvent()
	// Occurs after a mode is set or unset
	PostModeChange = NewEvent()
	// Occurs after initialization, before the main loop begins
	Ready = NewEvent()
	// Occurs when successfully linked to a server
	ServerLink = NewEvent()
	// Occurs when splitting from a server
	ServerSplit = NewEvent()
	// Occurs when a User issues the /STATS command
	StatsRequest = NewEvent()
	// Occurs immediately before a server shutdown or restart
	Shutdown = NewEvent()
	// Occurs after a User has been kicked
	UserKick = NewEvent()
	// Occurs before a User parts from a Channel
	UserPart = NewEvent()
	// Occurs before new User data is broadcast across the network
	UserPreBroadcast = NewEvent()
	// Occurs before a registered User issues any command
	UserPreCommand = NewEvent()
	// Occurs before a User joins a Channel
	UserPreJoin = NewEvent()
	// Occurs before a User kicks another User from a Channel
	UserPreKick = NewEvent()
	// Occurs before a User sends a NOTICE or PRIVMSG
	UserPreMessage = NewEvent()
	// Occurs before a User issues a MODE command
	UserPreMode = NewEvent()
	// Occurs before a User changes their nickname
	UserPreNick = NewEvent()
	// Occurs before a User sets the TOPIC in a Channel
	UserPreSetTopic = NewEvent()
	// Occurs when a User requests a Whois
	UserPreWhois = NewEvent()
	// Occurs before a User quits the server
	UserQuit = NewEvent()
	// Occurs after a User successfully joins a Channel
	UserPostJoin = NewEvent()
	// Occurs after a User successfully sends a NOTICE or PRIVMSG
	UserPostMessage = NewEvent()
	// Occurs after a User succesfully registers and introductory numerics
	// have been sent.
	UserPostRegister = NewEvent()

type TargetType int

const (
	// Target is *Channel
	IsChannel TargetType = iota
	// Target is string pattern for Server names
	// Target is *User

type ConfigureHandler interface {
	// Called to load configuration directives
	Configure(config *Config) error

type ChannelCreationHandler interface {
	// Called when a Channel is created locally
	ChannelCreation(ch *Channel)

type NamesItemHandler interface {
	// Called for each User output in a Names list
	NamesItem(*Server, *User, *Channel, *User, *string) EventResult

type Numeric005Handler interface {
	// Called upon User request of numeric 005.
	// Capability parameters can be added with the given callback.
	Numeric005(serv *Server, cb func(string))

type PostModeChangeHandler interface {
	// Called after a mode is changed on either a Channel or a User
	PostModeChange(*Server, *User, TargetType, interface{}, bool, byte, string)

type ReadyHandler interface {

type ServerLinkHandler interface {
	ServerLink(*Server, *ServerNode)

type ServerSplitHandler interface {
	ServerSplit(*Server, *ServerNode, string)

type StatsRequestHandler interface {
	// Called upon request of STATS by a User
	StatsRequest(*Server, *User, byte)

type ShutdownHandler interface {

type UserKickHandler interface {
	UserKick(serv *Server, user *User, ch *Channel, kickee *User, reason string)

type UserPartHandler interface {
	UserPart(*Server, *User, *Channel, *string, ExceptUsers)

type UserPreBroadcastHandler interface {
	UserPreBroadcast(*Server, *User)

type UserPreCommandHandler interface {
	// Called before every command issued by a User
	UserPreCommand(*Server, *User, Tokens) (EventResult, ClientError)

type UserPreJoinHandler interface {
	// Called when a User attempts to join a Channel
	// Parameter ch *Channel is nil if it does not (yet) exist
	// Parameter level can be modified to set the User's prefix level only if
	// the Channel does not yet exist; it defaults to channel operator.
	UserPreJoin(serv *Server, user *User, name string, ch *Channel,
		level *PrefixLevel, key string) (result EventResult, err ClientError)

type UserPreKickHandler interface {
	// Called before a User attempts to kick another User from a Channel
	UserPreKick(user *User, ch *Channel, kickee *User, reason string) (EventResult, ClientError)

type UserPreMessageHandler interface {
	// Called when a User attempts to send a message (NOTICE or PRIVMSG) to a
	// User or Channel.
	// If typ is IsChannel, target will be a *Channel;
	// if typ is IsUser, target will be a *User;
	// If typ is IsChannel, level will be nonzero if the user is sending
	// a message only to a particular group of prefixed users.
	// cmd is the command being used to message, either "NOTICE" or "PRIVMSG"
	UserPreMessage(user *User, typ TargetType, target interface{},
		level PrefixLevel, cmd string, message *string) (result EventResult, err ClientError)

type UserPreModeHandler interface {
	UserPreMode(serv *Server, user *User, typ TargetType, target interface{},
		modes *string, params Tokens) (EventResult, ClientError)

type UserPreNickHandler interface {
	UserPreNick(*Server, *User, string) (EventResult, ClientError)

type UserPreSetTopicHandler interface {
	// Called when a User attempts to set or remove the topic on a Channel
	UserPreSetTopic(*Server, *User, *Channel, string) (EventResult, ClientError)

type UserPreWhoisHandler interface {
	// Called when a User requests the WhoIs records for another User.
	// The given func can be called with a numeric and a message to be sent
	// to the requesting User.
	UserPreWhois(serv *Server, user, other *User,
		addLine func(int, string)) (EventResult, ClientError)

type UserPostJoinHandler interface {
	UserPostJoin(serv *Server, user *User, ch *Channel, except ExceptUsers)

type UserPostMessageHandler interface {
	UserPostMessage(serv *Server, user *User, typ TargetType, target interface{},
		level PrefixLevel, cmd, message string)

type UserPostRegisterHandler interface {
	// Called after a User registers
	UserPostRegister(*Server, *User)

type UserQuitHandler interface {
	UserQuit(*Server, *User, *string, ExceptUsers)

// Convenience functions for compile-time safety

func HandleChannelCreation(h ChannelCreationHandler)   { ChannelCreation.AddHandler(h) }
func HandleConfigure(h ConfigureHandler)               { Configure.AddHandler(h) }
func HandleNamesItem(h NamesItemHandler)               { NamesItem.AddHandler(h) }
func HandleNumeric005(h Numeric005Handler)             { Numeric005.AddHandler(h) }
func HandlePostModeChange(h PostModeChangeHandler)     { PostModeChange.AddHandler(h) }
func HandleReady(h ReadyHandler)                       { Ready.AddHandler(h) }
func HandleServerLink(h ServerLinkHandler)             { ServerLink.AddHandler(h) }
func HandleServerSplit(h ServerSplitHandler)           { ServerSplit.AddHandler(h) }
func HandleStatsRequest(h StatsRequestHandler)         { StatsRequest.AddHandler(h) }
func HandleShutdown(h ShutdownHandler)                 { Shutdown.AddHandler(h) }
func HandleUserKick(h UserKickHandler)                 { UserKick.AddHandler(h) }
func HandleUserPart(h UserPartHandler)                 { UserPart.AddHandler(h) }
func HandleUserPreBroadcast(h UserPreBroadcastHandler) { UserPreBroadcast.AddHandler(h) }
func HandleUserPreCommand(h UserPreCommandHandler)     { UserPreCommand.AddHandler(h) }
func HandleUserPreJoin(h UserPreJoinHandler)           { UserPreJoin.AddHandler(h) }
func HandleUserPreKick(h UserPreKickHandler)           { UserPreKick.AddHandler(h) }
func HandleUserPreMessage(h UserPreMessageHandler)     { UserPreMessage.AddHandler(h) }
func HandleUserPreMode(h UserPreModeHandler)           { UserPreMode.AddHandler(h) }
func HandleUserPreNick(h UserPreNickHandler)           { UserPreNick.AddHandler(h) }
func HandleUserPreSetTopic(h UserPreSetTopicHandler)   { UserPreSetTopic.AddHandler(h) }
func HandleUserPreWhois(h UserPreWhoisHandler)         { UserPreWhois.AddHandler(h) }
func HandleUserPostJoin(h UserPostJoinHandler)         { UserPostJoin.AddHandler(h) }
func HandleUserPostMessage(h UserPostMessageHandler)   { UserPostMessage.AddHandler(h) }
func HandleUserPostRegister(h UserPostRegisterHandler) { UserPostRegister.AddHandler(h) }
func HandleUserQuit(h UserQuitHandler)                 { UserQuit.AddHandler(h) }