Allow channel path to be customizable
We now allow server operators to customize the /r/ part of the channel links The new config option in the template is commented and the config module validates and will terminate with status 78 if an improper value is used. We've also dropped some old cruft and uses a more elegant method to assign CHANNEL.name Resolves #668
This commit is contained in:
parent
00a65a1584
commit
6d4558c978
|
@ -138,8 +138,6 @@ mail:
|
||||||
# 5. Click "Server key"
|
# 5. Click "Server key"
|
||||||
# 6. Under "APIs & auth" click "YouTube Data API" and then click "Enable API"
|
# 6. Under "APIs & auth" click "YouTube Data API" and then click "Enable API"
|
||||||
youtube-v3-key: ''
|
youtube-v3-key: ''
|
||||||
# Minutes between saving channel state to disk
|
|
||||||
channel-save-interval: 5
|
|
||||||
# Limit for the number of channels a user can register
|
# Limit for the number of channels a user can register
|
||||||
max-channels-per-user: 5
|
max-channels-per-user: 5
|
||||||
# Limit for the number of accounts an IP address can register
|
# Limit for the number of accounts an IP address can register
|
||||||
|
@ -147,6 +145,24 @@ max-accounts-per-ip: 5
|
||||||
# Minimum number of seconds between guest logins from the same IP
|
# Minimum number of seconds between guest logins from the same IP
|
||||||
guest-login-delay: 60
|
guest-login-delay: 60
|
||||||
|
|
||||||
|
# Allows you to customize the path divider. The /r/ in http://localhost/r/yourchannel
|
||||||
|
# Acceptable characters are a-z A-Z 0-9 _ and -
|
||||||
|
channel-path: 'r'
|
||||||
|
# Allows you to blacklist certain channels. Users will be automatically kicked
|
||||||
|
# upon trying to join one.
|
||||||
|
channel-blacklist: []
|
||||||
|
# Minutes between saving channel state to disk
|
||||||
|
channel-save-interval: 5
|
||||||
|
# Determines channel data storage mechanism.
|
||||||
|
# Defaults to 'file', in which channel data is JSON stringified and saved to a file
|
||||||
|
# in the `chandump/` folder. This is the legacy behavior of CyTube.
|
||||||
|
# The other possible option is 'database', in which case each key-value pair of
|
||||||
|
# channel data is stored as a row in the `channel_data` database table.
|
||||||
|
# To migrate legacy chandump files to the database, shut down CyTube (to prevent
|
||||||
|
# concurrent updates), then run `node lib/channel-storage/migrate.js`.
|
||||||
|
channel-storage:
|
||||||
|
type: 'file'
|
||||||
|
|
||||||
# Configure statistics tracking
|
# Configure statistics tracking
|
||||||
stats:
|
stats:
|
||||||
# Interval (in milliseconds) between data points - default 1h
|
# Interval (in milliseconds) between data points - default 1h
|
||||||
|
@ -208,10 +224,6 @@ playlist:
|
||||||
# The server must be invoked with node --expose-gc index.js for this to have any effect.
|
# The server must be invoked with node --expose-gc index.js for this to have any effect.
|
||||||
aggressive-gc: false
|
aggressive-gc: false
|
||||||
|
|
||||||
# Allows you to blacklist certain channels. Users will be automatically kicked
|
|
||||||
# upon trying to join one.
|
|
||||||
channel-blacklist: []
|
|
||||||
|
|
||||||
# If you have ffmpeg installed, you can query metadata from raw files, allowing
|
# If you have ffmpeg installed, you can query metadata from raw files, allowing
|
||||||
# server-synched raw file playback. This requires the following:
|
# server-synched raw file playback. This requires the following:
|
||||||
# * ffmpeg must be installed on the server
|
# * ffmpeg must be installed on the server
|
||||||
|
@ -231,16 +243,6 @@ setuid:
|
||||||
# how long to wait in ms before changing uid/gid
|
# how long to wait in ms before changing uid/gid
|
||||||
timeout: 15
|
timeout: 15
|
||||||
|
|
||||||
# Determines channel data storage mechanism.
|
|
||||||
# Defaults to 'file', in which channel data is JSON stringified and saved to a file
|
|
||||||
# in the `chandump/` folder. This is the legacy behavior of CyTube.
|
|
||||||
# The other possible option is 'database', in which case each key-value pair of
|
|
||||||
# channel data is stored as a row in the `channel_data` database table.
|
|
||||||
# To migrate legacy chandump files to the database, shut down CyTube (to prevent
|
|
||||||
# concurrent updates), then run `node lib/channel-storage/migrate.js`.
|
|
||||||
channel-storage:
|
|
||||||
type: 'file'
|
|
||||||
|
|
||||||
# Allows for external services to access the system commandline
|
# Allows for external services to access the system commandline
|
||||||
# Useful for setups where stdin isn't available such as when using PM2
|
# Useful for setups where stdin isn't available such as when using PM2
|
||||||
service-socket:
|
service-socket:
|
||||||
|
|
|
@ -21,4 +21,4 @@ example, for cytu.be I use:
|
||||||
npm run generate-userscript CyTube http://cytu.be/r/* https://cytu.be/r/*
|
npm run generate-userscript CyTube http://cytu.be/r/* https://cytu.be/r/*
|
||||||
```
|
```
|
||||||
|
|
||||||
This will generate `www/js/cytube-google-drive.user.js`.
|
This will generate `www/js/cytube-google-drive.user.js`. If you've changed the channel path, be sure to take that into account.
|
||||||
|
|
|
@ -61,6 +61,7 @@ function initPasswordResetCleanup(Server) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initChannelDumper(Server) {
|
function initChannelDumper(Server) {
|
||||||
|
const chanPath = Config.get('channel-path');
|
||||||
var CHANNEL_SAVE_INTERVAL = parseInt(Config.get("channel-save-interval"))
|
var CHANNEL_SAVE_INTERVAL = parseInt(Config.get("channel-save-interval"))
|
||||||
* 60000;
|
* 60000;
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
|
@ -70,9 +71,9 @@ function initChannelDumper(Server) {
|
||||||
return Promise.delay(wait).then(() => {
|
return Promise.delay(wait).then(() => {
|
||||||
if (!chan.dead && chan.users && chan.users.length > 0) {
|
if (!chan.dead && chan.users && chan.users.length > 0) {
|
||||||
return chan.saveState().tap(() => {
|
return chan.saveState().tap(() => {
|
||||||
LOGGER.info(`Saved /r/${chan.name}`);
|
LOGGER.info(`Saved /${chanPath}/${chan.name}`);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
LOGGER.error(`Failed to save /r/${chan.name}: ${err.stack}`);
|
LOGGER.error(`Failed to save /${chanPath}/${chan.name}: ${err.stack}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
|
@ -114,6 +114,8 @@ function fixOldChandump(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function migrate(src, dest, opts) {
|
function migrate(src, dest, opts) {
|
||||||
|
const chanPath = Config.get('channel-path');
|
||||||
|
|
||||||
return src.listChannels().then(names => {
|
return src.listChannels().then(names => {
|
||||||
return Promise.reduce(names, (_, name) => {
|
return Promise.reduce(names, (_, name) => {
|
||||||
// A long time ago there was a bug where CyTube would save a different
|
// A long time ago there was a bug where CyTube would save a different
|
||||||
|
@ -143,11 +145,11 @@ function migrate(src, dest, opts) {
|
||||||
});
|
});
|
||||||
return dest.save(name, data);
|
return dest.save(name, data);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
console.log(`Migrated /r/${name}`);
|
console.log(`Migrated /${chanPath}/${name}`);
|
||||||
}).catch(ChannelNotFoundError, err => {
|
}).catch(ChannelNotFoundError, err => {
|
||||||
console.log(`Skipping /r/${name} (not present in the database)`);
|
console.log(`Skipping /${chanPath}/${name} (not present in the database)`);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error(`Failed to migrate /r/${name}: ${err.stack}`);
|
console.error(`Failed to migrate /${chanPath}/${name}: ${err.stack}`);
|
||||||
});
|
});
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
|
@ -70,7 +70,12 @@ var defaults = {
|
||||||
"from-name": "CyTube Services"
|
"from-name": "CyTube Services"
|
||||||
},
|
},
|
||||||
"youtube-v3-key": "",
|
"youtube-v3-key": "",
|
||||||
|
"channel-blacklist": [],
|
||||||
|
"channel-path": "r",
|
||||||
"channel-save-interval": 5,
|
"channel-save-interval": 5,
|
||||||
|
"channel-storage": {
|
||||||
|
type: "file"
|
||||||
|
},
|
||||||
"max-channels-per-user": 5,
|
"max-channels-per-user": 5,
|
||||||
"max-accounts-per-ip": 5,
|
"max-accounts-per-ip": 5,
|
||||||
"guest-login-delay": 60,
|
"guest-login-delay": 60,
|
||||||
|
@ -102,7 +107,6 @@ var defaults = {
|
||||||
"max-items": 4000,
|
"max-items": 4000,
|
||||||
"update-interval": 5
|
"update-interval": 5
|
||||||
},
|
},
|
||||||
"channel-blacklist": [],
|
|
||||||
ffmpeg: {
|
ffmpeg: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
"ffprobe-exec": "ffprobe"
|
"ffprobe-exec": "ffprobe"
|
||||||
|
@ -114,9 +118,6 @@ var defaults = {
|
||||||
"user": "nobody",
|
"user": "nobody",
|
||||||
"timeout": 15
|
"timeout": 15
|
||||||
},
|
},
|
||||||
"channel-storage": {
|
|
||||||
type: "file"
|
|
||||||
},
|
|
||||||
"service-socket": {
|
"service-socket": {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
socket: "service.sock"
|
socket: "service.sock"
|
||||||
|
@ -390,6 +391,12 @@ function preprocessConfig(cfg) {
|
||||||
});
|
});
|
||||||
cfg["channel-blacklist"] = tbl;
|
cfg["channel-blacklist"] = tbl;
|
||||||
|
|
||||||
|
/* Check channel path */
|
||||||
|
if(!/^[-\w]+$/.test(cfg["channel-blacklist"])){
|
||||||
|
LOGGER.error("Channel paths may only use the same characters as usernames and channel names.");
|
||||||
|
process.exit(78); // sysexits.h for bad config
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg["link-domain-blacklist"].length > 0) {
|
if (cfg["link-domain-blacklist"].length > 0) {
|
||||||
cfg["link-domain-blacklist-regex"] = new RegExp(
|
cfg["link-domain-blacklist-regex"] = new RegExp(
|
||||||
cfg["link-domain-blacklist"].join("|").replace(/\./g, "\\."), "gi");
|
cfg["link-domain-blacklist"].join("|").replace(/\./g, "\\."), "gi");
|
||||||
|
|
|
@ -62,6 +62,7 @@ var Server = function () {
|
||||||
self.announcement = null;
|
self.announcement = null;
|
||||||
self.infogetter = null;
|
self.infogetter = null;
|
||||||
self.servers = {};
|
self.servers = {};
|
||||||
|
self.chanPath = Config.get('channel-path');
|
||||||
|
|
||||||
// backend init
|
// backend init
|
||||||
var initModule;
|
var initModule;
|
||||||
|
@ -264,7 +265,7 @@ Server.prototype.unloadChannel = function (chan, options) {
|
||||||
|
|
||||||
if (!options.skipSave) {
|
if (!options.skipSave) {
|
||||||
chan.saveState().catch(error => {
|
chan.saveState().catch(error => {
|
||||||
LOGGER.error(`Failed to save /r/${chan.name} for unload: ${error.stack}`);
|
LOGGER.error(`Failed to save /${this.chanPath}/${chan.name} for unload: ${error.stack}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,9 +355,9 @@ Server.prototype.shutdown = function () {
|
||||||
Promise.map(this.channels, channel => {
|
Promise.map(this.channels, channel => {
|
||||||
try {
|
try {
|
||||||
return channel.saveState().tap(() => {
|
return channel.saveState().tap(() => {
|
||||||
LOGGER.info(`Saved /r/${channel.name}`);
|
LOGGER.info(`Saved /${this.chanPath}/${channel.name}`);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
LOGGER.error(`Failed to save /r/${channel.name}: ${err.stack}`);
|
LOGGER.error(`Failed to save /${this.chanPath}/${channel.name}: ${err.stack}`);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LOGGER.error(`Failed to save channel: ${error.stack}`);
|
LOGGER.error(`Failed to save channel: ${error.stack}`);
|
||||||
|
@ -391,7 +392,7 @@ Server.prototype.handlePartitionMapChange = function () {
|
||||||
});
|
});
|
||||||
this.unloadChannel(channel, { skipSave: true });
|
this.unloadChannel(channel, { skipSave: true });
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
LOGGER.error(`Failed to unload /r/${channel.name} for ` +
|
LOGGER.error(`Failed to unload /${this.chanPath}/${channel.name} for ` +
|
||||||
`partition map flip: ${error.stack}`);
|
`partition map flip: ${error.stack}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ function merge(locals, res) {
|
||||||
loginDomain: Config.get("https.enabled") ? Config.get("https.full-address")
|
loginDomain: Config.get("https.enabled") ? Config.get("https.full-address")
|
||||||
: Config.get("http.full-address"),
|
: Config.get("http.full-address"),
|
||||||
csrfToken: typeof res.req.csrfToken === 'function' ? res.req.csrfToken() : '',
|
csrfToken: typeof res.req.csrfToken === 'function' ? res.req.csrfToken() : '',
|
||||||
baseUrl: getBaseUrl(res)
|
baseUrl: getBaseUrl(res),
|
||||||
|
channelPath: Config.get("channel-path"),
|
||||||
};
|
};
|
||||||
if (typeof locals !== "object") {
|
if (typeof locals !== "object") {
|
||||||
return _locals;
|
return _locals;
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { sendPug } from '../pug';
|
||||||
import * as HTTPStatus from '../httpstatus';
|
import * as HTTPStatus from '../httpstatus';
|
||||||
import { HTTPError } from '../../errors';
|
import { HTTPError } from '../../errors';
|
||||||
|
|
||||||
export default function initialize(app, ioConfig) {
|
export default function initialize(app, ioConfig, chanPath) {
|
||||||
app.get('/r/:channel', (req, res) => {
|
app.get(`/${chanPath}/:channel`, (req, res) => {
|
||||||
if (!req.params.channel || !CyTubeUtil.isValidChannelName(req.params.channel)) {
|
if (!req.params.channel || !CyTubeUtil.isValidChannelName(req.params.channel)) {
|
||||||
throw new HTTPError(`"${sanitizeText(req.params.channel)}" is not a valid ` +
|
throw new HTTPError(`"${sanitizeText(req.params.channel)}" is not a valid ` +
|
||||||
'channel name.', { status: HTTPStatus.NOT_FOUND });
|
'channel name.', { status: HTTPStatus.NOT_FOUND });
|
||||||
|
|
|
@ -132,6 +132,8 @@ module.exports = {
|
||||||
* Initializes webserver callbacks
|
* Initializes webserver callbacks
|
||||||
*/
|
*/
|
||||||
init: function (app, webConfig, ioConfig, clusterClient, channelIndex, session) {
|
init: function (app, webConfig, ioConfig, clusterClient, channelIndex, session) {
|
||||||
|
const chanPath = Config.get('channel-path');
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
counters.add("http:request", 1);
|
counters.add("http:request", 1);
|
||||||
next();
|
next();
|
||||||
|
@ -147,7 +149,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
app.use(cookieParser(webConfig.getCookieSecret()));
|
app.use(cookieParser(webConfig.getCookieSecret()));
|
||||||
app.use(csrf.init(webConfig.getCookieDomain()));
|
app.use(csrf.init(webConfig.getCookieDomain()));
|
||||||
app.use('/r/:channel', require('./middleware/ipsessioncookie').ipSessionCookieMiddleware);
|
app.use(`/${chanPath}/:channel`, require('./middleware/ipsessioncookie').ipSessionCookieMiddleware);
|
||||||
initializeLog(app);
|
initializeLog(app);
|
||||||
require('./middleware/authorize')(app, session);
|
require('./middleware/authorize')(app, session);
|
||||||
|
|
||||||
|
@ -176,7 +178,7 @@ module.exports = {
|
||||||
LOGGER.info('Enabled express-minify for CSS and JS');
|
LOGGER.info('Enabled express-minify for CSS and JS');
|
||||||
}
|
}
|
||||||
|
|
||||||
require('./routes/channel')(app, ioConfig);
|
require('./routes/channel')(app, ioConfig, chanPath);
|
||||||
require('./routes/index')(app, channelIndex, webConfig.getMaxIndexEntries());
|
require('./routes/index')(app, channelIndex, webConfig.getMaxIndexEntries());
|
||||||
app.get('/sioconfig(.json)?', handleLegacySocketConfig);
|
app.get('/sioconfig(.json)?', handleLegacySocketConfig);
|
||||||
require('./routes/socketconfig')(app, clusterClient);
|
require('./routes/socketconfig')(app, clusterClient);
|
||||||
|
|
|
@ -44,7 +44,7 @@ html(lang="en")
|
||||||
input(type="hidden", name="name", value=c.name)
|
input(type="hidden", name="name", value=c.name)
|
||||||
button.btn.btn-xs.btn-danger(type="submit") Delete
|
button.btn.btn-xs.btn-danger(type="submit") Delete
|
||||||
span.glyphicon.glyphicon-trash
|
span.glyphicon.glyphicon-trash
|
||||||
a(href="/r/"+c.name, style="margin-left: 5px")= c.name
|
a(href=`/${channelPath}/${c.name}`, style="margin-left: 5px")= c.name
|
||||||
.col-lg-6.col-md-6
|
.col-lg-6.col-md-6
|
||||||
h3 Register a new channel
|
h3 Register a new channel
|
||||||
if newChannelError
|
if newChannelError
|
||||||
|
@ -57,7 +57,7 @@ html(lang="en")
|
||||||
.form-group
|
.form-group
|
||||||
label.control-label(for="channelname") Channel URL
|
label.control-label(for="channelname") Channel URL
|
||||||
.input-group
|
.input-group
|
||||||
span.input-group-addon #{baseUrl}/r/
|
span.input-group-addon #{baseUrl}/#{channelPath}/
|
||||||
input#channelname.form-control(type="text", name="name", maxlength="30", onkeyup="checkChannel()")
|
input#channelname.form-control(type="text", name="name", maxlength="30", onkeyup="checkChannel()")
|
||||||
p#validate_channel.text-danger.pull-right
|
p#validate_channel.text-danger.pull-right
|
||||||
button#register.btn.btn-primary.btn-block(type="submit") Register
|
button#register.btn.btn-primary.btn-block(type="submit") Register
|
||||||
|
|
|
@ -11,7 +11,7 @@ html(lang="en")
|
||||||
include nav
|
include nav
|
||||||
+navheader()
|
+navheader()
|
||||||
#nav-collapsible.collapse.navbar-collapse
|
#nav-collapsible.collapse.navbar-collapse
|
||||||
- var cname = "/r/" + channelName
|
- var cname = `/${channelPath}/${channelName}`
|
||||||
ul.nav.navbar-nav
|
ul.nav.navbar-nav
|
||||||
+navdefaultlinks(cname)
|
+navdefaultlinks(cname)
|
||||||
li: a(href="javascript:void(0)", onclick="javascript:showUserOptions()") Options
|
li: a(href="javascript:void(0)", onclick="javascript:showUserOptions()") Options
|
||||||
|
|
|
@ -86,7 +86,7 @@ mixin adminoptions
|
||||||
#cs-adminoptions.tab-pane
|
#cs-adminoptions.tab-pane
|
||||||
h4 Admin-Only Settings
|
h4 Admin-Only Settings
|
||||||
form.form-horizontal(action="javascript:void(0)")
|
form.form-horizontal(action="javascript:void(0)")
|
||||||
- var defname = "CyTube - /r/" + channelName
|
- var defname = `CyTube - /${channelPath}/${channelName}`
|
||||||
+textbox-auto("cs-pagetitle", "Page title", defname)
|
+textbox-auto("cs-pagetitle", "Page title", defname)
|
||||||
+textbox-auto("cs-password", "Password", "leave blank to disable")
|
+textbox-auto("cs-password", "Password", "leave blank to disable")
|
||||||
+textbox-auto("cs-externalcss", "External CSS", "Stylesheet URL")
|
+textbox-auto("cs-externalcss", "External CSS", "Stylesheet URL")
|
||||||
|
|
|
@ -11,8 +11,16 @@ mixin head()
|
||||||
link(href="/css/cytube.css", rel="stylesheet")
|
link(href="/css/cytube.css", rel="stylesheet")
|
||||||
link(id="usertheme", href=DEFAULT_THEME, rel="stylesheet")
|
link(id="usertheme", href=DEFAULT_THEME, rel="stylesheet")
|
||||||
|
|
||||||
script(type="text/javascript").
|
if channelName
|
||||||
var DEFAULT_THEME = '#{DEFAULT_THEME}';
|
script(type="text/javascript").
|
||||||
|
var DEFAULT_THEME = '#{DEFAULT_THEME}';
|
||||||
|
var CHANNELPATH = '#{channelPath}';
|
||||||
|
var CHANNELNAME = '#{channelName}';
|
||||||
|
else
|
||||||
|
script(type="text/javascript").
|
||||||
|
var DEFAULT_THEME = '#{DEFAULT_THEME}';
|
||||||
|
var CHANNELPATH = '#{channelPath}';
|
||||||
|
|
||||||
script(src="/js/theme.js")
|
script(src="/js/theme.js")
|
||||||
//[if lt IE 9]
|
//[if lt IE 9]
|
||||||
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
||||||
|
|
|
@ -25,7 +25,7 @@ html(lang="en")
|
||||||
tbody
|
tbody
|
||||||
each chan in channels
|
each chan in channels
|
||||||
tr
|
tr
|
||||||
td: a(href="/r/"+chan.name) #{chan.pagetitle} (#{chan.name})
|
td: a(href=`/${channelPath}/${chan.name}`) #{chan.pagetitle} (#{chan.name})
|
||||||
td= chan.usercount
|
td= chan.usercount
|
||||||
td= chan.mediatitle
|
td= chan.mediatitle
|
||||||
.col-lg-3.col-md-3
|
.col-lg-3.col-md-3
|
||||||
|
@ -37,6 +37,6 @@ html(lang="en")
|
||||||
script(type="text/javascript").
|
script(type="text/javascript").
|
||||||
$("#channelname").keydown(function (ev) {
|
$("#channelname").keydown(function (ev) {
|
||||||
if (ev.keyCode === 13) {
|
if (ev.keyCode === 13) {
|
||||||
location.href = "/r/" + $("#channelname").val();
|
location.href = "/#{channelPath}/" + $("#channelname").val();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -453,8 +453,8 @@ console.log(channels[0]);
|
||||||
channels.forEach(function (c) {
|
channels.forEach(function (c) {
|
||||||
var tr = $("<tr/>").appendTo(tbl);
|
var tr = $("<tr/>").appendTo(tbl);
|
||||||
var name = $("<td/>").appendTo(tr);
|
var name = $("<td/>").appendTo(tr);
|
||||||
$("<a/>").attr("href", "/r/" + c.name)
|
$("<a/>").attr("href", `/${CHANNELPATH}/${c.name}`)
|
||||||
.text(c.pagetitle + " (/r/" + c.name + ")")
|
.text(c.pagetitle + ` (/${CHANNELPATH}/${c.name})`)
|
||||||
.appendTo(name);
|
.appendTo(name);
|
||||||
var usercount = $("<td/>").text(c.usercount).appendTo(tr);
|
var usercount = $("<td/>").text(c.usercount).appendTo(tr);
|
||||||
count += c.usercount;
|
count += c.usercount;
|
||||||
|
@ -475,7 +475,7 @@ console.log(channels[0]);
|
||||||
.attr("title", "Unload")
|
.attr("title", "Unload")
|
||||||
.appendTo(controlInner)
|
.appendTo(controlInner)
|
||||||
.click(function () {
|
.click(function () {
|
||||||
if (confirm("Are you sure you want to unload /r/" + c.name + "?")) {
|
if (confirm(`Are you sure you want to unload /${CHANNELPATH}/${c.name}?`)) {
|
||||||
socket.emit("acp-force-unload", {
|
socket.emit("acp-force-unload", {
|
||||||
name: c.name
|
name: c.name
|
||||||
});
|
});
|
||||||
|
|
|
@ -425,23 +425,6 @@ Callbacks = {
|
||||||
|
|
||||||
if (!CLIENT.guest) {
|
if (!CLIENT.guest) {
|
||||||
socket.emit("initUserPLCallbacks");
|
socket.emit("initUserPLCallbacks");
|
||||||
if ($("#loginform").length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var logoutform = $("<p/>").attr("id", "logoutform")
|
|
||||||
.addClass("navbar-text pull-right")
|
|
||||||
.insertAfter($("#loginform"));
|
|
||||||
|
|
||||||
$("<span/>").attr("id", "welcome").text("Welcome, " + CLIENT.name)
|
|
||||||
.appendTo(logoutform);
|
|
||||||
$("<span/>").html(" · ").appendTo(logoutform);
|
|
||||||
var domain = $("#loginform").attr("action").replace("/login", "");
|
|
||||||
$("<a/>").attr("id", "logout")
|
|
||||||
.attr("href", domain + "/logout?redirect=/r/" + CHANNEL.name)
|
|
||||||
.text("Logout")
|
|
||||||
.appendTo(logoutform);
|
|
||||||
|
|
||||||
$("#loginform").remove();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,7 +19,7 @@ var CHANNEL = {
|
||||||
css: "",
|
css: "",
|
||||||
js: "",
|
js: "",
|
||||||
motd: "",
|
motd: "",
|
||||||
name: false,
|
name: CHANNELNAME,
|
||||||
usercount: 0,
|
usercount: 0,
|
||||||
emotes: []
|
emotes: []
|
||||||
};
|
};
|
||||||
|
|
11
www/js/ui.js
11
www/js/ui.js
|
@ -615,17 +615,6 @@ $("#shuffleplaylist").click(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* load channel */
|
|
||||||
|
|
||||||
var loc = document.location+"";
|
|
||||||
var m = loc.match(/\/r\/([a-zA-Z0-9-_]+)/);
|
|
||||||
if(m) {
|
|
||||||
CHANNEL.name = m[1];
|
|
||||||
if (CHANNEL.name.indexOf("#") !== -1) {
|
|
||||||
CHANNEL.name = CHANNEL.name.substring(0, CHANNEL.name.indexOf("#"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* channel ranks stuff */
|
/* channel ranks stuff */
|
||||||
function chanrankSubmit(rank) {
|
function chanrankSubmit(rank) {
|
||||||
var name = $("#cs-chanranks-name").val();
|
var name = $("#cs-chanranks-name").val();
|
||||||
|
|
Loading…
Reference in a new issue