# Keys of other channels that should be searched in addition to this one when a query is sent against it. If auth is required on another channel referenced here, it must be equal to this channel's.
#extrasearchchannels = []
# A description (string) of the channel, will be shown on /path if specified
if not isinstance(channel, collections.abc.Mapping):
raise InvalidConfig(f'Invalid channel for {key!r}')
if any(x not in ('ircchannel', 'path', 'auth', 'active', 'hidden', 'extrasearchchannels') for x in channel):
if any(x not in ('ircchannel', 'path', 'auth', 'active', 'hidden', 'extrasearchchannels', 'description') for x in channel):
raise InvalidConfig(f'Unknown key(s) found in channel {key!r}')
if 'ircchannel' not in channel:
@@ -223,6 +223,11 @@ class Config(dict):
raise InvalidConfig(f'Invalid channel {key!r} extrasearchchannels: cannot refer to self')
# Validation of the values is performed after reading everything
if 'description' not in channel:
channel['description'] = None
if not isinstance(channel['description'], str) and channel['description'] is not None:
raise InvalidConfig(f'Invalid channel {key!r} description: must be a str or None')
# extrasearchchannels validation after reading all channels
for key, channel in obj['channels'].items():
if any(x not in obj['channels'] for x in channel['extrasearchchannels']):
@@ -806,11 +811,12 @@ class WebServer:
def __init__(self, config):
self.config = config
self._paths = {} # '/path' => ('#channel', auth, hidden, extrasearchpaths) where auth is either False (no authentication) or the HTTP header value for basic auth
self._paths = {} # '/path' => ('#channel', auth, hidden, extrasearchpaths, description) where auth is either False (no authentication) or the HTTP header value for basic auth
f'Basic {base64.b64encode(channel["auth"].encode("utf-8")).decode("utf-8")}' if channel['auth'] else False,
channel['hidden'],
[config['channels'][otherchannel]['path'] for otherchannel in channel['extrasearchchannels']]
[config['channels'][otherchannel]['path'] for otherchannel in channel['extrasearchchannels']],
channel['description'],
) for channel in config['channels'].values()}
needRebind = self.config['web'] != config['web'] #TODO only if there are changes to web.host or web.port; everything else can be updated without rebinding
self.config = config
@@ -870,6 +877,18 @@ class WebServer:
lines.append(f'{"(PW) " if auth else ""}<a href="/{html.escape(path)}/today">{html.escape(channel)}</a> (<a href="/{html.escape(path)}/search">search</a>)')