Add basic infrastructure for bouncer service

This commit is contained in:
Simon Ser 2020-03-18 12:23:08 +01:00
parent 8274ff17c1
commit e3d97bb164
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
5 changed files with 121 additions and 5 deletions

View File

@ -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
View File

@ -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
View File

@ -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
View 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
}

View File

@ -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