service: Introduce channel update

This adds the `channel update` service command, which is used to set the
auto-detach, auto-reattach, and message relaying settings of a channel.

Of note is that currently the parser parses `#` as a comment, which
means any `channel update #foo ...` will actually need to be escaped to
`channel update "#foo" ...`
This commit is contained in:
delthas 2020-11-30 22:16:44 +01:00 committed by Simon Ser
parent a76b22bf29
commit 0ddc0de7e5
2 changed files with 155 additions and 1 deletions

View file

@ -170,6 +170,70 @@ abbreviated form, for instance *network* can be abbreviated as *net* or just
*network status*
Show a list of saved networks and their current status.
*channel update* <name> [options...]
Update the options of an existing channel.
Options are:
*-relay-detached* <mode>
Set when to relay messages from detached channels to the user with a BouncerServ NOTICE.
Modes are:
*message*
Relay any message from this channel when detached.
*highlight*
Relay only messages mentioning you when detached.
*none*
Don't relay any messages from this channel when detached.
*default*
Currently same as *highlight*. This is the default behaviour.
*-reattach-on* <mode>
Set when to automatically reattach to detached channels.
Modes are:
*message*
Reattach to this channel when any message is received.
*highlight*
Reattach to this channel when any message mentioning you is received.
*none*
Never automatically reattach to this channel.
*default*
Currently same as *none*. This is the default behaviour.
*-detach-after* <duration>
Automatically detach this channel after the specified duration has elapsed without receving any message corresponding to *-detach-on*.
Example duration values: *1h30m*, *30s*, *2.5h*.
Setting this value to 0 will disable this behaviour, i.e. this channel will never be automatically detached. This is the default behaviour.
*-detach-on* <mode>
Set when to reset the auto-detach timer used by *-detach-after*, causing it to wait again for the auto-detach duration timer before detaching.
Joining, reattaching, sending a message, or changing any channel option will reset the timer, in addition to the messages specified by the mode.
Modes are:
*message*
Receiving any message from this channel will reset the auto-detach timer.
*highlight*
Receiving any message mentioning you from this channel will reset the auto-detach timer.
*none*
Receiving messages from this channel will not reset the auto-detach timer. Sending messages or joining the channel will still reset the timer.
*default*
Currently same as *message*. This is the default behaviour.
*certfp generate* [options...] <network name>
Generate self-signed certificate and use it for authentication (via SASL
EXTERNAL).

View file

@ -218,6 +218,15 @@ func init() {
desc: "change your password",
handle: handlePasswordChange,
},
"channel": {
children: serviceCommandSet{
"update": {
usage: "<name> [-relay-detached <default|none|highlight|message>] [-reattach-on <default|none|highlight|message>] [-detach-after <duration>] [-detach-on <default|none|highlight|message>]",
desc: "update a channel",
handle: handleServiceChannelUpdate,
},
},
},
}
}
@ -427,7 +436,7 @@ func handleServiceNetworkStatus(dc *downstreamConn, params []string) error {
func handleServiceNetworkUpdate(dc *downstreamConn, params []string) error {
if len(params) < 1 {
return fmt.Errorf("expected exactly one argument")
return fmt.Errorf("expected at least one argument")
}
fs := newNetworkFlagSet()
@ -696,3 +705,84 @@ func handleUserDelete(dc *downstreamConn, params []string) error {
sendServicePRIVMSG(dc, fmt.Sprintf("deleted user %q", username))
return nil
}
type channelFlagSet struct {
*flag.FlagSet
RelayDetached, ReattachOn, DetachAfter, DetachOn *string
}
func newChannelFlagSet() *channelFlagSet {
fs := &channelFlagSet{FlagSet: newFlagSet()}
fs.Var(stringPtrFlag{&fs.RelayDetached}, "relay-detached", "")
fs.Var(stringPtrFlag{&fs.ReattachOn}, "reattach-on", "")
fs.Var(stringPtrFlag{&fs.DetachAfter}, "detach-after", "")
fs.Var(stringPtrFlag{&fs.DetachOn}, "detach-on", "")
return fs
}
func (fs *channelFlagSet) update(channel *Channel) error {
if fs.RelayDetached != nil {
filter, err := parseFilter(*fs.RelayDetached)
if err != nil {
return err
}
channel.RelayDetached = filter
}
if fs.ReattachOn != nil {
filter, err := parseFilter(*fs.ReattachOn)
if err != nil {
return err
}
channel.ReattachOn = filter
}
if fs.DetachAfter != nil {
dur, err := time.ParseDuration(*fs.DetachAfter)
if err != nil || dur < 0 {
return fmt.Errorf("unknown duration for -detach-after %q (duration format: 0, 300s, 22h30m, ...)", *fs.DetachAfter)
}
channel.DetachAfter = dur
}
if fs.DetachOn != nil {
filter, err := parseFilter(*fs.DetachOn)
if err != nil {
return err
}
channel.DetachOn = filter
}
return nil
}
func handleServiceChannelUpdate(dc *downstreamConn, params []string) error {
if len(params) < 1 {
return fmt.Errorf("expected at least one argument")
}
name := params[0]
fs := newChannelFlagSet()
if err := fs.Parse(params[1:]); err != nil {
return err
}
uc, upstreamName, err := dc.unmarshalEntity(name)
if err != nil {
return fmt.Errorf("unknown channel %q", name)
}
ch, ok := uc.network.channels[upstreamName]
if !ok {
return fmt.Errorf("unknown channel %q", name)
}
if err := fs.update(ch); err != nil {
return err
}
uc.updateChannelAutoDetach(upstreamName)
if err := dc.srv.db.StoreChannel(uc.network.ID, ch); err != nil {
return fmt.Errorf("failed to update channel: %v", err)
}
sendServicePRIVMSG(dc, fmt.Sprintf("updated channel %q", name))
return nil
}