diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..a1e3ce9
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+root = true
+
+[*.js]
+indent_style = tab
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*]
+insert_final_newline = true
+
+[{package.json,*.yml}]
+indent_style = space
+indent_size = 2
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
index 05d8046..624ec21 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,18 +1,21 @@
{
- "extends": "airbnb",
- "rules": {
- "comma-dangle": 0,
- "max-len": 0,
- "no-console": 0,
- "no-param-reassign": 0,
- "no-shadow": 0,
- "consistent-return": 0,
- "func-names": 0,
- "indent": ["error", 4]
- },
- "env": {
- "browser": true,
- "node": true,
- "jquery": true
- }
+ "extends": "airbnb",
+ "rules": {
+ "comma-dangle": 0,
+ "max-len": 0,
+ "no-console": 0,
+ "no-param-reassign": 0,
+ "no-shadow": 0,
+ "consistent-return": 0,
+ "func-names": 0,
+ "indent": ["error", "tab", { "SwitchCase": 1 }],
+ "strict": 0,
+ "guard-for-in": "warn",
+ "no-restricted-syntax": ["warn", "ForInStatement"]
+ },
+ "env": {
+ "browser": true,
+ "node": true,
+ "jquery": true
+ }
}
\ No newline at end of file
diff --git a/config.example.hjson b/config.example.hjson
index f75be08..0cd6562 100644
--- a/config.example.hjson
+++ b/config.example.hjson
@@ -1,469 +1,473 @@
{
- /*
- Set this flag to false to disable web server hosting or true to enable web server hosting.
- This is useful if you want to host static files in another web server such as nginx.
-
- If you are only hosting the socket and want musiqpad to host the frontend set this to false.
- */
- hostWebserver: true
- socketServer: {
- host: "" // Host name or IP that the socket server is located at. Leave blank to bind to process IP address
- port: 8082// Leave blank to bind to process PORT
- }
- webServer: {
- address: "" // Leave blank to bind to process IP address.
- port: 8080// Leave blank to bind to process PORT.
+ /*
+ Set this flag to false to disable web server hosting or true to enable web server hosting.
+ This is useful if you want to host static files in another web server such as nginx.
+
+ If you are only hosting the socket and want musiqpad to host the frontend set this to false.
+ */
+ hostWebserver: true
+ socketServer: {
+ host: "" // Host name or IP that the socket server is located at. Leave blank to bind to process IP address
+ port: 8082// Leave blank to bind to process PORT
+ }
+ webServer: {
+ address: "" // Leave blank to bind to process IP address.
+ port: 8080// Leave blank to bind to process PORT.
- redirectHTTP: false// Set to true if you want HTTP redirect to HTTPS.
- redirectPort: 80// Required if setting above is true. Set to the port you want to redirect HTTP to HTTPS from (Default: 80).
- }
- useSSL: false// If you want your pad to be accesible over HTTPS set SSL to true and add the path of your certificates
- certificate: {
- key: "path-to-key"
- cert: "path-to-cert"
- }
- room: {
- name: "Pad Name" // This is your pad name. It is shown as a user friendly description on the lounge and tab name.
- slug: "this-is-your-slug" // Slugs are used to identify your pad when connecting to musiqpad! This slug must be unique and all in lowecase.
- greet: "Welcome to musiqpad!"
- bg: "" // Background image file path. Accepts external images. If this is undefined the default background will be used.
- maxCon: 0
- ownerEmail: "user@domain.tld" // This needs to be set then the server restarted to take effect.
- guestCanSeeChat: true
- bannedCanSeeChat: false
- lastmsglimit: 6// How many messages a user can see after joining.
- signupcd: 0// How many miliseconds the user cannot do certain things after they sign up.
- allowemojis: true
- allowrecovery: false
- recaptcha: false
- queue: {
- cycle: true
- lock: false
- limit: 50
- }
- history: {
- limit_save: 0
- limit_send: 50
- }
- mail: {
- confirmation: false// Whether to force user to confirm his email address before he is able to do anything
- sender: "user@domain.tld" // Domain should point to this box when using direct mode
-
- // DIRECT PROBABLY WON'T WORK BECAUSE YOUR IP DOESN'T HAVE A GOOD REPUTATION!
-
- transport: "direct" // 'smtp', 'direct' or 'xoauth'
- options: {}
- /*
- EXAMPLES:
-
- -- SMTP --
- transport: "smtp"
- options: {
- service: "gmail"
- auth: {
- user: "mail@somewebsite.com",
- pass: "pass",
- }
- }
- ----------
-
- -- XOAUTH2 --
- transport: "xoauth"
- options: {
- service: "gmail"
- auth: {
- xoauth: {
- user: '{username}'
- clientId: '{Client ID}'
- clientSecret: '{Client Secret}'
- refreshToken: '{refresh-token}'
- accessToken: '{cached access token}
- }
- }
- }
- -------------
-
- -- DIRECT --
- transport: "direct"
- options: {}
- -------------
- */
- }
- description:
- '''
-
Pad Description
- Here you can put anything you want in HTML!
- '''
- tags: { // Tags for Google & co
- keywords: "musiqpad"
- description: ""
- image: "https://cdn.musiqpad.com/img/icon-256.png" // Image on twitter/facebook/slack/...
- twitter: "@musiqpad"
- description: // A one to two sentence description for search engines & co
- '''
-
- '''
- themeColor: "" // a hex color for the theme on chrome for android
- favicon: "/pads/lib/img/icon.png"
- }
- }
- apis: {
- YT: {
- key: "" // Required api key in order for YouTube search to work.
- restrictSearchToMusic: false
- }
- SC: {
- key: ""
- }
- reCaptcha: {
- key: ""
- secret: ""
- }
- musiqpad: {
- key: "" // This is required in order for your socket to update the musiqpad lounge. Request an API Key here: https://musiqpad.com/lounge
- sendLobbyStats: false
- }
- }
+ redirectHTTP: false// Set to true if you want HTTP redirect to HTTPS.
+ redirectPort: 80// Required if setting above is true. Set to the port you want to redirect HTTP to HTTPS from (Default: 80).
+ }
+ useSSL: false// If you want your pad to be accesible over HTTPS set SSL to true and add the path of your certificates
+ certificate: {
+ key: "path-to-key"
+ cert: "path-to-cert"
+ }
+ room: {
+ name: "Pad Name" // This is your pad name. It is shown as a user friendly description on the lounge and tab name.
+ slug: "this-is-your-slug" // Slugs are used to identify your pad when connecting to musiqpad! This slug must be unique and all in lowecase.
+ greet: "Welcome to musiqpad!"
+ bg: "" // Background image file path. Accepts external images. If this is undefined the default background will be used.
+ maxCon: 0
+ ownerEmail: "user@domain.tld" // This needs to be set then the server restarted to take effect.
+ guestCanSeeChat: true
+ bannedCanSeeChat: false
+ lastmsglimit: 6// How many messages a user can see after joining.
+ signupcd: 0// How many miliseconds the user cannot do certain things after they sign up.
+ allowemojis: true
+ allowrecovery: false
+ recaptcha: false
+ queue: {
+ cycle: true
+ lock: false
+ limit: 50
+ }
+ history: {
+ limit_save: 0
+ limit_send: 50
+ }
+ mail: {
+ confirmation: false// Whether to force user to confirm his email address before he is able to do anything
+ sender: "user@domain.tld" // Domain should point to this box when using direct mode
+
+ // DIRECT PROBABLY WON'T WORK BECAUSE YOUR IP DOESN'T HAVE A GOOD REPUTATION!
+
+ transport: "direct" // 'smtp', 'direct' or 'xoauth'
+ options: {}
+ /*
+ EXAMPLES:
+
+ -- SMTP --
+ transport: "smtp"
+ options: {
+ service: "gmail"
+ auth: {
+ user: "mail@somewebsite.com",
+ pass: "pass",
+ }
+ }
+ ----------
+
+ -- XOAUTH2 --
+ transport: "xoauth"
+ options: {
+ service: "gmail"
+ auth: {
+ xoauth: {
+ user: '{username}'
+ clientId: '{Client ID}'
+ clientSecret: '{Client Secret}'
+ refreshToken: '{refresh-token}'
+ accessToken: '{cached access token}
+ }
+ }
+ }
+ -------------
+
+ -- DIRECT --
+ transport: "direct"
+ options: {}
+ -------------
+ */
+ }
+ description:
+ '''
+
Pad Description
+ Here you can put anything you want in HTML!
+ '''
+ tags: { // Tags for Google & co
+ keywords: "musiqpad"
+ description: ""
+ image: "https://cdn.musiqpad.com/img/icon-256.png" // Image on twitter/facebook/slack/...
+ twitter: "@musiqpad"
+ description: // A one to two sentence description for search engines & co
+ '''
+
+ '''
+ themeColor: "" // a hex color for the theme on chrome for android
+ favicon: "/pads/lib/img/icon.png"
+ }
+ scripts: { // Only if you host the frontend yourself
+ js: [], // Example: ["https://exapmple.com/musiqpad.js", "lib/js/custom.js"]
+ css: []
+ }
+ }
+ apis: {
+ YT: {
+ key: "" // Required api key in order for YouTube search to work.
+ restrictSearchToMusic: false
+ }
+ SC: {
+ key: ""
+ }
+ reCaptcha: {
+ key: ""
+ secret: ""
+ }
+ musiqpad: {
+ key: "" // This is required in order for your socket to update the musiqpad lounge. Request an API Key here: https://musiqpad.com/lounge
+ sendLobbyStats: false
+ }
+ }
- // The amount of time users stay logged in for before having to login again in days.
- // 0 = login every time
- loginExpire: 7
- db: {
- dbType: "level" // Values "level" for LevelDB, "mysql" for MySQL and "mongo" for MongoDB
- dbDir: "./socketserver/db" // Only used for LevelDB. Directory to save databases. Default is ./socketserver/db
- mysqlUser: "" // Only used for MySQL. Database username
- mysqlPassword: "" // Only used for MySQL. Database password
- mysqlHost: "" // Only used for MySQL. Host address
- mysqlDatabase: "" // Only used for MySQL. Database being used
- mongoUser: "" // Only used for MongoDB. Database username
- mongoPassword: "" // Only used for MongoDB. Database password
- mongoHost: "" // Only used for MongoDB. Host address
- mongoDatabase: "" // Only used for MongoDB. Database being used
- }
-
- /*
- "djqueue.join": Ability to join queue
- "djqueue.joinlocked": Ability to join locked queue
- "djqueue.leave": Ability to leave queue
- "djqueue.skip.self": Ability to skip self
- "djqueue.skip.other": Ability to skip others
- "djqueue.lock": Ability to lock/unlock queue
- "djqueue.limit": Ability to change waitlist limit
- "djqueue.cycle": Ability to enable/disable queue cycle
- "djqueue.move": Ability to move, swap, add and remove people in the queue
- "djqueue.playLiveVideos": Ability to play live videos with undefined duration
- "djqueue.lock.bypass": Bypass locked queue
- "djqueue.limit.bypass": Bypass queue limit
- "chat.send": Abilty to send chat messages
- "chat.delete": Ability to delete others" chat messages
- "chat.specialMention": Ability to use @everyone, @guest and @djs as mention
- "chat.broadcast": Ability to send a highlighted broadcast message
- "chat.private": Ability to send PMs
- "chat.staff": Ability to send and receive special staff chat
- "playlist.create": Ability to create playlists
- "playlist.delete": Ability to delete playlists
- "playlist.rename": Ability to rename playlists
- "playlist.import": Ability to import playlists
- "playlist.shuffle": Ability to shuffle playlists
- "room.grantroles": Ability to change user roles (requires canGrantPerms property)
- "room.restrict.ban": Ability to ban and unban users
- "room.restrict.mute": Ability to mute and unmute users
- "room.restrict.mute_silent": Ability to shadow mute and unmute users
- "room.ratelimit.bypass": Will bypass ratelimit
- "room.whois": Possibility to request additional information about a user
- "room.whois.iphistory": Possibility to request all IP addresses that the user logged from since account creation
+ // The amount of time users stay logged in for before having to login again in days.
+ // 0 = login every time
+ loginExpire: 7
+ db: {
+ dbType: "level" // Values "level" for LevelDB, "mysql" for MySQL and "mongo" for MongoDB
+ dbDir: "./socketserver/db" // Only used for LevelDB. Directory to save databases. Default is ./socketserver/db
+ mysqlUser: "" // Only used for MySQL. Database username
+ mysqlPassword: "" // Only used for MySQL. Database password
+ mysqlHost: "" // Only used for MySQL. Host address
+ mysqlDatabase: "" // Only used for MySQL. Database being used
+ mongoUser: "" // Only used for MongoDB. Database username
+ mongoPassword: "" // Only used for MongoDB. Database password
+ mongoHost: "" // Only used for MongoDB. Host address
+ mongoDatabase: "" // Only used for MongoDB. Database being used
+ }
+
+ /*
+ "djqueue.join": Ability to join queue
+ "djqueue.joinlocked": Ability to join locked queue
+ "djqueue.leave": Ability to leave queue
+ "djqueue.skip.self": Ability to skip self
+ "djqueue.skip.other": Ability to skip others
+ "djqueue.lock": Ability to lock/unlock queue
+ "djqueue.limit": Ability to change waitlist limit
+ "djqueue.cycle": Ability to enable/disable queue cycle
+ "djqueue.move": Ability to move, swap, add and remove people in the queue
+ "djqueue.playLiveVideos": Ability to play live videos with undefined duration
+ "djqueue.lock.bypass": Bypass locked queue
+ "djqueue.limit.bypass": Bypass queue limit
+ "chat.send": Abilty to send chat messages
+ "chat.delete": Ability to delete others" chat messages
+ "chat.specialMention": Ability to use @everyone, @guest and @djs as mention
+ "chat.broadcast": Ability to send a highlighted broadcast message
+ "chat.private": Ability to send PMs
+ "chat.staff": Ability to send and receive special staff chat
+ "playlist.create": Ability to create playlists
+ "playlist.delete": Ability to delete playlists
+ "playlist.rename": Ability to rename playlists
+ "playlist.import": Ability to import playlists
+ "playlist.shuffle": Ability to shuffle playlists
+ "room.grantroles": Ability to change user roles (requires canGrantPerms property)
+ "room.restrict.ban": Ability to ban and unban users
+ "room.restrict.mute": Ability to mute and unmute users
+ "room.restrict.mute_silent": Ability to shadow mute and unmute users
+ "room.ratelimit.bypass": Will bypass ratelimit
+ "room.whois": Possibility to request additional information about a user
+ "room.whois.iphistory": Possibility to request all IP addresses that the user logged from since account creation
- NOTE: Changing the PROPERTY NAME will break role assignments. Title can be changed
- without breaking things, but property name must stay the same.
- */
+ NOTE: Changing the PROPERTY NAME will break role assignments. Title can be changed
+ without breaking things, but property name must stay the same.
+ */
-
- // Defines the order that roles will appear on the user list
- // PROPERTY names. NOT title. (case-sensitive)
- roleOrder: [
- "dev"
- "owner"
- "coowner"
- "supervisor"
- "bot"
- "regular"
- "default"
- ]
-
- // Defines which roles are "staff" members
- // PROPERTY names. NOT title. (case-sensitive)
- staffRoles: [
- "dev"
- "owner"
- "coowner"
- "supervisor"
- "bot"
- ]
-
+
+ // Defines the order that roles will appear on the user list
+ // PROPERTY names. NOT title. (case-sensitive)
+ roleOrder: [
+ "dev"
+ "owner"
+ "coowner"
+ "supervisor"
+ "bot"
+ "regular"
+ "default"
+ ]
+
+ // Defines which roles are "staff" members
+ // PROPERTY names. NOT title. (case-sensitive)
+ staffRoles: [
+ "dev"
+ "owner"
+ "coowner"
+ "supervisor"
+ "bot"
+ ]
+
- /*
+ /*
- Role Options:
+ Role Options:
- rolename:{
- title: "", // This is the title that gets displayed on the frontend.
- showtitle: true/false, // This is whether or not to display the title on the frontend.
- badge: "", // This can be any icon from the mdi package. A list of the icons is available here: https://materialdesignicons.com
- style: {}, // This can be used to set specific styles to the Username of a user with this role.
- permissions: [], // A list of permissions a user with this role is allowed to use.
- canGrantRoles: [], // A list of the roles that a user with this role can grant. I.e. an owner should be able to grant manager.
- mention: "" // A custom mention. I.e. "owner" would mention this group when someone typed @owner.
- }
+ rolename:{
+ title: "", // This is the title that gets displayed on the frontend.
+ showtitle: true/false, // This is whether or not to display the title on the frontend.
+ badge: "", // This can be any icon from the mdi package. A list of the icons is available here: https://materialdesignicons.com
+ style: {}, // This can be used to set specific styles to the Username of a user with this role.
+ permissions: [], // A list of permissions a user with this role is allowed to use.
+ canGrantRoles: [], // A list of the roles that a user with this role can grant. I.e. an owner should be able to grant manager.
+ mention: "" // A custom mention. I.e. "owner" would mention this group when someone typed @owner.
+ }
- Below are a list of roles we suggest using.
+ Below are a list of roles we suggest using.
- */
+ */
- // Defines roles and permissions
- roles: {
- owner: { // REQUIRED ROLE
- title: "Owner"
- showtitle: true
- style: {
- color: "#F46B40"
- }
- permissions: [
- "djqueue.join"
- "djqueue.joinlocked"
- "djqueue.leave"
- "djqueue.skip.self"
- "djqueue.skip.other"
- "djqueue.lock"
- "djqueue.cycle"
- "djqueue.limit"
- "djqueue.move"
- "djqueue.playLiveVideos"
- "djqueue.limit.bypass"
- "djqueue.lock.bypass"
- "chat.send"
- "chat.private"
- "chat.broadcast"
- "chat.delete"
- "chat.specialMention"
- "chat.staff"
- "playlist.create"
- "playlist.delete"
- "playlist.rename"
- "playlist.import"
- "playlist.shuffle"
- "room.grantroles"
- "room.restrict.ban"
- "room.restrict.mute"
- "room.restrict.mute_silent"
- "room.ratelimit.bypass"
- "room.whois"
- "room.whois.iphistory"
- "server.checkForUpdates"
- ]
- canGrantRoles: [
- "dev"
- "coowner"
- "supervisor"
- "bot"
- "regular"
- "default"
- ]
- }
- dev: { // OPTIONAL ROLE FOR MUSIQPAD DEVS
- title: "Dev"
- showtitle: true
- style: {
- color: "#A77DC2"
- }
- permissions: [
- "djqueue.join"
- "djqueue.joinlocked"
- "djqueue.leave"
- "djqueue.skip.self"
- "djqueue.skip.other"
- "djqueue.lock"
- "djqueue.cycle"
- "djqueue.limit"
- "djqueue.move"
- "djqueue.playLiveVideos"
- "djqueue.limit.bypass"
- "djqueue.lock.bypass"
- "chat.send"
- "chat.private"
- "chat.broadcast"
- "chat.delete"
- "chat.specialMention"
- "chat.staff"
- "playlist.create"
- "playlist.delete"
- "playlist.rename"
- "playlist.import"
- "playlist.shuffle"
- "room.grantroles"
- "room.restrict.ban"
- "room.restrict.mute"
- "room.restrict.mute_silent"
- "room.ratelimit.bypass"
- "room.whois"
- ]
- canGrantRoles: [
- "dev"
- "coowner"
- "supervisor"
- "bot"
- "regular"
- "default"
- ]
- mention: "devs"
- }
- coowner: {
- title: "Co-owner"
- showtitle: true
- style: {
- color: "#89BE6C"
- }
- permissions: [
- "djqueue.join"
- "djqueue.joinlocked"
- "djqueue.leave"
- "djqueue.skip.self"
- "djqueue.skip.other"
- "djqueue.lock"
- "djqueue.cycle"
- "djqueue.limit"
- "djqueue.move"
- "djqueue.playLiveVideos"
- "djqueue.limit.bypass"
- "djqueue.lock.bypass"
- "chat.send"
- "chat.private"
- "chat.delete"
- "chat.specialMention"
- "chat.broadcast"
- "chat.staff"
- "playlist.create"
- "playlist.delete"
- "playlist.rename"
- "playlist.import"
- "playlist.shuffle"
- "room.grantroles"
- "room.restrict.ban"
- "room.restrict.mute"
- "room.restrict.mute_silent"
- "room.ratelimit.bypass"
- "room.whois"
- "room.whois.iphistory"
- ]
- canGrantRoles: [
- "supervisor"
- "bot"
- "regular"
- "default"
- ]
- }
- supervisor: {
- title: "Supervisor"
- showtitle: true
- style: {
- color: "#009CDD"
- }
- permissions: [
- "djqueue.join"
- "djqueue.joinlocked"
- "djqueue.leave"
- "djqueue.skip.self"
- "djqueue.skip.other"
- "djqueue.lock"
- "djqueue.cycle"
- "djqueue.move"
- "djqueue.playLiveVideos"
- "djqueue.limit.bypass"
- "djqueue.lock.bypass"
- "chat.send"
- "chat.private"
- "chat.delete"
- "chat.specialMention"
- "chat.staff"
- "playlist.create"
- "playlist.delete"
- "playlist.rename"
- "playlist.import"
- "playlist.shuffle"
- "room.grantroles"
- "room.restrict.ban"
- "room.restrict.mute"
- "room.restrict.mute_silent"
- "room.ratelimit.bypass"
- "room.whois"
- ]
- canGrantRoles: [
- "regular"
- "default"
- ]
- }
- bot: {
- title: "Bot"
- showtitle: true
- badge: "android"
- style: {
- color: "#964B74"
- }
- permissions: [
- "djqueue.skip.other"
- "djqueue.lock"
- "djqueue.cycle"
- "djqueue.move"
- "chat.send"
- "chat.delete"
- "chat.specialMention"
- "room.restrict.ban"
- "room.restrict.mute"
- "room.restrict.mute_silent"
- "room.ratelimit.bypass"
- ]
- canGrantRoles: [
- ]
- }
- regular: {
- title: "Regular"
- showtitle: false
- style: {
- color: "#925AFF"
- }
- permissions: [
- "djqueue.join"
- "djqueue.joinlocked"
- "djqueue.leave"
- "chat.send"
- "chat.private"
- "djqueue.skip.self"
- "playlist.create"
- "playlist.delete"
- "playlist.rename"
- "playlist.import"
- ]
- canGrantRoles: [
- ]
- }
- default: { // REQUIRED ROLE
- title: "Default"
- showtitle: false
- style: {
- color: "#ffffff"
- }
- permissions: [
- "djqueue.join"
- "djqueue.leave"
- "chat.send"
- "chat.private"
- "djqueue.skip.self"
- "playlist.create"
- "playlist.delete"
- "playlist.rename"
- "playlist.import"
- ]
- canGrantRoles: [
- ]
- }
- }
+ // Defines roles and permissions
+ roles: {
+ owner: { // REQUIRED ROLE
+ title: "Owner"
+ showtitle: true
+ style: {
+ color: "#F46B40"
+ }
+ permissions: [
+ "djqueue.join"
+ "djqueue.joinlocked"
+ "djqueue.leave"
+ "djqueue.skip.self"
+ "djqueue.skip.other"
+ "djqueue.lock"
+ "djqueue.cycle"
+ "djqueue.limit"
+ "djqueue.move"
+ "djqueue.playLiveVideos"
+ "djqueue.limit.bypass"
+ "djqueue.lock.bypass"
+ "chat.send"
+ "chat.private"
+ "chat.broadcast"
+ "chat.delete"
+ "chat.specialMention"
+ "chat.staff"
+ "playlist.create"
+ "playlist.delete"
+ "playlist.rename"
+ "playlist.import"
+ "playlist.shuffle"
+ "room.grantroles"
+ "room.restrict.ban"
+ "room.restrict.mute"
+ "room.restrict.mute_silent"
+ "room.ratelimit.bypass"
+ "room.whois"
+ "room.whois.iphistory"
+ "server.checkForUpdates"
+ ]
+ canGrantRoles: [
+ "dev"
+ "coowner"
+ "supervisor"
+ "bot"
+ "regular"
+ "default"
+ ]
+ }
+ dev: { // OPTIONAL ROLE FOR MUSIQPAD DEVS
+ title: "Dev"
+ showtitle: true
+ style: {
+ color: "#A77DC2"
+ }
+ permissions: [
+ "djqueue.join"
+ "djqueue.joinlocked"
+ "djqueue.leave"
+ "djqueue.skip.self"
+ "djqueue.skip.other"
+ "djqueue.lock"
+ "djqueue.cycle"
+ "djqueue.limit"
+ "djqueue.move"
+ "djqueue.playLiveVideos"
+ "djqueue.limit.bypass"
+ "djqueue.lock.bypass"
+ "chat.send"
+ "chat.private"
+ "chat.broadcast"
+ "chat.delete"
+ "chat.specialMention"
+ "chat.staff"
+ "playlist.create"
+ "playlist.delete"
+ "playlist.rename"
+ "playlist.import"
+ "playlist.shuffle"
+ "room.grantroles"
+ "room.restrict.ban"
+ "room.restrict.mute"
+ "room.restrict.mute_silent"
+ "room.ratelimit.bypass"
+ "room.whois"
+ ]
+ canGrantRoles: [
+ "dev"
+ "coowner"
+ "supervisor"
+ "bot"
+ "regular"
+ "default"
+ ]
+ mention: "devs"
+ }
+ coowner: {
+ title: "Co-owner"
+ showtitle: true
+ style: {
+ color: "#89BE6C"
+ }
+ permissions: [
+ "djqueue.join"
+ "djqueue.joinlocked"
+ "djqueue.leave"
+ "djqueue.skip.self"
+ "djqueue.skip.other"
+ "djqueue.lock"
+ "djqueue.cycle"
+ "djqueue.limit"
+ "djqueue.move"
+ "djqueue.playLiveVideos"
+ "djqueue.limit.bypass"
+ "djqueue.lock.bypass"
+ "chat.send"
+ "chat.private"
+ "chat.delete"
+ "chat.specialMention"
+ "chat.broadcast"
+ "chat.staff"
+ "playlist.create"
+ "playlist.delete"
+ "playlist.rename"
+ "playlist.import"
+ "playlist.shuffle"
+ "room.grantroles"
+ "room.restrict.ban"
+ "room.restrict.mute"
+ "room.restrict.mute_silent"
+ "room.ratelimit.bypass"
+ "room.whois"
+ "room.whois.iphistory"
+ ]
+ canGrantRoles: [
+ "supervisor"
+ "bot"
+ "regular"
+ "default"
+ ]
+ }
+ supervisor: {
+ title: "Supervisor"
+ showtitle: true
+ style: {
+ color: "#009CDD"
+ }
+ permissions: [
+ "djqueue.join"
+ "djqueue.joinlocked"
+ "djqueue.leave"
+ "djqueue.skip.self"
+ "djqueue.skip.other"
+ "djqueue.lock"
+ "djqueue.cycle"
+ "djqueue.move"
+ "djqueue.playLiveVideos"
+ "djqueue.limit.bypass"
+ "djqueue.lock.bypass"
+ "chat.send"
+ "chat.private"
+ "chat.delete"
+ "chat.specialMention"
+ "chat.staff"
+ "playlist.create"
+ "playlist.delete"
+ "playlist.rename"
+ "playlist.import"
+ "playlist.shuffle"
+ "room.grantroles"
+ "room.restrict.ban"
+ "room.restrict.mute"
+ "room.restrict.mute_silent"
+ "room.ratelimit.bypass"
+ "room.whois"
+ ]
+ canGrantRoles: [
+ "regular"
+ "default"
+ ]
+ }
+ bot: {
+ title: "Bot"
+ showtitle: true
+ badge: "android"
+ style: {
+ color: "#964B74"
+ }
+ permissions: [
+ "djqueue.skip.other"
+ "djqueue.lock"
+ "djqueue.cycle"
+ "djqueue.move"
+ "chat.send"
+ "chat.delete"
+ "chat.specialMention"
+ "room.restrict.ban"
+ "room.restrict.mute"
+ "room.restrict.mute_silent"
+ "room.ratelimit.bypass"
+ ]
+ canGrantRoles: [
+ ]
+ }
+ regular: {
+ title: "Regular"
+ showtitle: false
+ style: {
+ color: "#925AFF"
+ }
+ permissions: [
+ "djqueue.join"
+ "djqueue.joinlocked"
+ "djqueue.leave"
+ "chat.send"
+ "chat.private"
+ "djqueue.skip.self"
+ "playlist.create"
+ "playlist.delete"
+ "playlist.rename"
+ "playlist.import"
+ ]
+ canGrantRoles: [
+ ]
+ }
+ default: { // REQUIRED ROLE
+ title: "Default"
+ showtitle: false
+ style: {
+ color: "#ffffff"
+ }
+ permissions: [
+ "djqueue.join"
+ "djqueue.leave"
+ "chat.send"
+ "chat.private"
+ "djqueue.skip.self"
+ "playlist.create"
+ "playlist.delete"
+ "playlist.rename"
+ "playlist.import"
+ ]
+ canGrantRoles: [
+ ]
+ }
+ }
}
\ No newline at end of file
diff --git a/socketserver/database_util.js b/socketserver/database_util.js
index c6ef8b1..e32b9ba 100644
--- a/socketserver/database_util.js
+++ b/socketserver/database_util.js
@@ -3,15 +3,15 @@ const Hash = require('./hash');
function DBUtils() {}
DBUtils.prototype.makePass = function (inPass, salt) {
- return Hash.md5(('' + inPass) + (salt || '')).toString();
+ return Hash.md5(('' + inPass) + (salt || '')).toString();
};
DBUtils.prototype.validateEmail = function (email) {
- return /^.+@.+\..+$/.test(email);
+ return /^.+@.+\..+$/.test(email);
};
DBUtils.prototype.validateUsername = function (un) {
- return /^[a-z0-9_-]{3,20}$/i.test(un);
+ return /^[a-z0-9_-]{3,20}$/i.test(un);
};
module.exports = new DBUtils();
diff --git a/socketserver/db_level.js b/socketserver/db_level.js
index 20b65d7..f0fc439 100644
--- a/socketserver/db_level.js
+++ b/socketserver/db_level.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line
'use strict';
// Modules
const levelup = require('levelup');
diff --git a/socketserver/db_mongo.js b/socketserver/db_mongo.js
index a9779af..96ca9f2 100644
--- a/socketserver/db_mongo.js
+++ b/socketserver/db_mongo.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line
'use strict';
// Modules
const mongodb = require('mongodb').MongoClient;
diff --git a/socketserver/mail/mailer.js b/socketserver/mail/mailer.js
index 857ce83..e397714 100644
--- a/socketserver/mail/mailer.js
+++ b/socketserver/mail/mailer.js
@@ -1,68 +1,76 @@
+'use strict';
const nodemailer = require('nodemailer');
const xoauth2 = require('xoauth2');
const fs = require('fs-extra');
const nconf = require('nconf');
const ejs = require('ejs');
-var Mailer = function () {
- const options = nconf.get('room:mail:options');
- var _this = this;
- _this.test = 1;
- if (nconf.get('room:allowrecovery') || nconf.get('room:mail:confirmation')) {
- switch (nconf.get('room:mail:transport')) {
- case 'smtp': {
- _this.transporter = nodemailer.createTransport(options);
- break;
- }
- case 'xoauth': {
- const xoauth = xoauth2.createXOAuth2Generator({
- user: options.auth.xoauth.user,
- clientId: options.auth.xoauth.clientId,
- clientSecret: options.auth.xoauth.clientSecret,
- refreshToken: options.auth.xoauth.refreshToken,
- accessToken: options.auth.xoauth.accessToken
- });
- options.auth.xoauth = xoauth;
- _this.transporter = nodemailer.createTransport(options);
- break;
- }
- case 'direct': {
- const domain = nconf.get('room:mail:sender').split('@')[1];
- options.name = domain;
- _this.transporter = nodemailer.createTransport(options);
- break;
- }
- }
+class Mailer {
+ constructor() {
+ const options = nconf.get('room:mail:options');
+ const self = this;
+
+ if (nconf.get('room:allowrecovery') || nconf.get('room:mail:confirmation')) {
+ switch (nconf.get('room:mail:transport')) {
+ case 'smtp': {
+ self.transporter = nodemailer.createTransport(options);
+ break;
+ }
+ case 'xoauth': {
+ const xoauth = xoauth2.createXOAuth2Generator({
+ user: options.auth.xoauth.user,
+ clientId: options.auth.xoauth.clientId,
+ clientSecret: options.auth.xoauth.clientSecret,
+ refreshToken: options.auth.xoauth.refreshToken,
+ accessToken: options.auth.xoauth.accessToken
+ });
+ options.auth.xoauth = xoauth;
+ self.transporter = nodemailer.createTransport(options);
+ break;
+ }
+ case 'direct': {
+ const domain = nconf.get('room:mail:sender').split('@')[1];
+ options.name = domain;
+ self.transporter = nodemailer.createTransport(options);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ }
}
-};
-Mailer.prototype.sendEmail = function (type, opts, receiver, callback) {
- const html = ejs.render(fs.readFileSync(`socketserver/mail/templates/${type}.html`, 'utf8'), {
- opts,
- room: nconf.get('room'),
- });
+ sendEmail(type, opts, receiver, callback) {
+ const html = ejs.render(fs.readFileSync(`socketserver/mail/templates/${type}.html`, 'utf8'), {
+ opts,
+ room: nconf.get('room'),
+ });
- var subject;
- switch(type) {
- case 'signup':
- subject = 'Welcome to musiqpad!';
- break;
- case 'recovery':
- subject = 'Password recovery';
- break;
- }
+ let subject;
+ switch (type) {
+ case 'signup':
+ subject = 'Welcome to musiqpad!';
+ break;
+ case 'recovery':
+ subject = 'Password recovery';
+ break;
+ default:
+ break;
+ }
- const emailObj = {
- from: nconf.get('room:mail:sender'),
- to: receiver,
- subject,
- html,
- };
+ const emailObj = {
+ from: nconf.get('room:mail:sender'),
+ to: receiver,
+ subject,
+ html,
+ };
- this.transporter.sendMail(emailObj, (error, response) => {
- if (error) callback(error);
- else callback(null, response);
- });
-};
+ this.transporter.sendMail(emailObj, (error, response) => {
+ if (error) callback(error);
+ else callback(null, response);
+ });
+ }
+}
module.exports = new Mailer();
diff --git a/socketserver/role.js b/socketserver/role.js
index e7805ac..9d0e3dc 100644
--- a/socketserver/role.js
+++ b/socketserver/role.js
@@ -1,97 +1,94 @@
-// eslint-disable-next-line
'use strict';
const nconf = require('nconf');
-var roles = nconf.get('roles');
+let roles = nconf.get('roles');
+let roleOrder = null;
+let staffRoles = null;
-// Caching the value so we don't have to loop through something every login
-var roleOrder = null;
-var staffRoles = null;
+class Role {
+ getRole(inRole) {
+ if (this.roleExists(inRole)) {
+ return roles[inRole];
+ }
-function Role(){
-
-}
+ return roles.default;
+ }
-Role.prototype.getRole = function(inRole){
- if (this.roleExists(inRole))
- return roles[inRole];
-
- return roles.default;
-};
-
-Role.prototype.roleExists = function(inRole){
- if (typeof roles[inRole] !== 'undefined')
- return true;
- return false;
-};
-
-Role.prototype.checkPermission = function(inRole, inPerm){
- var role = this.getRole(inRole);
- if (role){
- if((typeof inPerm) == 'string') {
- return role.permissions.indexOf(inPerm) != -1;
- }else{
- for(var i = 0; i < inPerm.length; i++)
- if(role.permissions.indexOf(inPerm[i]) == -1) return false;
+ roleExists(inRole) {
+ if (typeof roles[inRole] !== 'undefined') {
+ return true;
}
- return true;
+ return false;
}
- return false;
-};
-
-Role.prototype.checkCanGrant = function(inRole, inPerm){
- var role = this.getRole(inRole);
-
- if (role){
- if((typeof inPerm) == 'string') {
- inPerm = inPerm.toLowerCase();
- return role.canGrantRoles.indexOf(inPerm) != -1;
- }else{
- for(var i = 0; i < inPerm.length; i++)
- if(role.canGrantRoles.indexOf(inPerm[i].toLowerCase()) == -1) return false;
+
+ checkPermission(inRole, inPerm) {
+ const role = this.getRole(inRole);
+ if (role) {
+ if ((typeof inPerm) === 'string') {
+ return role.permissions.indexOf(inPerm) !== -1;
+ }
+ for (let i = 0; i < inPerm.length; i++) {
+ if (role.permissions.indexOf(inPerm[i]) === -1) {
+ return false;
+ }
+ }
+ return true;
}
-
- return true;
+ return false;
}
- return false;
-};
-Role.prototype.makeClientObj = function () {
- return roles;
-};
+ checkCanGrant(inRole, inPerm) {
+ const role = this.getRole(inRole);
-Role.prototype.getOrder = function () {
- if (roleOrder) return roleOrder;
+ if (role) {
+ if ((typeof inPerm) === 'string') {
+ inPerm = inPerm.toLowerCase();
+ return role.canGrantRoles.indexOf(inPerm) !== -1;
+ }
+ for (let i = 0; i < inPerm.length; i++) {
+ if (role.canGrantRoles.indexOf(inPerm[i].toLowerCase()) === -1) return false;
+ }
- let roleOrderTemp = nconf.get('roleOrder');
- if (roleOrderTemp && Array.isArray(roleOrderTemp)){
- for (var i in roles){
- if (roleOrderTemp.indexOf(i) == -1) roleOrderTemp.push(i);
+ return true;
}
+ return false;
+ }
- roleOrder = roleOrderTemp;
- return roleOrderTemp;
- }
-
- var temp = [];
-
- for (var i in roles){
- temp.push(i);
+ makeClientObj() {
+ return roles;
}
-
- roleOrder = temp;
- return temp;
-};
-
-Role.prototype.getStaffRoles = function(){
- if(staffRoles) return staffRoles;
-
- if (nconf.get('staffRoles') && Array.isArray(nconf.get('staffRoles'))) {
- staffRoles = nconf.get('staffRoles');
- return staffRoles;
+
+ getOrder() {
+ if (roleOrder) return roleOrder;
+
+ const roleOrderTemp = nconf.get('roleOrder');
+ if (roleOrderTemp && Array.isArray(roleOrderTemp)) {
+ for (let i in roles) {
+ if (roleOrderTemp.indexOf(i) === -1) roleOrderTemp.push(i);
+ }
+
+ roleOrder = roleOrderTemp;
+ return roleOrderTemp;
+ }
+
+ const temp = [];
+
+ for (var i in roles) {
+ temp.push(i);
+ }
+
+ roleOrder = temp;
+ return temp;
}
- return [];
-};
+ getStaffRoles() {
+ if (staffRoles) return staffRoles;
+ if (nconf.get('staffRoles') && Array.isArray(nconf.get('staffRoles'))) {
+ staffRoles = nconf.get('staffRoles');
+ return staffRoles;
+ }
+ return [];
+ }
+}
module.exports = new Role();
diff --git a/socketserver/room.js b/socketserver/room.js
index 0c80083..1abedb0 100644
--- a/socketserver/room.js
+++ b/socketserver/room.js
@@ -1,710 +1,699 @@
-var extend = require('extend');
-var ws = require('ws');
-var https = require('https');
-var http = require('http');
-var log = new (require('basic-logger'))({showTimestamp: true, prefix: "Room"});
-var DJQueue = require('./djqueue.js');
-var Roles = require('./role');
-var DB = require('./database');
+'use strict';
+const extend = require('extend');
+const ws = require('ws');
+const https = require('https');
+const log = new (require('basic-logger'))({ showTimestamp: true, prefix: 'Room' });
+const DJQueue = require('./djqueue.js');
+const Roles = require('./role');
+const DB = require('./database');
const nconf = require('nconf');
-var defaultDBObj = function(){
+const DefaultDBObj = function () {
return {
- roles: {},
+ roles: {},
restrictions: {}, // Uses UID as key, object containing reason and end time as value.
history: []
};
};
-var Room = function(socketServer, options){
- var that = this;
-
- this.roomInfo = extend(true, {
- name: "", // Room name
- slug: "", // Room name shorthand (no spaces, alphanumeric with dashes)
- greet: "", // Room greetings
- maxCon: 0, // Max connections; 0 = unlimited
- ownerEmail: "", // Owner email for owner promotion
- guestCanSeeChat: true, // Whether guests can see the chat or not
- bannedCanSeeChat: true, // Whether banned users can see the chat
- roomOwnerUN: null, // Username of the room owner to use with lobby API
- }, options);
-
- this.socketServer = socketServer;
- this.queue = new DJQueue( this );
- this.attendeeList = [];
- this.data = new defaultDBObj();
- this.apiUpdateTimeout = null;
- this.lastChat = [];
- this.createApiTimeout();
-
- this.restrictiontypes = [
- 'BAN',
- 'MUTE',
- 'SILENT_MUTE'
+class Room {
+ constructor(socketServer, options) {
+ const that = this;
+
+ this.roomInfo = extend(true, {
+ name: '', // Room name
+ slug: '', // Room name shorthand (no spaces, alphanumeric with dashes)
+ greet: '', // Room greetings
+ maxCon: 0, // Max connections; 0 = unlimited
+ ownerEmail: '', // Owner email for owner promotion
+ guestCanSeeChat: true, // Whether guests can see the chat or not
+ bannedCanSeeChat: true, // Whether banned users can see the chat
+ roomOwnerUN: null, // Username of the room owner to use with lobby API
+ }, options);
+
+ this.socketServer = socketServer;
+ this.queue = new DJQueue(this);
+ this.attendeeList = [];
+ this.data = new DefaultDBObj();
+ this.apiUpdateTimeout = null;
+ this.lastChat = [];
+ this.createApiTimeout();
+
+ this.restrictiontypes = [
+ 'BAN',
+ 'MUTE',
+ 'SILENT_MUTE'
];
- DB.getRoom(this.roomInfo.slug, function(err, data){
- // Just in case the slug doesn't exist yet
- data = data || {};
+ DB.getRoom(this.roomInfo.slug, (err, data) => {
+ // Just in case the slug doesn't exist yet
+ data = data || {};
- // If the slug doesn't exist, make owner will make the slug
- if (err && !err.notFound){
- console.log(err);
- return;
- }
-
- extend(true, that.data, data);
+ // If the slug doesn't exist, make owner will make the slug
+ if (err && !err.notFound) {
+ console.log(err);
+ return;
+ }
- that.makeOwner();
- });
-};
+ extend(true, that.data, data);
-Room.prototype.getRoomMeta = function(){
- return {
- name: this.roomInfo.name,
- slug: this.roomInfo.slug,
- greet: this.roomInfo.greet,
- bg: this.roomInfo.bg,
- guestCanSeeChat: this.roomInfo.guestCanSeeChat,
- bannedCanSeeChat: this.roomInfo.bannedCanSeeChat,
- roomOwnerUN: this.roomInfo.roomOwnerUN
- };
-};
+ that.makeOwner();
+ });
+ }
-Room.prototype.makeOwner = function(){
- if (!nconf.get('room:ownerEmail')) return;
+ getRoomMeta() {
+ return {
+ name: this.roomInfo.name,
+ slug: this.roomInfo.slug,
+ greet: this.roomInfo.greet,
+ bg: this.roomInfo.bg,
+ guestCanSeeChat: this.roomInfo.guestCanSeeChat,
+ bannedCanSeeChat: this.roomInfo.bannedCanSeeChat,
+ roomOwnerUN: this.roomInfo.roomOwnerUN
+ };
+ }
- var that = this;
+ makeOwner() {
+ if (!nconf.get('room:ownerEmail')) return;
- DB.getUser(this.roomInfo.ownerEmail, function(err, data){
- if (err == 'UserNotFound') { console.log('Owner does not exist yet.'); that.data.roles.owner = []; return; }
- if (err) { console.log('Cannot make Room Owner: ' + err); return; }
+ const that = this;
- if (typeof data.uid !== 'number') { console.log('Cannot make room owner: UserUIDError'); return; }
+ DB.getUser(this.roomInfo.ownerEmail, (err, data) => {
+ if (err === 'UserNotFound') {
+ console.log('Owner does not exist yet.');
+ that.data.roles.owner = [];
+ return;
+ }
+ if (err) {
+ console.log(`Cannot make Room Owner: ${err}`);
+ return;
+ }
- log.info('Granting ' + data.un + ' (' + data.uid + ') Owner permissions');
+ if (typeof data.uid !== 'number') {
+ console.log('Cannot make room owner: UserUIDError');
+ return;
+ }
- // Remove user from other roles to avoid interesting bugs
- for (var i in that.data.roles){
- var ind = that.data.roles[i].indexOf(data.uid);
- if ( ind > -1 ) that.data.roles[i].splice(ind, 1);
- }
+ log.info(`Granting ${data.un} (${data.uid}) Owner permissions`);
- // Only one owner, set entire array to one UID and set owner username for API
- that.data.roles.owner = [ data.uid ];
- that.data.roomOwnerUN = data.un;
- that.roomInfo.roomOwnerUN = data.un;
- data.role = that.findRole(data.uid);
- that.sendUserUpdate(data);
- that.save();
- });
-};
+ // Remove user from other roles to avoid interesting bugs
+ for (const i in that.data.roles) {
+ const ind = that.data.roles[i].indexOf(data.uid);
+ if (ind > -1) that.data.roles[i].splice(ind, 1);
+ }
-Room.prototype.addUser = function( sock ){
- this.attendeeList.push( sock );
- var userSend = null;
- var numGuests = 0;
- sock.room = this.roomInfo.slug;
+ // Only one owner, set entire array to one UID and set owner username for API
+ that.data.roles.owner = [data.uid];
+ that.data.roomOwnerUN = data.un;
+ that.roomInfo.roomOwnerUN = data.un;
+ data.role = that.findRole(data.uid);
+ that.sendUserUpdate(data);
+ that.save();
+ });
+ }
- if (sock.user){
- this.checkMakeOwner();
- sock.user.data.role = this.findRole(sock.user.data.uid);
- userSend = sock.user.getClientObj();
+ addUser(sock) {
+ this.attendeeList.push(sock);
+ let userSend = null;
+ let numGuests = 0;
+ sock.room = this.roomInfo.slug;
+
+ if (sock.user) {
+ this.checkMakeOwner();
+ sock.user.data.role = this.findRole(sock.user.data.uid);
+ userSend = sock.user.getClientObj();
- for (var i = 0; i < this.attendeeList.length; i++){
- var sockObj = this.attendeeList[i];
+ for (let i = 0; i < this.attendeeList.length; i++) {
+ const sockObj = this.attendeeList[i];
- if (!sockObj.user){
- numGuests++;
- continue;
- }
+ if (!sockObj.user) {
+ numGuests++;
+ continue;
+ }
- if (sockObj == sock) continue;
+ if (sockObj === sock) continue;
- if (sockObj.user && sock.user && sockObj.user.data.uid == sock.user.data.uid){
- this.removeUser(sockObj);
- sockObj.close(1000, JSON.stringify({
- type: 'ConnectedElsewhere'
- }));
+ if (sockObj.user && sock.user && sockObj.user.data.uid === sock.user.data.uid) {
+ this.removeUser(sockObj);
+ sockObj.close(1000, JSON.stringify({
+ type: 'ConnectedElsewhere'
+ }));
+ }
}
- }
- }else{
- for (var i = 0; i < this.attendeeList.length; i++){
- var sockObj = this.attendeeList[i];
+ } else {
+ for (let i = 0; i < this.attendeeList.length; i++) {
+ const sockObj = this.attendeeList[i];
- if (!sockObj.user){
- numGuests++;
+ if (!sockObj.user) {
+ numGuests++;
+ }
}
}
- }
- //TODO: Find and add role key to user object from room db
-
- this.sendAll({
- type: 'userJoined',
- data: {
- user: userSend,
- guests: numGuests
- }
- },
- function(sockObj){
- return sockObj != sock;
- });
+ // TODO: Find and add role key to user object from room db
-};
+ this.sendAll({
+ type: 'userJoined',
+ data: {
+ user: userSend,
+ guests: numGuests
+ }
+ },
+ sockObj => sockObj !== sock);
+ }
-Room.prototype.replaceUser = function( sock_old, sock_new ){
- if (!sock_old || !sock_old.user || !sock_new || !sock_new.user || sock_old.user.data.uid != sock_new.user.data.uid) return false;
- var ind = this.attendeeList.indexOf(sock_old);
- this.checkMakeOwner();
+ replaceUser(sockOld, sockNew) {
+ if (!sockOld || !sockOld.user || !sockNew || !sockNew.user || sockOld.user.data.uid !== sockNew.user.data.uid) return false;
+ const ind = this.attendeeList.indexOf(sockOld);
+ this.checkMakeOwner();
+ if (ind === -1) return false;
- if (ind == -1 ) return false;
+ sockNew.room = this.roomInfo.slug;
+ sockNew.user.data.role = this.findRole(sockOld.user.data.uid);
+ this.attendeeList[ind] = sockNew;
+ this.queue.replaceSocket(sockOld, sockNew);
- sock_new.room = this.roomInfo.slug;
+ return true;
+ }
- sock_new.user.data.role = this.findRole(sock_old.user.data.uid);
+ removeUser(sock) {
+ const that = this;
+ const ind = this.attendeeList.indexOf(sock);
- this.attendeeList[ind] = sock_new;
+ if (ind > -1) {
+ sock.room = null;
- this.queue.replaceSocket(sock_old, sock_new);
+ let userSend = null;
- return true;
-};
+ this.queue.remove(sock);
-Room.prototype.removeUser = function( sock ){
- var that = this;
- var ind = this.attendeeList.indexOf(sock);
+ if (sock.user) {
+ userSend = sock.user.getClientObj();
+ sock.user.data.role = null;
+ }
- if (ind > -1) {
- sock.room = null;
+ this.attendeeList.splice(ind, 1);
- var userSend = null;
+ this.sendAll({
+ type: 'userLeft',
+ data: {
+ user: userSend,
+ guests: ((() => {
+ let num = 0;
+ for (let i = 0; i < that.attendeeList.length; i++) {
+ if (!that.attendeeList[i].user) num++;
+ }
+ return num;
+ }))()
+ }
+ });
+ }
+ }
- this.queue.remove( sock );
+ restrictUser(restrictObj, callback) {
+ /*
+ Expects {
+ restrictObj: {
+ uid: uid,
+ end: int,
+ start: int,
+ reason: '',
+ type: '',
+ source: {
+ uid: uid,
+ role: role
+ }
+ }
+ }
+ */
+ const that = this;
- if (sock.user) {
- userSend = sock.user.getClientObj();
- sock.user.data.role = null;
+ if (this.restrictiontypes.indexOf(restrictObj.type) === -1) {
+ if (callback) callback('InvalidRestrictionType');
+ return;
}
- this.attendeeList.splice( ind, 1 );
-
- this.sendAll({
- type: 'userLeft',
- data: {
- user: userSend,
- guests: (function(){
- var num = 0;
- for (var i = 0; i < that.attendeeList.length; i++){
- if (!that.attendeeList[i].user) num++;
- }
- return num;
- })()
+ DB.getUserByUid(restrictObj.uid, (err, user) => {
+ if (err) {
+ if (callback) {
+ callback(err);
+ }
+ return;
}
- });
- }
-};
-Room.prototype.restrictUser = function(restrictObj, callback){
- /*
- Expects {
- restrictObj: {
- uid: uid,
- end: int,
- start: int,
- reason: '',
- type: '',
- source: {
- uid: uid,
- role: role
+ if (that.isUserRestricted(restrictObj.uid, restrictObj.type)) {
+ if (callback) callback('UserAlreadyRestricted');
+ return;
}
- }
- }
- */
- var that = this;
-
- if(this.restrictiontypes.indexOf(restrictObj.type) == -1)
- {
- if (callback) callback("InvalidRestrictionType");
- return;
- }
-
- DB.getUserByUid(restrictObj.uid, function(err, user) {
- if (err) {
- if (callback)
- callback(err);
- return;
- }
-
- if (that.isUserRestricted(restrictObj.uid, restrictObj.type)){
- if (callback) callback('UserAlreadyRestricted');
- return;
- }
- user.role = that.findRole(user.uid);
-
- if (!Roles.checkCanGrant(restrictObj.source.role, [user.role])) {
- if (callback) callback('UserCannotBeRestricted');
- return;
- }
-
- restrictObj.reason = restrictObj.reason.substr(0, 50);
-
- that.data.restrictions[restrictObj.uid] = that.data.restrictions[restrictObj.uid] || {};
- that.data.restrictions[restrictObj.uid][restrictObj.type] = restrictObj;
- that.save();
-
- that.sendAll({
- type: 'userRestricted',
- data: {
- uid: restrictObj.uid,
- type: restrictObj.type,
- source: restrictObj.source.uid,
+ user.role = that.findRole(user.uid);
+
+ if (!Roles.checkCanGrant(restrictObj.source.role, [user.role])) {
+ if (callback) callback('UserCannotBeRestricted');
+ return;
}
- }, function(obj){
- return restrictObj.type != 'SILENT_MUTE' || (obj.user && Roles.checkPermission(obj.user.role, 'room.restrict.silent_mute'));
- });
- var userSock = that.findSocketByUid(restrictObj.uid);
+ restrictObj.reason = restrictObj.reason.substr(0, 50);
+
+ that.data.restrictions[restrictObj.uid] = that.data.restrictions[restrictObj.uid] || {};
+ that.data.restrictions[restrictObj.uid][restrictObj.type] = restrictObj;
+ that.save();
- //Check if user is online
- if (userSock && restrictObj.type == 'BAN'){
- that.removeUser(userSock);
- userSock.close(1000, JSON.stringify({
- type: 'banned',
+ that.sendAll({
+ type: 'userRestricted',
data: {
- end: restrictObj.end,
- reason: restrictObj.reason
+ uid: restrictObj.uid,
+ type: restrictObj.type,
+ source: restrictObj.source.uid,
}
- }));
- }
-
- if (callback) callback(null);
- });
-};
+ }, obj => restrictObj.type !== 'SILENT_MUTE' || (obj.user && Roles.checkPermission(obj.user.role, 'room.restrict.silent_mute')));
+
+ const userSock = that.findSocketByUid(restrictObj.uid);
+
+ // Check if user is online
+ if (userSock && restrictObj.type === 'BAN') {
+ that.removeUser(userSock);
+ userSock.close(1000, JSON.stringify({
+ type: 'banned',
+ data: {
+ end: restrictObj.end,
+ reason: restrictObj.reason
+ }
+ }));
+ }
-Room.prototype.getRestrictions = function(arr, uid){
- var out = {};
-
- for(var key in this.data.restrictions[uid]){
- if(key.indexOf(arr))
- out[key] = this.data.restrictions[uid][key];
+ if (callback) callback(null);
+ });
}
-
- return out;
-};
-Room.prototype.unrestrictUser = function(uid, type, sock){
- if (this.data.restrictions[uid][type]){
- delete this.data.restrictions[uid][type];
- this.save();
+ getRestrictions(arr, uid) {
+ const out = {};
- this.sendAll({
- type: 'userUnrestricted',
- data: {
- uid: uid,
- type: type,
- source: (sock ? sock.user.data.uid : null)
- }
- }, function(obj){
- return type != 'SILENT_MUTE' || (obj.user && Roles.checkPermission(obj.user.role, 'room.restrict.silent_mute'));
- });
+ for (const key in this.data.restrictions[uid]) {
+ if (key.indexOf(arr))
+ out[key] = this.data.restrictions[uid][key];
+ }
- return true;
+ return out;
}
- return false;
-};
-Room.prototype.isUserRestricted = function(uid, type){
- if ((this.data.restrictions[uid] || {})[type]) {
- if (this.data.restrictions[uid][type].end < new Date(Date.now())) {
- this.unrestrictUser(uid, type);
- return false;
+ unrestrictUser(uid, type, sock) {
+ if (this.data.restrictions[uid][type]) {
+ delete this.data.restrictions[uid][type];
+ this.save();
+
+ this.sendAll({
+ type: 'userUnrestricted',
+ data: {
+ uid,
+ type,
+ source: (sock ? sock.user.data.uid : null)
+ }
+ }, obj => type !== 'SILENT_MUTE' || (obj.user && Roles.checkPermission(obj.user.role, 'room.restrict.silent_mute')));
+
+ return true;
}
- else {
+ return false;
+ }
+
+ isUserRestricted(uid, type) {
+ if ((this.data.restrictions[uid] || {})[type]) {
+ if (this.data.restrictions[uid][type].end < new Date(Date.now())) {
+ this.unrestrictUser(uid, type);
+ return false;
+ }
return true;
}
+ return false;
}
- return false;
-};
-Room.prototype.setRole = function(user, role){
- if (!user) return false;
+ setRole(user, role) {
+ if (!user) return false;
- if (!role) role = 'default';
+ if (!role) role = 'default';
- role = role.toLowerCase();
+ role = role.toLowerCase();
- if (Roles.roleExists(role)){
- if (typeof this.data.roles[role] === 'undefined') this.data.roles[role] = [];
+ if (Roles.roleExists(role)) {
+ if (typeof this.data.roles[role] === 'undefined') this.data.roles[role] = [];
- var userSock = this.findSocketByUid(user.uid);
+ const userSock = this.findSocketByUid(user.uid);
- // Remove user from other role
- this.removeRole(user);
+ // Remove user from other role
+ this.removeRole(user);
- if (role != 'default')
- this.data.roles[role].push(user.uid);
+ if (role !== 'default') this.data.roles[role].push(user.uid);
- user.role = role;
+ user.role = role;
-
- // Save the changes
- this.save();
+ // Save the changes
+ this.save();
- if (userSock){
- // We can't assign this user object to the socket because it lacks playlists
- userSock.user.data.role = role;
- }
+ if (userSock) {
+ // We can't assign this user object to the socket because it lacks playlists
+ userSock.user.data.role = role;
+ }
- this.sendUserUpdate(user);
+ this.sendUserUpdate(user);
- return true;
+ return true;
+ }
+ return false;
}
- return false;
-};
+ removeRole(user) {
+ if (!user) return;
-Room.prototype.removeRole = function(user){
- if (!user) return;
-
- for (var i in this.data.roles){
- var ind = this.data.roles[i].indexOf(user.uid);
- if ( ind > -1){
- this.data.roles[i].splice(ind, 1);
+ for (const i in this.data.roles) {
+ const ind = this.data.roles[i].indexOf(user.uid);
+ if (ind > -1) {
+ this.data.roles[i].splice(ind, 1);
+ }
}
}
-};
-Room.prototype.findRole = function(uid){
- if (!uid) return 'default';
+ findRole(uid) {
+ if (!uid) return 'default';
- for (var i in this.data.roles){
- var ind = this.data.roles[i].indexOf(uid);
- if ( ind > -1 && Roles.roleExists(i) ){
- return i;
+ for (const i in this.data.roles) {
+ const ind = this.data.roles[i].indexOf(uid);
+ if (ind > -1 && Roles.roleExists(i)) {
+ return i;
+ }
}
+
+ return 'default';
}
- return 'default';
-};
+ findSocketByUid(uid) {
+ for (const i in this.attendeeList) {
+ if (!this.attendeeList[i].user) continue;
-Room.prototype.findSocketByUid = function( uid ){
+ if (this.attendeeList[i].user.data.uid === uid) return this.attendeeList[i];
+ }
- for (var i in this.attendeeList){
- if (!this.attendeeList[i].user) continue;
+ return null;
+ }
- if (this.attendeeList[i].user.data.uid == uid) return this.attendeeList[i];
+ getAttendees() {
+ return this.attendeeList;
}
- return null;
-};
+ getBannedUsers(callback) {
+ const banned = [];
+ const rawBanned = [];
+ const that = this;
-Room.prototype.getAttendees = function(){
- return this.attendeeList;
-};
+ for (const i in this.data.restrictions) {
+ // This will unban appropriately when the list is viewed.
+ if (this.isUserRestricted(i, 'BAN'))
+ rawBanned.push(i);
+ }
-Room.prototype.getBannedUsers = function(callback){
- var banned = [];
- var rawBanned = [];
- var that = this;
-
- for (var i in this.data.restrictions){
- // This will unban appropriately when the list is viewed.
- if (this.isUserRestricted(i, 'BAN'))
- rawBanned.push(i);
- }
+ if (!rawBanned.length) {
+ callback('NoBans');
+ return;
+ }
+
+ DB.getUserByUid(rawBanned, { getPlaylists: false }, (err, users) => {
+ for (const j in users) {
+ const usr = users[j].getClientObj();
+ usr.role = that.findRole(usr.uid);
+ banned.push(usr);
+ }
- if (!rawBanned.length){
- callback('NoBans');
- return;
+ callback(err, banned);
+ });
}
- DB.getUserByUid(rawBanned, {getPlaylists: false}, function (err, users) {
- for (var j in users){
- var usr = users[j].getClientObj();
- usr.role = that.findRole(usr.uid);
- banned.push(usr);
+ getRoomStaff(callback) {
+ const staff = [];
+ let rawStaff = [];
+ const that = this;
+
+ for (const i in this.data.roles) {
+ if (Roles.getStaffRoles().indexOf(i) > -1) {
+ rawStaff = rawStaff.concat(this.data.roles[i]);
+ }
}
- callback(err, banned);
- });
-};
+ if (!rawStaff.length) {
+ callback('NoStaff');
+ return;
+ }
-Room.prototype.getRoomStaff = function(callback){
- var staff = [];
- var rawStaff = [];
- var that = this;
+ DB.getUserByUid(rawStaff, { getPlaylists: false }, (err, users) => {
+ for (const j in users) {
+ const usr = users[j].getClientObj();
+ usr.role = that.findRole(usr.uid);
+ staff.push(usr);
+ }
- for (var i in this.data.roles){
- if (Roles.getStaffRoles().indexOf(i) > -1) {
- rawStaff = rawStaff.concat(this.data.roles[i]);
- }
+ callback(err, staff);
+ });
}
- if (!rawStaff.length){
- callback('NoStaff');
- return;
+ sendSystemMessage(message) {
+ this.sendAll({ type: 'systemMessage', data: message });
}
- DB.getUserByUid(rawStaff, { getPlaylists: false }, function (err, users) {
- for (var j in users){
- var usr = users[j].getClientObj();
- usr.role = that.findRole(usr.uid);
- staff.push(usr);
- }
+ sendBroadcastMessage(message) {
+ this.sendAll({ type: 'broadcastMessage', data: message });
+ }
- callback(err, staff);
- });
-};
+ sendMessage(sock, message, ext, specdata, callback) {
+ const that = this;
-Room.prototype.sendSystemMessage = function(message) {
- this.sendAll({type:'systemMessage', data:message});
-};
+ message = message.substring(0, 255).replace(//g, '>');
-Room.prototype.sendBroadcastMessage = function(message) {
- this.sendAll({type:'broadcastMessage', data:message});
-};
+ callback = callback || (() => {});
-Room.prototype.sendMessage = function( sock, message, ext, specdata, callback ){
- var that = this;
+ if (this.isUserRestricted(sock.user.uid, 'SILENT_MUTE')) {
+ DB.logChat(sock.user.uid, message, 'res:mute_s', (err, cid) => {
+ sock.sendJSON({
+ type: 'chat',
+ data: {
+ uid: sock.user.uid,
+ message,
+ time: Date.now(),
+ cid,
+ special: specdata,
+ }
+ });
+ callback(cid);
+ });
+ } else if (this.isUserRestricted(sock.user.uid, 'MUTE')) {
+ callback(null);
+ } else {
+ DB.logChat(sock.user.uid, message, specdata, (err, cid) => {
+ that.sendAll({
+ type: 'chat',
+ data: {
+ uid: sock.user.uid, // Will always be present. Unauthd can't send messages
+ message,
+ time: Date.now(),
+ cid,
+ special: specdata
+ }
+ }, obj => {
+ // Guests can't see chat with config variable set
+ if (!that.roomInfo.guestCanSeeChat && !obj.user) return false;
- message = message.substring(0,255).replace(//g, '>');
+ // Banned users can't see chat with config variable set
+ if (!that.roomInfo.bannedCanSeeChat && obj.user && that.isUserRestricted(obj.user.uid, 'BAN')) return false;
- callback = callback || function(){};
-
- if(this.isUserRestricted(sock.user.uid, 'SILENT_MUTE')){
- DB.logChat(sock.user.uid, message, 'res:mute_s', function(err, cid){
- sock.sendJSON({
- type: 'chat',
- data: {
- uid: sock.user.uid,
- message: message,
- time: Date.now(),
- cid: cid,
- special: specdata,
- }
- });
- callback(cid);
- });
- } else if(this.isUserRestricted(sock.user.uid, 'MUTE')){
- callback(null);
- } else {
- DB.logChat(sock.user.uid, message, specdata, function(err, cid){
- that.sendAll({
- type: 'chat',
- data: {
- uid: sock.user.uid, // Will always be present. Unauthd can't send messages
- message: message,
- time: Date.now(),
- cid: cid,
- special: specdata
- }
- }, function(obj){
- // Guests can't see chat with config variable set
- if (!that.roomInfo.guestCanSeeChat && !obj.user) return false;
-
- // Banned users can't see chat with config variable set
- if (!that.roomInfo.bannedCanSeeChat && obj.user && that.isUserRestricted(obj.user.uid, 'BAN')) return false;
-
- // Check for extensive function
- if("function" === typeof ext) if(!ext(obj)) return false;
-
- return true;
- });
-
- //Save last X messages to show newly connected users
- if(!specdata){
- that.lastChat.push({
- user: sock.user.getClientObj(),
- message: message,
- time: Date.now(),
- cid: cid,
+ // Check for extensive function
+ if (typeof ext === 'function') if (!ext(obj)) return false;
+
+ return true;
});
- if(that.lastChat.length > nconf.get('room:lastmsglimit')) that.lastChat.shift();
- }
-
- callback(cid);
- });
- }
-};
-Room.prototype.makePrevChatObj = function(){
- var uids = [];
- var temp = extend(true, [], this.lastChat);
+ // Save last X messages to show newly connected users
+ if (!specdata) {
+ that.lastChat.push({
+ user: sock.user.getClientObj(),
+ message,
+ time: Date.now(),
+ cid,
+ });
+ if (that.lastChat.length > nconf.get('room:lastmsglimit')) that.lastChat.shift();
+ }
- for (var i = 0; i < temp.length; i++){
- var ind = uids.indexOf(temp[i].user.uid);
- if ( ind == -1 ){
- uids.push( temp[i].user.uid );
- continue;
+ callback(cid);
+ });
}
-
- temp[i].user = { uid: temp[i].user.uid };
}
- return temp;
-};
+ makePrevChatObj() {
+ const uids = [];
+ const temp = extend(true, [], this.lastChat);
-Room.prototype.deleteChat = function(cid, uid){
- for (var i = 0; i < this.lastChat.length; i++){
- if (this.lastChat[i].cid == cid){
- this.lastChat.splice(i, 1);
- break;
- }
- }
+ for (let i = 0; i < temp.length; i++) {
+ const ind = uids.indexOf(temp[i].user.uid);
+ if (ind === -1) {
+ uids.push(temp[i].user.uid);
+ continue;
+ }
- this.sendAll({
- type: 'deleteChat',
- data: {
- cid: cid,
- mid : uid
+ temp[i].user = { uid: temp[i].user.uid };
}
- });
-};
-Room.prototype.sendAll = function (message, condition){
- condition = condition || function(){return true;};
- for (var i in this.attendeeList){
- var obj = this.attendeeList[i];
+ return temp;
+ }
- if (obj.readyState != ws.OPEN || !condition(obj)) continue;
+ deleteChat(cid, uid) {
+ for (let i = 0; i < this.lastChat.length; i++) {
+ if (this.lastChat[i].cid === cid) {
+ this.lastChat.splice(i, 1);
+ break;
+ }
+ }
- obj.sendJSON(message);
+ this.sendAll({
+ type: 'deleteChat',
+ data: {
+ cid,
+ mid: uid
+ }
+ });
}
-};
-Room.prototype.sendUserUpdate = function(user){
- if (!user) return;
+ sendAll(message, condition) {
+ if (!condition) condition = () => true;
+ for (const i in this.attendeeList) {
+ const obj = this.attendeeList[i];
- this.sendAll({
- type: 'userUpdate',
- data: {
- user: user.getClientObj()
- }
- });
-};
-
-Room.prototype.getUsersObj = function(){
- var temp = {
- guests: 0,
- users: {}
- };
- var guestCounter = 0;
+ if (obj.readyState !== ws.OPEN || !condition(obj)) continue;
- for (var i = 0; i < this.attendeeList.length; i++){
- var obj = this.attendeeList[i];
- if (!obj.user){
- temp.guests++;
- continue;
+ obj.sendJSON(message);
}
+ }
+
+ sendUserUpdate(user) {
+ if (!user) return;
- temp.users[ obj.user.uid ] = obj.user.getClientObj();
+ this.sendAll({
+ type: 'userUpdate',
+ data: {
+ user: user.getClientObj()
+ }
+ });
}
- return temp;
-};
+ getUsersObj() {
+ const temp = {
+ guests: 0,
+ users: {}
+ };
-Room.prototype.getHistoryObj = function() {
- return this.data.history.slice(-nconf.get('room:history:limit_send')).reverse();
-};
+ for (let i = 0; i < this.attendeeList.length; i++) {
+ const obj = this.attendeeList[i];
+ if (!obj.user) {
+ temp.guests++;
+ continue;
+ }
-Room.prototype.addToHistory = function(historyObj) {
- //Limit history
- if(nconf.get('room:history:limit_save') !== 0)
- while (this.data.history.length >= nconf.get('room:history:limit_save')) {
- this.data.history.shift();
+ temp.users[obj.user.uid] = obj.user.getClientObj();
}
- //Add to history and save
- this.data.history.push(historyObj);
- this.save();
-};
+ return temp;
+ }
-Room.prototype.updateLobbyServer = function(song, dj, callback) {
- if (!nconf.get('apis:musiqpad:sendLobbyStats')) {
- if (callback) callback();
- return;
+ getHistoryObj() {
+ return this.data.history.slice(-nconf.get('room:history:limit_send')).reverse();
}
- else if (!nconf.get('apis:musiqpad:key') || nconf.get('apis:musiqpad:key') == "") {
- console.log("A musiqpad key must be defined in the config for updating the lobby server.");
- return;
+
+ addToHistory(historyObj) {
+ // Limit history
+ if (nconf.get('room:history:limit_save') !== 0) {
+ while (this.data.history.length >= nconf.get('room:history:limit_save')) {
+ this.data.history.shift();
+ }
+ }
+
+ // Add to history and save
+ this.data.history.push(historyObj);
+ this.save();
}
- var postData = {
- song: song,
- dj: dj,
- room: this.getRoomMeta(),
- userCount: this.attendeeList.length
- };
- var postOptions = {
- host: 'api.musiqpad.com',
- port: '443',
- path: '/pad/' + this.roomInfo.slug,
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'apikey': nconf.get('apis:musiqpad:key')
- }
- };
- try {
- var postReq = https.request(postOptions, function (response) {
- if (response.statusCode < 200 || response.statusCode > 299) {
- console.log('Request Failed with Status Code: ' + response.statusCode);
- }
- if (callback) callback();
- });
- postReq.write(JSON.stringify(postData));
- postReq.on('error', function() {
+
+ updateLobbyServer(song, dj, callback) {
+ if (!nconf.get('apis:musiqpad:sendLobbyStats')) {
+ if (callback) callback();
+ return;
+ } else if (!nconf.get('apis:musiqpad:key') || nconf.get('apis:musiqpad:key') === '') {
+ console.log('A musiqpad key must be defined in the config for updating the lobby server.');
+ return;
+ }
+ const postData = {
+ song,
+ dj,
+ room: this.getRoomMeta(),
+ userCount: this.attendeeList.length
+ };
+ const postOptions = {
+ host: 'api.musiqpad.com',
+ port: '443',
+ path: `/pad/${this.roomInfo.slug}`,
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ apikey: nconf.get('apis:musiqpad:key')
+ }
+ };
+ try {
+ const postReq = https.request(postOptions, response => {
+ if (response.statusCode < 200 || response.statusCode > 299) {
+ console.log(`Request Failed with Status Code: ${response.statusCode}`);
+ }
+ if (callback) callback();
+ });
+ postReq.write(JSON.stringify(postData));
+ postReq.on('error', () => {
+ postReq.end();
+ console.log('Lobby Update errored.');
+ });
+ postReq.setTimeout(3000, () => {
+ console.log('Lobby Update timed out.');
+ postReq.abort();
+ });
postReq.end();
- console.log('Lobby Update errored.');
- });
- postReq.setTimeout(3000, function() {
- console.log('Lobby Update timed out.');
- postReq.abort();
- });
- postReq.end();
- }
- catch (e) {
+ } catch (e) { }
+ this.createApiTimeout();
}
- this.createApiTimeout();
-};
-
-Room.prototype.createApiTimeout = function() {
- var that = this;
- clearTimeout(this.apiUpdateTimeout);
+ createApiTimeout() {
+ const that = this;
+ clearTimeout(this.apiUpdateTimeout);
- this.apiUpdateTimeout = setTimeout(function() {
- if (that.queue.currentsong && that.queue.currentdj) {
- that.updateLobbyServer(that.queue.currentsong, that.queue.currentdj ? that.queue.currentdj.user.getClientObj() : null);
- }
- else {
- that.updateLobbyServer(null, null);
- }
- }, 300000);
- return this.apiUpdateTimeout;
-};
+ this.apiUpdateTimeout = setTimeout(() => {
+ if (that.queue.currentsong && that.queue.currentdj) {
+ that.updateLobbyServer(that.queue.currentsong, that.queue.currentdj ? that.queue.currentdj.user.getClientObj() : null);
+ } else {
+ that.updateLobbyServer(null, null);
+ }
+ }, 300000);
+ return this.apiUpdateTimeout;
+ }
-Room.prototype.sockIsJoined = function(sock){
- if (this.attendeeList.indexOf(sock) > -1)
- return true;
- return false;
-};
+ sockIsJoined(sock) {
+ if (this.attendeeList.indexOf(sock) > -1) return true;
+ return false;
+ }
-Room.prototype.makeDbObject = function(){
- return this.data;
-};
+ makeDbObject() {
+ return this.data;
+ }
-Room.prototype.save = function(){
- DB.setRoom(this.roomInfo.slug, this.makeDbObject());
-};
+ save() {
+ DB.setRoom(this.roomInfo.slug, this.makeDbObject());
+ }
-Room.prototype.checkMakeOwner = function() {
- if (this.data.roles.owner && this.data.roles.owner.length == 0) {
- this.makeOwner();
+ checkMakeOwner() {
+ if (this.data.roles.owner && this.data.roles.owner.length === 0) {
+ this.makeOwner();
+ }
}
}
diff --git a/socketserver/socketserver.js b/socketserver/socketserver.js
index 78bd26e..55cb67d 100644
--- a/socketserver/socketserver.js
+++ b/socketserver/socketserver.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line
'use strict';
//Modules
var ws = require('ws');
diff --git a/webserver/app.js b/webserver/app.js
index 0cbe913..c0c4ea4 100644
--- a/webserver/app.js
+++ b/webserver/app.js
@@ -1,4 +1,3 @@
-// eslint-disable-next-line
'use strict';
const express = require('express');
const compression = require('compression');
@@ -12,83 +11,84 @@ const ejs = require('ejs');
const app = express();
let server2 = null;
let server = null;
+// eslint-disable-next-line
let socketServer = null;
-
/* SSL */
if (nconf.get('useSSL') && nconf.get('certificate') && nconf.get('certificate:key') && nconf.get('certificate:cert')) {
- const certificate = {
- key: fs.readFileSync(nconf.get('certificate:key')),
- cert: fs.readFileSync(nconf.get('certificate:cert')),
- };
+ const certificate = {
+ key: fs.readFileSync(nconf.get('certificate:key')),
+ cert: fs.readFileSync(nconf.get('certificate:cert')),
+ };
- server = https.createServer(certificate, app);
- if (nconf.get('webServer:redirectHTTP') && nconf.get('webServer:redirectPort') !== '') {
- server2 = http.createServer(app);
- }
+ server = https.createServer(certificate, app);
+ if (nconf.get('webServer:redirectHTTP') && nconf.get('webServer:redirectPort') !== '') {
+ server2 = http.createServer(app);
+ }
+} else {
+ server = http.createServer(app);
}
-else {
- server = http.createServer(app);
+
+if (nconf.get('webServer:redirectHTTP')) {
+ app.use((req, res, next) => {
+ if (!req.secure) {
+ return res.redirect(['https://', req.hostname, ':', nconf.get('webServer:port') || process.env.PORT, req.url].join(''));
+ }
+ next();
+ });
}
app.set('view engine', 'html');
+app.set('views', `${__dirname}/public`);
app.engine('html', ejs.renderFile);
-app.set('views', __dirname + '/public');
app.use(compression());
-if (nconf.get('webServer:redirectHTTP')) {
- app.use((req, res, next) => {
- if (!req.secure) {
- return res.redirect(['https://', req.hostname, ':', nconf.get('webServer:port') || process.env.PORT, req.url].join(''));
- }
- next();
- });
-}
-
app.get(['/', '/index.html'], (req, res) => {
- res.render('index', {
- tags: nconf.get('room:tags'),
- room: nconf.get('room'),
- });
+ res.render('index', {
+ tags: nconf.get('room:tags'),
+ room: nconf.get('room'),
+ scripts: nconf.get('room:scripts'),
+ });
});
-app.use(express.static(path.resolve(__dirname, 'public')));
+
app.use('/pads', express.static(path.resolve(__dirname, 'public')));
+app.use(express.static(path.resolve(__dirname, 'public')));
+
app.get('/config', (req, res) => {
- res.setHeader('Content-Type', 'application/javascript');
- res.send(fs.readFileSync(__dirname + '/public/lib/js/webconfig.js'));
+ res.setHeader('Content-Type', 'application/javascript');
+ res.send(fs.readFileSync(`${__dirname}/public/lib/js/webconfig.js`));
});
app.get('/api/room', (req, res) => {
- const roomInfo = {
- slug: nconf.get('room:slug'),
- name: nconf.get('room:name'),
- people: null,
- queue: null,
- media: null,
- };
- res.send(roomInfo);
+ const roomInfo = {
+ slug: nconf.get('room:slug'),
+ name: nconf.get('room:name'),
+ people: null,
+ queue: null,
+ media: null,
+ };
+ res.send(roomInfo);
});
-server.listen(nconf.get('webServer:port') || process.env.PORT, nconf.get('webServer:address') || process.env.IP, function(){
- const addr = server.address();
- console.log('Webserver listening at', addr.address + ':' + addr.port);
+server.listen(nconf.get('webServer:port') || process.env.PORT, nconf.get('webServer:address') || process.env.IP, () => {
+ const addr = server.address();
+ console.log('Webserver listening at', `${addr.address}:${addr.port}`);
});
if (server2 != null) {
- server2.listen(nconf.get('webServer:redirectPort') || 80, nconf.get('webServer:address') || process.env.IP, function(){
- const addr2 = server2.address();
- console.log('HTTP Webserver listening at', addr2.address + ':' + addr2.port);
- });
+ server2.listen(nconf.get('webServer:redirectPort') || 80, nconf.get('webServer:address') || process.env.IP, () => {
+ const addr2 = server2.address();
+ console.log('HTTP Webserver listening at', `${addr2.address}:${addr2.port}`);
+ });
}
-const setSocketServer = function (ss) {
- socketServer = ss;
+const setSocketServer = ss => {
+ socketServer = ss;
};
-
module.exports = {
- app,
- server,
- server2,
- setSocketServer,
+ app,
+ server,
+ server2,
+ setSocketServer,
};
diff --git a/webserver/public/index.html b/webserver/public/index.html
index ce04284..902e5bd 100644
--- a/webserver/public/index.html
+++ b/webserver/public/index.html
@@ -4,7 +4,7 @@
- <% if (tags) { %>
+ <% if (tags) { -%>
@@ -13,10 +13,15 @@
- <% } else { %>
- <% } %>
+ <% } else { -%>
+ <% } -%>
<%- room.name -%>
+ <% if (scripts.css) { -%>
+ <% scripts.css.forEach(function(url){ -%>
+
+ <% }); -%>
+ <% } -%>
@@ -757,5 +762,10 @@
+ <% if (scripts.js) { -%>
+ <% scripts.js.forEach(function(url){ -%>
+
+ <% }); -%>
+ <% } -%>