mirror of
https://github.com/ergochat/ergo.git
synced 2025-04-29 11:18:00 +02:00
OPER command
This commit is contained in:
parent
85e2f65b1b
commit
41e79e3b09
@ -6,17 +6,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
// communication
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
hostname string
|
|
||||||
send chan<- Reply
|
send chan<- Reply
|
||||||
recv <-chan string
|
recv <-chan string
|
||||||
|
// basic info
|
||||||
username string
|
username string
|
||||||
realname string
|
realname string
|
||||||
|
hostname string
|
||||||
nick string
|
nick string
|
||||||
|
serverPass bool
|
||||||
|
// modes
|
||||||
|
away bool
|
||||||
registered bool
|
registered bool
|
||||||
invisible bool
|
invisible bool
|
||||||
channels ChannelSet
|
wallOps bool
|
||||||
|
restricted bool
|
||||||
|
operator bool
|
||||||
|
localOperator bool
|
||||||
|
// relations
|
||||||
server *Server
|
server *Server
|
||||||
|
channels ChannelSet
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientSet map[*Client]bool
|
type ClientSet map[*Client]bool
|
||||||
|
@ -13,8 +13,8 @@ type Message interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotEnoughArgs = errors.New("not enough arguments")
|
NotEnoughArgsError = errors.New("not enough arguments")
|
||||||
ErrUModeUnknownFlag = errors.New("unknown umode flag")
|
UModeUnknownFlagError = errors.New("unknown umode flag")
|
||||||
)
|
)
|
||||||
|
|
||||||
// unknown
|
// unknown
|
||||||
@ -38,7 +38,7 @@ type PingMessage struct {
|
|||||||
|
|
||||||
func NewPingMessage(args []string) (Message, error) {
|
func NewPingMessage(args []string) (Message, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
msg := &PingMessage{server: args[0]}
|
msg := &PingMessage{server: args[0]}
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
@ -60,7 +60,7 @@ type PongMessage struct {
|
|||||||
|
|
||||||
func NewPongMessage(args []string) (Message, error) {
|
func NewPongMessage(args []string) (Message, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
message := &PongMessage{server1: args[0]}
|
message := &PongMessage{server1: args[0]}
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
@ -73,6 +73,27 @@ func (m *PongMessage) Handle(s *Server, c *Client) {
|
|||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PASS <password>
|
||||||
|
|
||||||
|
type PassMessage struct {
|
||||||
|
password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPassMessage(args []string) (Message, error) {
|
||||||
|
if len(args) < 1 {
|
||||||
|
return nil, NotEnoughArgsError
|
||||||
|
}
|
||||||
|
return &PassMessage{password: args[0]}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *PassMessage) Handle(s *Server, c *Client) {
|
||||||
|
if m.password == server.password {
|
||||||
|
c.serverPass = true
|
||||||
|
} else {
|
||||||
|
c.send <- ErrPass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NICK
|
// NICK
|
||||||
|
|
||||||
type NickMessage struct {
|
type NickMessage struct {
|
||||||
@ -81,7 +102,7 @@ type NickMessage struct {
|
|||||||
|
|
||||||
func NewNickMessage(args []string) (Message, error) {
|
func NewNickMessage(args []string) (Message, error) {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
return &NickMessage{args[0]}, nil
|
return &NickMessage{args[0]}, nil
|
||||||
}
|
}
|
||||||
@ -101,7 +122,7 @@ type UserMessage struct {
|
|||||||
|
|
||||||
func NewUserMessage(args []string) (Message, error) {
|
func NewUserMessage(args []string) (Message, error) {
|
||||||
if len(args) != 4 {
|
if len(args) != 4 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
msg := &UserMessage{
|
msg := &UserMessage{
|
||||||
user: args[0],
|
user: args[0],
|
||||||
@ -119,7 +140,7 @@ func (m *UserMessage) Handle(s *Server, c *Client) {
|
|||||||
s.UserLogin(c, m.user, m.realname)
|
s.UserLogin(c, m.user, m.realname)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QUIT
|
// QUIT [ <Quit Message> ]
|
||||||
|
|
||||||
type QuitMessage struct {
|
type QuitMessage struct {
|
||||||
message string
|
message string
|
||||||
@ -137,18 +158,19 @@ func (m *QuitMessage) Handle(s *Server, c *Client) {
|
|||||||
s.Quit(c, m.message)
|
s.Quit(c, m.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MODE
|
// MODE <nickname> *( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
|
||||||
|
|
||||||
type ModeMessage struct {
|
type ModeMessage struct {
|
||||||
nickname string
|
nickname string
|
||||||
modes []string
|
modes []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var MODE_RE = regexp.MustCompile("^[-+][a-zA-Z]+$")
|
// mode s is accepted but ignored, like some other modes
|
||||||
|
var MODE_RE = regexp.MustCompile("^[-+][iwroOs]+$")
|
||||||
|
|
||||||
func NewModeMessage(args []string) (Message, error) {
|
func NewModeMessage(args []string) (Message, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
msg := &ModeMessage{
|
msg := &ModeMessage{
|
||||||
nickname: args[0],
|
nickname: args[0],
|
||||||
@ -174,7 +196,7 @@ func (m *ModeMessage) Handle(s *Server, c *Client) {
|
|||||||
s.ChangeUserMode(c, m.modes)
|
s.ChangeUserMode(c, m.modes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// JOIN
|
// JOIN ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0"
|
||||||
|
|
||||||
type JoinMessage struct {
|
type JoinMessage struct {
|
||||||
channels []string
|
channels []string
|
||||||
@ -224,7 +246,7 @@ type PartMessage struct {
|
|||||||
|
|
||||||
func NewPartMessage(args []string) (Message, error) {
|
func NewPartMessage(args []string) (Message, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
msg := &PartMessage{channels: strings.Split(args[0], ",")}
|
msg := &PartMessage{channels: strings.Split(args[0], ",")}
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
@ -255,7 +277,7 @@ type PrivMsgMessage struct {
|
|||||||
|
|
||||||
func NewPrivMsgMessage(args []string) (Message, error) {
|
func NewPrivMsgMessage(args []string) (Message, error) {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
return &PrivMsgMessage{
|
return &PrivMsgMessage{
|
||||||
target: args[0],
|
target: args[0],
|
||||||
@ -298,7 +320,7 @@ type TopicMessage struct {
|
|||||||
|
|
||||||
func NewTopicMessage(args []string) (Message, error) {
|
func NewTopicMessage(args []string) (Message, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
msg := &TopicMessage{channel: args[0]}
|
msg := &TopicMessage{channel: args[0]}
|
||||||
if len(args) > 1 {
|
if len(args) > 1 {
|
||||||
@ -329,7 +351,7 @@ type InviteMessage struct {
|
|||||||
|
|
||||||
func NewInviteMessage(args []string) (Message, error) {
|
func NewInviteMessage(args []string) (Message, error) {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return nil, ErrNotEnoughArgs
|
return nil, NotEnoughArgsError
|
||||||
}
|
}
|
||||||
return &InviteMessage{
|
return &InviteMessage{
|
||||||
nickname: args[0],
|
nickname: args[0],
|
||||||
@ -352,3 +374,28 @@ func (m *InviteMessage) Handle(s *Server, c *Client) {
|
|||||||
|
|
||||||
channel.Invite(c, invitee)
|
channel.Invite(c, invitee)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OPER <name> <password>
|
||||||
|
|
||||||
|
type OperMessage struct {
|
||||||
|
name string
|
||||||
|
password string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOperMessage(args []string) Message {
|
||||||
|
if len(args) < 2 {
|
||||||
|
return nil, NotEnoughArgsError
|
||||||
|
}
|
||||||
|
return &OperMessage{
|
||||||
|
name: args[0],
|
||||||
|
password: args[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *OperMessage) Handle(s *Server, c *Client) {
|
||||||
|
if s.operators[m.name] == m.password {
|
||||||
|
c.send <- RplYoureOper(s)
|
||||||
|
} else {
|
||||||
|
c.send <- ErrPasswdMismatch(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,12 +15,14 @@ var (
|
|||||||
"MODE": NewModeMessage,
|
"MODE": NewModeMessage,
|
||||||
"NICK": NewNickMessage,
|
"NICK": NewNickMessage,
|
||||||
"PART": NewPartMessage,
|
"PART": NewPartMessage,
|
||||||
|
"PASS": NewPassMessage,
|
||||||
"PING": NewPingMessage,
|
"PING": NewPingMessage,
|
||||||
"PONG": NewPongMessage,
|
"PONG": NewPongMessage,
|
||||||
"PRIVMSG": NewPrivMsgMessage,
|
"PRIVMSG": NewPrivMsgMessage,
|
||||||
"QUIT": NewQuitMessage,
|
"QUIT": NewQuitMessage,
|
||||||
"TOPIC": NewTopicMessage,
|
"TOPIC": NewTopicMessage,
|
||||||
"USER": NewUserMessage,
|
"USER": NewUserMessage,
|
||||||
|
"OPER": NewOperMessage,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ func RplCreated(server *Server) Reply {
|
|||||||
|
|
||||||
func RplMyInfo(server *Server) Reply {
|
func RplMyInfo(server *Server) Reply {
|
||||||
return NewReply(server, RPL_MYINFO,
|
return NewReply(server, RPL_MYINFO,
|
||||||
fmt.Sprintf("%s %s i ik", server.name, VERSION))
|
fmt.Sprintf("%s %s iwroO ik", server.name, VERSION))
|
||||||
}
|
}
|
||||||
|
|
||||||
func RplUModeIs(server *Server, client *Client) Reply {
|
func RplUModeIs(server *Server, client *Client) Reply {
|
||||||
@ -122,6 +122,12 @@ func RplPong(server *Server) Reply {
|
|||||||
return NewReply(server, RPL_PONG, "")
|
return NewReply(server, RPL_PONG, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// server functions
|
||||||
|
|
||||||
|
func RplYoureOper(server *Server) Reply {
|
||||||
|
return NewReply(server, RPL_YOUREOPER, ":You are now an IRC operator")
|
||||||
|
}
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
|
|
||||||
func ErrAlreadyRegistered(source Identifier) Reply {
|
func ErrAlreadyRegistered(source Identifier) Reply {
|
||||||
@ -177,3 +183,7 @@ func ErrNoSuchNick(source Identifier, nick string) Reply {
|
|||||||
return NewReply(source, ERR_NOSUCHNICK,
|
return NewReply(source, ERR_NOSUCHNICK,
|
||||||
nick+" :No such nick/channel")
|
nick+" :No such nick/channel")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ErrPasswdMismatch(server *Server) Reply {
|
||||||
|
return NewReply(server, ERR_PASSWDMISMATCH, ":Password incorrect")
|
||||||
|
}
|
||||||
|
@ -13,6 +13,8 @@ type Server struct {
|
|||||||
recv chan<- *ClientMessage
|
recv chan<- *ClientMessage
|
||||||
nicks map[string]*Client
|
nicks map[string]*Client
|
||||||
channels map[string]*Channel
|
channels map[string]*Channel
|
||||||
|
password string
|
||||||
|
operators map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientMessage struct {
|
type ClientMessage struct {
|
||||||
@ -68,6 +70,10 @@ func (s *Server) GetOrMakeChannel(name string) *Channel {
|
|||||||
return channel
|
return channel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) AddOperator(name string, password string) {
|
||||||
|
s.operators[name] = password
|
||||||
|
}
|
||||||
|
|
||||||
// Send a message to clients of channels fromClient is a member.
|
// Send a message to clients of channels fromClient is a member.
|
||||||
func (s *Server) SendToInterestedClients(fromClient *Client, reply Reply) {
|
func (s *Server) SendToInterestedClients(fromClient *Client, reply Reply) {
|
||||||
clients := make(map[*Client]bool)
|
clients := make(map[*Client]bool)
|
||||||
@ -114,7 +120,7 @@ func (s *Server) UserLogin(c *Client, user string, realName string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) tryRegister(c *Client) {
|
func (s *Server) tryRegister(c *Client) {
|
||||||
if !c.registered && c.HasNick() && c.HasUser() {
|
if !c.registered && c.HasNick() && c.HasUser() && (s.password == "" || c.serverAuth) {
|
||||||
c.registered = true
|
c.registered = true
|
||||||
c.send <- RplWelcome(s, c)
|
c.send <- RplWelcome(s, c)
|
||||||
c.send <- RplYourHost(s, c)
|
c.send <- RplYourHost(s, c)
|
||||||
@ -134,10 +140,21 @@ func (s *Server) Quit(c *Client, message string) {
|
|||||||
|
|
||||||
func (s *Server) ChangeUserMode(c *Client, modes []string) {
|
func (s *Server) ChangeUserMode(c *Client, modes []string) {
|
||||||
for _, mode := range modes {
|
for _, mode := range modes {
|
||||||
if mode == "+i" {
|
switch mode {
|
||||||
|
case "+i":
|
||||||
c.invisible = true
|
c.invisible = true
|
||||||
} else if mode == "-i" {
|
case "-i":
|
||||||
c.invisible = false
|
c.invisible = false
|
||||||
|
case "-o":
|
||||||
|
c.operator = false
|
||||||
|
case "-O":
|
||||||
|
c.localOperator = false
|
||||||
|
case "+r":
|
||||||
|
c.restricted = true
|
||||||
|
case "+w":
|
||||||
|
c.wallOps = true
|
||||||
|
case "-w":
|
||||||
|
c.wallOps = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.send <- RplUModeIs(s, c)
|
c.send <- RplUModeIs(s, c)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user