irc

package
v0.0.0-...-5be91bf Latest Latest
Warning

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

Go to latest
Published: May 14, 2025 License: MIT Imports: 2 Imported by: 0

README

A flexible and extensible IRC server library written in Go. It provides a modern approach to building IRC servers with full support for UnrealIRCd compatible channel and user modes.

Features

  • Flexible Configuration: Configure via YAML, TOML, or JSON files, with support for remote configuration via HTTPS
  • Plugin System: Extend functionality through a hook/callback system
  • Web Portal: Built-in web interface for operator management
  • Bot API: RESTful API for bots to interact with the IRC server
  • Mode Support: Complete implementation of UnrealIRCd compatible channel and user modes
  • TLS Support: Secure your IRC server with TLS
  • Hot Reload: Rehash configuration without restarting the server

Quick Start

Running the Server

# Run with default configuration (config.yaml)
go run main.go

# Run with a specific configuration file
go run main.go -config /path/to/config.yaml

# Run with a remote configuration
go run main.go -config https://example.com/config.yaml

Configuration

Copy the example configuration file to config.yaml:

cp config.yaml.example config.yaml

Edit the configuration to match your needs. See Configuration for details.

API Usage

Core Server

package main

import (
    "log"
    
    "github.com/yourusername/goircd/config"
    "github.com/yourusername/goircd/server"
)

func main() {
    // Load configuration
    cfg, err := config.Load("config.yaml")
    if err != nil {
        log.Fatalf("Failed to load configuration: %v", err)
    }
    
    // Create server
    srv, err := server.NewServer(cfg)
    if err != nil {
        log.Fatalf("Failed to create server: %v", err)
    }
    
    // Register custom hooks
    srv.RegisterHook("PRIVMSG", myCustomHandler)
    
    // Start server
    if err := srv.Start(); err != nil {
        log.Fatalf("Server failed: %v", err)
    }
}

func myCustomHandler(params *server.HookParams) error {
    // Custom handler for PRIVMSG
    client := params.Client
    message := params.Message
    
    // Log all private messages
    log.Printf("PRIVMSG from %s to %s: %s", 
        client.Nickname, 
        message.Params[0], 
        message.Params[1],
    )
    
    return nil
}

Custom Channel Implementation

package main

import (
    "fmt"
    
    "github.com/yourusername/goircd/server"
)

// CustomChannel extends the default Channel
type CustomChannel struct {
    *server.Channel
    CustomData map[string]interface{}
}

// NewCustomChannel creates a new custom channel
func NewCustomChannel(srv *server.Server, name string) *CustomChannel {
    return &CustomChannel{
        Channel:    server.NewChannel(srv, name),
        CustomData: make(map[string]interface{}),
    }
}

// CustomSendToAll sends a message to all members with a prefix
func (c *CustomChannel) CustomSendToAll(message string, except *server.Client) {
    c.SendToAll(fmt.Sprintf("[%s] %s", c.Name, message), except)
}

// Register a factory function to create custom channels
func registerCustomChannelFactory(srv *server.Server) {
    srv.ChannelFactory = func(srv *server.Server, name string) server.Channel {
        return NewCustomChannel(srv, name)
    }
}

Bot API Usage

The Bot API allows bots to interact with the IRC server via a RESTful API. Here's an example of sending a message to a channel:

curl -X POST \
  http://localhost:8081/api/send \
  -H 'Authorization: Bearer your-secret-token-1' \
  -H 'Content-Type: application/json' \
  -d '{
    "nickname": "MyBot",
    "channel": "#mychannel",
    "message": "Hello, world!"
  }'

Web Portal

The web portal provides a web interface for operator management. It allows operators to:

  • View server statistics
  • View and manage channels
  • View and manage users
  • Rehash the server configuration

Operators can log in using their operator credentials or via a magic link sent via IRC.

Configuration

The configuration file can be in YAML, TOML, or JSON format. See config.yaml.example for a complete example.

Key configuration sections:

  • server: Basic server settings
  • tls: TLS configuration
  • web_portal: Web portal configuration
  • bots: Bot API configuration
  • operators: Operator definitions
  • plugins: Plugin configuration

Environment Variables

All configuration options can be overridden with environment variables. The format is:

IRCD_SECTION_KEY=value

For example:

  • IRCD_SERVER_NAME=irc.example.com
  • IRCD_SERVER_PORT=6667
  • IRCD_TLS_ENABLED=true

IRC Commands

GoIRCd supports all standard IRC commands, including:

  • NICK: Change nickname
  • USER: Register user
  • JOIN: Join channel
  • PART: Leave channel
  • PRIVMSG: Send message
  • QUIT: Disconnect
  • MODE: Change channel or user modes
  • TOPIC: Change channel topic
  • KICK: Kick user from channel
  • OPER: Become an operator
  • KILL: Forcibly disconnect a user
  • REHASH: Reload configuration

Supported Modes

Channel Modes

  • p: Private channel
  • s: Secret channel
  • i: Invite-only channel
  • n: No messages from outside
  • m: Moderated channel
  • t: Topic settable by channel operators only
  • c: No colors allowed
  • C: No CTCPs allowed
  • D: Delayed join
  • f: Channel flood protection
  • P: Permanent channel
  • R: Only registered users can join
  • K: No knock allowed
  • N: No nickname changes while in channel
  • S: Strip colors from channel messages
  • l: User limit
  • k: Channel key (password)

User Modes

  • i: Invisible
  • o: IRC Operator
  • O: Local Operator
  • s: Receives server notices
  • w: Receives wallops
  • z: Connected via services
  • S: User is protected
  • k: User doesn't receive KNOCK notices
  • p: Blocks details for whois requests
  • r: Registered user
  • W: WebIRC user
  • I: Hides idle time in WHOIS
  • G: Allow filter bypass
  • C: No CTCPs

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

View Source
const (
	// 001 - 099: Welcome, info
	RPL_WELCOME       = 1   // Welcome to the Internet Relay Network <nick>!<user>@<host>
	RPL_YOURHOST      = 2   // Your host is <servername>, running version <ver>
	RPL_CREATED       = 3   // This server was created <date>
	RPL_MYINFO        = 4   // <servername> <version> <available user modes> <available channel modes>
	RPL_BOUNCE        = 5   // Try server <server name>, port <port number>
	RPL_ISUPPORT      = 5   // Also used for ISUPPORT (newer IRCDs)
	RPL_STATSCOMMANDS = 212 // <command> <count> <byte count> <remote count>
	RPL_ENDOFSTATS    = 219 // <stats letter> :End of STATS report
	RPL_UMODEIS       = 221 // <user mode string>
	RPL_SERVLIST      = 234 // <name> <server> <mask> <type> <hopcount> <info>
	RPL_SERVLISTEND   = 235 // <mask> <type> :End of service listing
	RPL_STATSLLINE    = 241 // L <hostmask> * <servername> <maxdepth>
	RPL_STATSUPTIME   = 242 // :Server Up %d days, %.2f hours
	RPL_STATSOLINE    = 243 // O <hostmask> * <name>
	RPL_STATSHLINE    = 244 // H <hostmask> * <servername>
	RPL_STATSDLINE    = 250 // Highest connection count: %d (%d clients)
	RPL_LUSERCLIENT   = 251 // :There are <integer> users and <integer> services on <integer> servers
	RPL_LUSEROP       = 252 // <integer> :operator(s) online
	RPL_LUSERUNKNOWN  = 253 // <integer> :unknown connection(s)
	RPL_LUSERCHANNELS = 254 // <integer> :channels formed
	RPL_LUSERME       = 255 // :I have <integer> clients and <integer> servers
	RPL_ADMINME       = 256 // <server> :Administrative info
	RPL_ADMINLOC1     = 257 // :<admin info>
	RPL_ADMINLOC2     = 258 // :<admin info>
	RPL_ADMINEMAIL    = 259 // :<admin info>
	RPL_TRACELOG      = 261 // File <logfile> <debug level>
	RPL_TRACEEND      = 262 // <server name> <version & debug level> :End of TRACE
	RPL_LOCALUSERS    = 265 // :Current local users: <integer> Max: <integer>
	RPL_GLOBALUSERS   = 266 // :Current global users: <integer> Max: <integer>
	RPL_ENDOFACCEPT   = 282 // :End of /ACCEPT list

	// 300 - 399: Command replies
	RPL_NONE            = 300 // Dummy reply
	RPL_AWAY            = 301 // <nick> :<away message>
	RPL_USERHOST        = 302 // :*1<reply> *( " " <reply> )
	RPL_ISON            = 303 // :*1<nick> *( " " <nick> )
	RPL_UNAWAY          = 305 // :You are no longer marked as being away
	RPL_NOWAWAY         = 306 // :You have been marked as being away
	RPL_WHOISUSER       = 311 // <nick> <user> <host> * :<real name>
	RPL_WHOISSERVER     = 312 // <nick> <server> :<server info>
	RPL_WHOISOPERATOR   = 313 // <nick> :is an IRC operator
	RPL_WHOWASUSER      = 314 // <nick> <user> <host> * :<real name>
	RPL_ENDOFWHO        = 315 // <name> :End of WHO list
	RPL_WHOISIDLE       = 317 // <nick> <integer> :seconds idle
	RPL_ENDOFWHOIS      = 318 // <nick> :End of WHOIS list
	RPL_WHOISCHANNELS   = 319 // <nick> :*( ( "@" / "+" ) <channel> " " )
	RPL_LISTSTART       = 321 // Channel :Users  Name
	RPL_LIST            = 322 // <channel> <# visible> :<topic>
	RPL_LISTEND         = 323 // :End of LIST
	RPL_CHANNELMODEIS   = 324 // <channel> <mode> <mode params>
	RPL_UNIQOPIS        = 325 // <channel> <nickname>
	RPL_NOTOPIC         = 331 // <channel> :No topic is set
	RPL_TOPIC           = 332 // <channel> :<topic>
	RPL_INVITING        = 341 // <channel> <nick>
	RPL_SUMMONING       = 342 // <user> :Summoning user to IRC
	RPL_INVITELIST      = 346 // <channel> <invitemask>
	RPL_ENDOFINVITELIST = 347 // <channel> :End of channel invite list
	RPL_EXCEPTLIST      = 348 // <channel> <exceptionmask>
	RPL_ENDOFEXCEPTLIST = 349 // <channel> :End of channel exception list
	RPL_VERSION         = 351 // <version>.<debuglevel> <server> :<comments>
	RPL_WHOREPLY        = 352 // <channel> <user> <host> <server> <nick> <H|G>[*][@|+] :<hopcount> <real name>
	RPL_NAMREPLY        = 353 // ( "=" / "*" / "@" ) <channel> :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
	RPL_ENDOFNAMES      = 366 // <channel> :End of NAMES list
	RPL_BANLIST         = 367 // <channel> <banmask>
	RPL_ENDOFBANLIST    = 368 // <channel> :End of channel ban list
	RPL_ENDOFWHOWAS     = 369 // <nick> :End of WHOWAS
	RPL_INFO            = 371 // :<string>
	RPL_MOTD            = 372 // :- <text>
	RPL_ENDOFINFO       = 374 // :End of INFO list
	RPL_MOTDSTART       = 375 // :- <server> Message of the day -
	RPL_ENDOFMOTD       = 376 // :End of MOTD command
	RPL_YOUREOPER       = 381 // :You are now an IRC operator
	RPL_REHASHING       = 382 // <config file> :Rehashing
	RPL_YOURESERVICE    = 383 // You are service <servicename>
	RPL_TIME            = 391 // <server> :<string showing server's local time>
	RPL_USERSSTART      = 392 // :UserID   Terminal  Host
	RPL_USERS           = 393 // :<username> <ttyline> <hostname>
	RPL_ENDOFUSERS      = 394 // :End of users
	RPL_NOUSERS         = 395 // :Nobody logged in

	// 400 - 599: Error replies
	ERR_NOSUCHNICK        = 401 // <nickname> :No such nick/channel
	ERR_NOSUCHSERVER      = 402 // <server name> :No such server
	ERR_NOSUCHCHANNEL     = 403 // <channel name> :No such channel
	ERR_CANNOTSENDTOCHAN  = 404 // <channel name> :Cannot send to channel
	ERR_TOOMANYCHANNELS   = 405 // <channel name> :You have joined too many channels
	ERR_WASNOSUCHNICK     = 406 // <nickname> :There was no such nickname
	ERR_TOOMANYTARGETS    = 407 // <target> :<error code> recipients. <abort message>
	ERR_NOSUCHSERVICE     = 408 // <service name> :No such service
	ERR_NOORIGIN          = 409 // :No origin specified
	ERR_NORECIPIENT       = 411 // :No recipient given (<command>)
	ERR_NOTEXTTOSEND      = 412 // :No text to send
	ERR_NOTOPLEVEL        = 413 // <mask> :No toplevel domain specified
	ERR_WILDTOPLEVEL      = 414 // <mask> :Wildcard in toplevel domain
	ERR_BADMASK           = 415 // <mask> :Bad Server/host mask
	ERR_UNKNOWNCOMMAND    = 421 // <command> :Unknown command
	ERR_NOMOTD            = 422 // :MOTD File is missing
	ERR_NOADMININFO       = 423 // <server> :No administrative info available
	ERR_FILEERROR         = 424 // :File error doing <file op> on <file>
	ERR_NONICKNAMEGIVEN   = 431 // :No nickname given
	ERR_ERRONEUSNICKNAME  = 432 // <nick> :Erroneous nickname
	ERR_NICKNAMEINUSE     = 433 // <nick> :Nickname is already in use
	ERR_NICKCOLLISION     = 436 // <nick> :Nickname collision KILL from <user>@<host>
	ERR_UNAVAILRESOURCE   = 437 // <nick/channel> :Nick/channel is temporarily unavailable
	ERR_USERNOTINCHANNEL  = 441 // <nick> <channel> :They aren't on that channel
	ERR_NOTONCHANNEL      = 442 // <channel> :You're not on that channel
	ERR_USERONCHANNEL     = 443 // <user> <channel> :is already on channel
	ERR_NOLOGIN           = 444 // <user> :User not logged in
	ERR_SUMMONDISABLED    = 445 // :SUMMON has been disabled
	ERR_USERSDISABLED     = 446 // :USERS has been disabled
	ERR_NOTREGISTERED     = 451 // :You have not registered
	ERR_NEEDMOREPARAMS    = 461 // <command> :Not enough parameters
	ERR_ALREADYREGISTRED  = 462 // :Unauthorized command (already registered)
	ERR_NOPERMFORHOST     = 463 // :Your host isn't among the privileged
	ERR_PASSWDMISMATCH    = 464 // :Password incorrect
	ERR_YOUREBANNEDCREEP  = 465 // :You are banned from this server
	ERR_YOUWILLBEBANNED   = 466 // :You will be banned
	ERR_KEYSET            = 467 // <channel> :Channel key already set
	ERR_CHANNELISFULL     = 471 // <channel> :Cannot join channel (+l)
	ERR_UNKNOWNMODE       = 472 // <char> :is unknown mode char to me
	ERR_INVITEONLYCHAN    = 473 // <channel> :Cannot join channel (+i)
	ERR_BANNEDFROMCHAN    = 474 // <channel> :Cannot join channel (+b)
	ERR_BADCHANNELKEY     = 475 // <channel> :Cannot join channel (+k)
	ERR_BADCHANMASK       = 476 // <channel> :Bad Channel Mask
	ERR_NOCHANMODES       = 477 // <channel> :Channel doesn't support modes
	ERR_BANLISTFULL       = 478 // <channel> <char> :Channel list is full
	ERR_NOPRIVILEGES      = 481 // :Permission Denied- You're not an IRC operator
	ERR_CHANOPRIVSNEEDED  = 482 // <channel> :You're not channel operator
	ERR_CANTKILLSERVER    = 483 // :You can't kill a server!
	ERR_RESTRICTED        = 484 // :Your connection is restricted!
	ERR_UNIQOPPRIVSNEEDED = 485 // :You're not the original channel operator
	ERR_NOOPERHOST        = 491 // :No O-lines for your host
	ERR_UMODEUNKNOWNFLAG  = 501 // :Unknown MODE flag
	ERR_USERSDONTMATCH    = 502 // :Cannot change mode for other users
	ERR_GHOSTEDCLIENT     = 503 // :Message could not be delivered to <nick>
	ERR_USERNOTONSERV     = 504 // <nick> :User not on this server
	ERR_WRONGPONG         = 513 // :To connect type /QUOTE PONG <number>
	ERR_HELPNOTFOUND      = 524 // <subject> :Help not found
	ERR_ACCEPTFULL        = 525 // :Accept list is full
	ERR_ACCEPTEXIST       = 526 // <nick> <user> <host> :is already on accept list
	ERR_ACCEPTNOT         = 527 // <nick> <user> <host> :is not on accept list
	ERR_NOINVITE          = 528 // <user> <channel> :Cannot invite to channel
	ERR_INVALIDSERVICE    = 552 // <nickname> :is an invalid service nickname
	ERR_LINKSET           = 553 // :Unknown error
	ERR_KILLDENY          = 561 // :Cannot kill client
	ERR_INVALIDACCOUNT    = 577 // :Invalid account
	ERR_NEEDREGGEDNICK    = 599 // :You must connect with a registered nickname
)

Command responses

Variables

This section is empty.

Functions

func FormatHostmask

func FormatHostmask(nick, user, host string) string

FormatHostmask formats a hostmask

func ParseHostmask

func ParseHostmask(hostmask string) (nick, user, host string)

ParseHostmask parses a hostmask (nick!user@host)

Types

type Message

type Message struct {
	Prefix  string
	Command string
	Params  []string
}

Message represents an IRC message

func ParseMessage

func ParseMessage(line string) *Message

ParseMessage parses an IRC message

func (*Message) ErrorReply

func (m *Message) ErrorReply(prefix, errorCode, target, message string) *Message

ErrorReply creates an error reply to this message

func (*Message) Reply

func (m *Message) Reply(prefix, command string, params ...string) *Message

Reply creates a new message as a reply to this message

func (*Message) String

func (m *Message) String() string

String returns the string representation of the message

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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