Add basic infrastructure for bouncer service
This commit is contained in:
parent
8274ff17c1
commit
e3d97bb164
@ -326,15 +326,21 @@ func (dc *downstreamConn) handleMessage(msg *irc.Message) error {
|
||||
func (dc *downstreamConn) handleMessageUnregistered(msg *irc.Message) error {
|
||||
switch msg.Command {
|
||||
case "NICK":
|
||||
if err := parseMessageParams(msg, &dc.nick); err != nil {
|
||||
var nick string
|
||||
if err := parseMessageParams(msg, &nick); err != nil {
|
||||
return err
|
||||
}
|
||||
if nick == serviceNick {
|
||||
return ircError{&irc.Message{
|
||||
Command: irc.ERR_NICKNAMEINUSE,
|
||||
Params: []string{dc.nick, nick, "Nickname reserved for bouncer service"},
|
||||
}}
|
||||
}
|
||||
dc.nick = nick
|
||||
case "USER":
|
||||
var username string
|
||||
if err := parseMessageParams(msg, &username, nil, nil, &dc.realname); err != nil {
|
||||
if err := parseMessageParams(msg, &dc.rawUsername, nil, nil, &dc.realname); err != nil {
|
||||
return err
|
||||
}
|
||||
dc.rawUsername = username
|
||||
case "PASS":
|
||||
if err := parseMessageParams(msg, &dc.password); err != nil {
|
||||
return err
|
||||
@ -890,6 +896,11 @@ func (dc *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
|
||||
}
|
||||
|
||||
for _, name := range strings.Split(targetsStr, ",") {
|
||||
if name == serviceNick {
|
||||
handleServicePRIVMSG(dc, text)
|
||||
continue
|
||||
}
|
||||
|
||||
uc, upstreamName, err := dc.unmarshalChannel(name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
1
go.mod
1
go.mod
@ -4,6 +4,7 @@ go 1.13
|
||||
|
||||
require (
|
||||
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
|
||||
|
2
go.sum
2
go.sum
@ -2,6 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b h1:uhWtEWBHgop1rqEk2klKaxPAkVDCXexai6hSuRQ7Nvs=
|
||||
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
87
service.go
Normal file
87
service.go
Normal file
@ -0,0 +1,87 @@
|
||||
package soju
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/google/shlex"
|
||||
"gopkg.in/irc.v3"
|
||||
)
|
||||
|
||||
const serviceNick = "BouncerServ"
|
||||
|
||||
type serviceCommand struct {
|
||||
usage string
|
||||
desc string
|
||||
handle func(dc *downstreamConn, params []string) error
|
||||
}
|
||||
|
||||
func sendServicePRIVMSG(dc *downstreamConn, text string) {
|
||||
dc.SendMessage(&irc.Message{
|
||||
Prefix: &irc.Prefix{Name: serviceNick},
|
||||
Command: "PRIVMSG",
|
||||
Params: []string{dc.nick, text},
|
||||
})
|
||||
}
|
||||
|
||||
func handleServicePRIVMSG(dc *downstreamConn, text string) {
|
||||
words, err := shlex.Split(text)
|
||||
if err != nil {
|
||||
sendServicePRIVMSG(dc, fmt.Sprintf("error: failed to parse command: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
var name string
|
||||
var params []string
|
||||
if len(words) > 0 {
|
||||
name = strings.ToLower(words[0])
|
||||
params = words[1:]
|
||||
}
|
||||
|
||||
cmd, ok := serviceCommands[name]
|
||||
if !ok {
|
||||
sendServicePRIVMSG(dc, fmt.Sprintf(`error: unknown command %q (type "help" for a list of commands)`, name))
|
||||
return
|
||||
}
|
||||
|
||||
if err := cmd.handle(dc, params); err != nil {
|
||||
sendServicePRIVMSG(dc, fmt.Sprintf("error: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
var serviceCommands map[string]serviceCommand
|
||||
|
||||
func init() {
|
||||
serviceCommands = map[string]serviceCommand{
|
||||
"help": {
|
||||
usage: "[command]",
|
||||
desc: "print help message",
|
||||
handle: handleServiceHelp,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func handleServiceHelp(dc *downstreamConn, params []string) error {
|
||||
if len(params) > 0 {
|
||||
name := strings.ToLower(params[0])
|
||||
cmd, ok := serviceCommands[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown command %q", name)
|
||||
}
|
||||
|
||||
text := name
|
||||
if cmd.usage != "" {
|
||||
text += " " + cmd.usage
|
||||
}
|
||||
text += ": " + cmd.desc
|
||||
|
||||
sendServicePRIVMSG(dc, text)
|
||||
} else {
|
||||
var l []string
|
||||
for name := range serviceCommands {
|
||||
l = append(l, name)
|
||||
}
|
||||
sendServicePRIVMSG(dc, "available commands: "+strings.Join(l, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
17
upstream.go
17
upstream.go
@ -558,9 +558,24 @@ func (uc *upstreamConn) handleMessage(msg *irc.Message) error {
|
||||
forwardChannel(dc, ch)
|
||||
})
|
||||
case "PRIVMSG":
|
||||
if err := parseMessageParams(msg, nil, nil); err != nil {
|
||||
if msg.Prefix == nil {
|
||||
return fmt.Errorf("expected a prefix")
|
||||
}
|
||||
|
||||
var nick string
|
||||
if err := parseMessageParams(msg, &nick, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if msg.Prefix.Name == serviceNick {
|
||||
uc.logger.Printf("skipping PRIVMSG from soju's service: %v", msg)
|
||||
break
|
||||
}
|
||||
if nick == serviceNick {
|
||||
uc.logger.Printf("skipping PRIVMSG to soju's service: %v", msg)
|
||||
break
|
||||
}
|
||||
|
||||
uc.ring.Produce(msg)
|
||||
case "INVITE":
|
||||
var nick string
|
||||
|
Loading…
Reference in New Issue
Block a user