mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
Small bugfix, security patch
This commit is contained in:
@@ -125,7 +125,7 @@ class NotificationHandler {
|
|||||||
}, 1000 * this.reconnectRetryCount );
|
}, 1000 * this.reconnectRetryCount );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if ( res.status === 403 || res.status === 401 || res.status === 404 ) {
|
} else if ( res.status === 403 || res.status === 401 || res.status === 404 || res.status === 402 ) {
|
||||||
document.dispatchEvent( new Event( 'musicplayer:autherror' ) );
|
document.dispatchEvent( new Event( 'musicplayer:autherror' ) );
|
||||||
reject( 'ERR_UNAUTHORIZED' );
|
reject( 'ERR_UNAUTHORIZED' );
|
||||||
} else {
|
} else {
|
||||||
@@ -260,4 +260,4 @@ class NotificationHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NotificationHandler;
|
export default NotificationHandler;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@
|
|||||||
router.push( '/get' );
|
router.push( '/get' );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
} else if ( res.status === 404 ) {
|
} else if ( res.status === 402 ) {
|
||||||
userStore.setSubscriptionStatus( false );
|
userStore.setSubscriptionStatus( false );
|
||||||
router.push( '/get' );
|
router.push( '/get' );
|
||||||
sessionStorage.setItem( 'getRedirectionReason', 'notOwned' );
|
sessionStorage.setItem( 'getRedirectionReason', 'notOwned' );
|
||||||
@@ -166,4 +166,4 @@
|
|||||||
.player-hidden {
|
.player-hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
702
backend/eslint.config.mjs
Normal file
702
backend/eslint.config.mjs
Normal file
@@ -0,0 +1,702 @@
|
|||||||
|
import vue from 'eslint-plugin-vue';
|
||||||
|
import eslint from '@eslint/js';
|
||||||
|
import globals from 'globals';
|
||||||
|
import typescript from '@typescript-eslint/eslint-plugin';
|
||||||
|
import stylistic from '@stylistic/eslint-plugin';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
|
const style = {
|
||||||
|
'plugins': {
|
||||||
|
'@stylistic': stylistic,
|
||||||
|
'@stylistic/js': stylistic,
|
||||||
|
'@stylistic/ts': stylistic,
|
||||||
|
},
|
||||||
|
'files': [
|
||||||
|
'**/*.ts',
|
||||||
|
'**/*.js',
|
||||||
|
'**/*.mjs',
|
||||||
|
'**/*.cjs',
|
||||||
|
'**/*.tsx',
|
||||||
|
'**/*.jsx'
|
||||||
|
],
|
||||||
|
'rules': {
|
||||||
|
// Formatting
|
||||||
|
'@stylistic/array-bracket-newline': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'multiline': true,
|
||||||
|
'minItems': 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/array-bracket-spacing': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/array-element-newline': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'multiline': true,
|
||||||
|
'minItems': 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/arrow-parens': [
|
||||||
|
'error',
|
||||||
|
'as-needed'
|
||||||
|
],
|
||||||
|
'@stylistic/arrow-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'before': true,
|
||||||
|
'after': true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/block-spacing': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/brace-style': [
|
||||||
|
'error',
|
||||||
|
'1tbs'
|
||||||
|
],
|
||||||
|
'@stylistic/comma-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'before': false,
|
||||||
|
'after': true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/comma-style': [
|
||||||
|
'error',
|
||||||
|
'last'
|
||||||
|
],
|
||||||
|
'@stylistic/dot-location': [
|
||||||
|
'error',
|
||||||
|
'property'
|
||||||
|
],
|
||||||
|
'@stylistic/eol-last': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/function-call-spacing': [
|
||||||
|
'error',
|
||||||
|
'never'
|
||||||
|
],
|
||||||
|
'@stylistic/function-paren-newline': [
|
||||||
|
'error',
|
||||||
|
'multiline'
|
||||||
|
],
|
||||||
|
'@stylistic/function-call-argument-newline': [
|
||||||
|
'error',
|
||||||
|
'consistent'
|
||||||
|
],
|
||||||
|
'@stylistic/implicit-arrow-linebreak': [
|
||||||
|
'error',
|
||||||
|
'beside'
|
||||||
|
],
|
||||||
|
'@stylistic/indent': [
|
||||||
|
'error',
|
||||||
|
4
|
||||||
|
],
|
||||||
|
'@stylistic/key-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'beforeColon': false,
|
||||||
|
'afterColon': true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/keyword-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'before': true,
|
||||||
|
'after': true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/lines-between-class-members': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/max-len': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
'code': 90,
|
||||||
|
'comments': 100,
|
||||||
|
'ignoreComments': false,
|
||||||
|
'ignoreUrls': true,
|
||||||
|
'ignoreStrings': false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/new-parens': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/newline-per-chained-call': [ 'error' ],
|
||||||
|
'@stylistic/no-extra-parens': [
|
||||||
|
'error',
|
||||||
|
'all',
|
||||||
|
{
|
||||||
|
'nestedBinaryExpressions': false,
|
||||||
|
'ternaryOperandBinaryExpressions': false,
|
||||||
|
'ignoreJSX': 'multi-line',
|
||||||
|
'nestedConditionalExpressions': false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/no-extra-semi': 'error',
|
||||||
|
'@stylistic/no-floating-decimal': 'error',
|
||||||
|
'@stylistic/no-mixed-operators': 'error',
|
||||||
|
'@stylistic/no-mixed-spaces-and-tabs': 'error',
|
||||||
|
'@stylistic/no-multi-spaces': 'error',
|
||||||
|
'@stylistic/no-multiple-empty-lines': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'max': 3,
|
||||||
|
'maxEOF': 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/no-tabs': 'error',
|
||||||
|
'@stylistic/no-trailing-spaces': 'error',
|
||||||
|
'@stylistic/no-whitespace-before-property': 'error',
|
||||||
|
'@stylistic/object-curly-newline': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'multiline': true,
|
||||||
|
'minProperties': 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/object-curly-spacing': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/object-property-newline': 'error',
|
||||||
|
'@stylistic/operator-linebreak': [
|
||||||
|
'error',
|
||||||
|
'before'
|
||||||
|
],
|
||||||
|
'@stylistic/one-var-declaration-per-line': 'error',
|
||||||
|
'@stylistic/padded-blocks': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'blocks': 'never',
|
||||||
|
'classes': 'always',
|
||||||
|
'switches': 'never',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
// Padding lines. The most in-depth part of this config
|
||||||
|
'@stylistic/padding-line-between-statements': [
|
||||||
|
'error',
|
||||||
|
// Variables, Constants
|
||||||
|
{
|
||||||
|
'blankLine': 'never',
|
||||||
|
'prev': 'var',
|
||||||
|
'next': 'var'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'never',
|
||||||
|
'prev': 'let',
|
||||||
|
'next': 'let'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'never',
|
||||||
|
'prev': 'const',
|
||||||
|
'next': 'const'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'var',
|
||||||
|
'next': [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'break',
|
||||||
|
'cjs-export',
|
||||||
|
'cjs-import',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'directive',
|
||||||
|
'do',
|
||||||
|
'empty',
|
||||||
|
'export',
|
||||||
|
'expression',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'iife',
|
||||||
|
'import',
|
||||||
|
'let',
|
||||||
|
'return',
|
||||||
|
'switch',
|
||||||
|
'throw',
|
||||||
|
'try',
|
||||||
|
'var',
|
||||||
|
'with'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'let',
|
||||||
|
'next': [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'break',
|
||||||
|
'cjs-export',
|
||||||
|
'cjs-import',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'directive',
|
||||||
|
'do',
|
||||||
|
'empty',
|
||||||
|
'export',
|
||||||
|
'expression',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'iife',
|
||||||
|
'import',
|
||||||
|
'return',
|
||||||
|
'switch',
|
||||||
|
'throw',
|
||||||
|
'try',
|
||||||
|
'var',
|
||||||
|
'while',
|
||||||
|
'with'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'const',
|
||||||
|
'next': [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'break',
|
||||||
|
'cjs-export',
|
||||||
|
'cjs-import',
|
||||||
|
'class',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'directive',
|
||||||
|
'do',
|
||||||
|
'empty',
|
||||||
|
'export',
|
||||||
|
'expression',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'iife',
|
||||||
|
'import',
|
||||||
|
'let',
|
||||||
|
'return',
|
||||||
|
'switch',
|
||||||
|
'throw',
|
||||||
|
'try',
|
||||||
|
'var',
|
||||||
|
'while',
|
||||||
|
'with'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// Import
|
||||||
|
{
|
||||||
|
'blankLine': 'never',
|
||||||
|
'prev': 'import',
|
||||||
|
'next': 'import'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'never',
|
||||||
|
'prev': 'cjs-import',
|
||||||
|
'next': 'cjs-import'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'break',
|
||||||
|
'cjs-export',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'directive',
|
||||||
|
'do',
|
||||||
|
'empty',
|
||||||
|
'export',
|
||||||
|
'expression',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'iife',
|
||||||
|
'let',
|
||||||
|
'return',
|
||||||
|
'switch',
|
||||||
|
'throw',
|
||||||
|
'try',
|
||||||
|
'var',
|
||||||
|
'while',
|
||||||
|
'with'
|
||||||
|
],
|
||||||
|
'next': 'cjs-import'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'cjs-import',
|
||||||
|
'next': [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'break',
|
||||||
|
'cjs-export',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'directive',
|
||||||
|
'do',
|
||||||
|
'empty',
|
||||||
|
'export',
|
||||||
|
'expression',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'iife',
|
||||||
|
'let',
|
||||||
|
'return',
|
||||||
|
'switch',
|
||||||
|
'throw',
|
||||||
|
'try',
|
||||||
|
'var',
|
||||||
|
'while',
|
||||||
|
'with'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'break',
|
||||||
|
'cjs-export',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'directive',
|
||||||
|
'do',
|
||||||
|
'empty',
|
||||||
|
'export',
|
||||||
|
'expression',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'iife',
|
||||||
|
'let',
|
||||||
|
'return',
|
||||||
|
'switch',
|
||||||
|
'throw',
|
||||||
|
'try',
|
||||||
|
'var',
|
||||||
|
'while',
|
||||||
|
'with'
|
||||||
|
],
|
||||||
|
'next': 'import'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'import',
|
||||||
|
'next': [
|
||||||
|
'block',
|
||||||
|
'block-like',
|
||||||
|
'break',
|
||||||
|
'cjs-export',
|
||||||
|
'class',
|
||||||
|
'const',
|
||||||
|
'continue',
|
||||||
|
'debugger',
|
||||||
|
'directive',
|
||||||
|
'do',
|
||||||
|
'empty',
|
||||||
|
'export',
|
||||||
|
'expression',
|
||||||
|
'for',
|
||||||
|
'function',
|
||||||
|
'if',
|
||||||
|
'iife',
|
||||||
|
'let',
|
||||||
|
'return',
|
||||||
|
'switch',
|
||||||
|
'throw',
|
||||||
|
'try',
|
||||||
|
'var',
|
||||||
|
'while',
|
||||||
|
'with'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// If
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'if'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'if',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// For
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'for'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'for',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// While
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'while'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'while',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// Functions
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'function'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'function',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// Block Statements
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'block-like'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'block-like',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// Switch
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'switch'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'switch',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// Try-Catch
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'try'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'try',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// Throw
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'throw'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'throw',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// Return
|
||||||
|
{
|
||||||
|
'blankLine': 'never',
|
||||||
|
'prev': 'return',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'return'
|
||||||
|
},
|
||||||
|
// Export
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'export'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'export',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'cjs-export'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'cjs-export',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
// Classes
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': '*',
|
||||||
|
'next': 'class'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'blankLine': 'always',
|
||||||
|
'prev': 'class',
|
||||||
|
'next': '*'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@stylistic/quote-props': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/quotes': [
|
||||||
|
'error',
|
||||||
|
'single'
|
||||||
|
],
|
||||||
|
'@stylistic/rest-spread-spacing': [
|
||||||
|
'error',
|
||||||
|
'never'
|
||||||
|
],
|
||||||
|
'@stylistic/semi': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/semi-spacing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'before': false,
|
||||||
|
'after': true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/semi-style': [
|
||||||
|
'error',
|
||||||
|
'last'
|
||||||
|
],
|
||||||
|
'@stylistic/space-before-blocks': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/space-before-function-paren': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/space-in-parens': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/space-infix-ops': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'int32Hint': false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/space-unary-ops': 'error',
|
||||||
|
'@stylistic/spaced-comment': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/template-curly-spacing': [
|
||||||
|
'error',
|
||||||
|
'always'
|
||||||
|
],
|
||||||
|
'@stylistic/switch-colon-spacing': 'error',
|
||||||
|
'@stylistic/wrap-iife': [
|
||||||
|
'error',
|
||||||
|
'inside'
|
||||||
|
],
|
||||||
|
'@stylistic/wrap-regex': 'error',
|
||||||
|
'@stylistic/ts/type-annotation-spacing': 'error',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {import('eslint').Linter.Config} */
|
||||||
|
export default tseslint.config(
|
||||||
|
// Base JavaScript rules
|
||||||
|
eslint.configs.recommended,
|
||||||
|
tseslint.configs.recommended,
|
||||||
|
style,
|
||||||
|
|
||||||
|
// Vue support (including TS and JSX inside SFCs)
|
||||||
|
{
|
||||||
|
'files': [ '**/*.vue' ],
|
||||||
|
'languageOptions': {
|
||||||
|
'sourceType': 'module',
|
||||||
|
'ecmaVersion': 'latest',
|
||||||
|
'globals': globals.browser,
|
||||||
|
'parserOptions': {
|
||||||
|
'parser': tseslint.parser,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'plugins': {
|
||||||
|
'vue': vue,
|
||||||
|
'@stylistic': stylistic,
|
||||||
|
'@stylistic/js': stylistic,
|
||||||
|
'@stylistic/ts': stylistic,
|
||||||
|
'@typescript-eslint': typescript,
|
||||||
|
},
|
||||||
|
'extends': [
|
||||||
|
eslint.configs.recommended,
|
||||||
|
...vue.configs['flat/recommended']
|
||||||
|
],
|
||||||
|
'rules': {
|
||||||
|
...typescript.configs.recommended.rules,
|
||||||
|
...style.rules,
|
||||||
|
|
||||||
|
// Vue specific rules
|
||||||
|
'@stylistic/indent': 'off',
|
||||||
|
'vue/html-indent': [
|
||||||
|
'error',
|
||||||
|
4
|
||||||
|
],
|
||||||
|
'vue/html-comment-indent': [
|
||||||
|
'error',
|
||||||
|
4
|
||||||
|
],
|
||||||
|
'vue/script-indent': [
|
||||||
|
'error',
|
||||||
|
4,
|
||||||
|
{
|
||||||
|
'baseIndent': 1,
|
||||||
|
'switchCase': 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'vue/html-self-closing': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'html': {
|
||||||
|
'void': 'never',
|
||||||
|
'normal': 'never',
|
||||||
|
'component': 'always'
|
||||||
|
},
|
||||||
|
'svg': 'always',
|
||||||
|
'math': 'never'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'vue/max-attributes-per-line': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'singleline': 3,
|
||||||
|
'multiline': 1,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
2110
backend/package-lock.json
generated
2110
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,12 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/simplePCBuilding/MusicPlayerV2#readme",
|
"homepage": "https://github.com/simplePCBuilding/MusicPlayerV2#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.29.0",
|
||||||
|
"@stylistic/eslint-plugin": "^5.0.0",
|
||||||
"@types/express-session": "^1.18.0",
|
"@types/express-session": "^1.18.0",
|
||||||
"typescript": "^5.4.5"
|
"eslint-plugin-vue": "^10.2.0",
|
||||||
|
"typescript": "^5.4.5",
|
||||||
|
"typescript-eslint": "^8.35.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/body-parser": "^1.19.5",
|
"@types/body-parser": "^1.19.5",
|
||||||
|
|||||||
@@ -5,56 +5,77 @@ import jwt from 'jsonwebtoken';
|
|||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import account from './account';
|
import account from './account';
|
||||||
import sdk from 'oauth-janishutz-client-server';
|
import sdk from 'oauth-janishutz-client-server';
|
||||||
import { createServer } from 'node:http';
|
import {
|
||||||
import { Server } from 'socket.io';
|
createServer
|
||||||
|
} from 'node:http';
|
||||||
|
import {
|
||||||
|
Server
|
||||||
|
} from 'socket.io';
|
||||||
import crypto from 'node:crypto';
|
import crypto from 'node:crypto';
|
||||||
import type { Room, Song } from './definitions';
|
import type {
|
||||||
|
Room, Song
|
||||||
|
} from './definitions';
|
||||||
import storeSDK from 'store.janishutz.com-sdk';
|
import storeSDK from 'store.janishutz.com-sdk';
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
|
|
||||||
const isFossVersion = true;
|
const isFossVersion = true;
|
||||||
|
|
||||||
declare let __dirname: string | undefined
|
declare let __dirname: string | undefined;
|
||||||
if ( typeof( __dirname ) === 'undefined' ) {
|
|
||||||
|
if ( typeof __dirname === 'undefined' ) {
|
||||||
__dirname = path.resolve( path.dirname( '' ) );
|
__dirname = path.resolve( path.dirname( '' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Change config file, as well as in main.ts, index.html, oauth, if deploying there
|
// TODO: Change config file, as well as in main.ts, index.html, oauth, if deploying there
|
||||||
// const sdkConfig = JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/sdk.config.testing.json' ) ) );
|
// const sdkConfig = JSON.parse( fs.readFileSync( path.join(
|
||||||
const sdkConfig = JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/sdk.config.secret.json' ) ) );
|
// __dirname,
|
||||||
|
// '/config/sdk.config.testing.json'
|
||||||
|
// ) ).toString() );
|
||||||
|
const sdkConfig = JSON.parse( fs.readFileSync( path.join(
|
||||||
|
__dirname,
|
||||||
|
'/config/sdk.config.secret.json'
|
||||||
|
) ).toString() );
|
||||||
|
|
||||||
const run = () => {
|
const run = () => {
|
||||||
let app = express();
|
const app = express();
|
||||||
app.use( cors( {
|
|
||||||
credentials: true,
|
app.use( cors( {
|
||||||
origin: true
|
'credentials': true,
|
||||||
|
'origin': true
|
||||||
} ) );
|
} ) );
|
||||||
|
|
||||||
if ( !isFossVersion ) {
|
if ( !isFossVersion ) {
|
||||||
// storeSDK.configure( JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/store-sdk.config.testing.json' ) ) ) );
|
// storeSDK.configure( JSON.parse( fs.readFileSync( path.join(
|
||||||
storeSDK.configure( JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/store-sdk.config.secret.json' ) ) ) );
|
// __dirname,
|
||||||
|
// '/config/store-sdk.config.testing.json'
|
||||||
|
// ) ).toString() ) );
|
||||||
|
storeSDK.configure( JSON.parse( fs.readFileSync( path.join(
|
||||||
|
__dirname,
|
||||||
|
'/config/store-sdk.config.secret.json'
|
||||||
|
) ).toString() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
const httpServer = createServer( app );
|
const httpServer = createServer( app );
|
||||||
|
|
||||||
if ( !isFossVersion ) {
|
if ( !isFossVersion ) {
|
||||||
// Load id.janishutz.com SDK and allow signing in
|
// Load id.janishutz.com SDK and allow signing in
|
||||||
sdk.routes( app, ( uid: string ) => {
|
sdk.routes( app, ( uid: string ) => {
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
account.checkUser( uid ).then( stat => {
|
account.checkUser( uid ).then( stat => {
|
||||||
resolve( stat );
|
resolve( stat );
|
||||||
} ).catch( e => {
|
} )
|
||||||
reject( e );
|
.catch( e => {
|
||||||
} );
|
reject( e );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
},
|
}, ( uid: string, email: string, username: string ) => {
|
||||||
( uid: string, email: string, username: string ) => {
|
|
||||||
return new Promise( ( resolve, reject ) => {
|
return new Promise( ( resolve, reject ) => {
|
||||||
account.createUser( uid, username, email ).then( stat => {
|
account.createUser( uid, username, email ).then( stat => {
|
||||||
resolve( stat );
|
resolve( stat );
|
||||||
} ).catch( e => {
|
} )
|
||||||
reject( e );
|
.catch( e => {
|
||||||
} );
|
reject( e );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
}, sdkConfig );
|
}, sdkConfig );
|
||||||
}
|
}
|
||||||
@@ -65,89 +86,118 @@ const run = () => {
|
|||||||
}
|
}
|
||||||
const socketData: SocketData = {};
|
const socketData: SocketData = {};
|
||||||
const io = new Server( httpServer, {
|
const io = new Server( httpServer, {
|
||||||
cors: {
|
'cors': {
|
||||||
origin: true,
|
'origin': true,
|
||||||
credentials: true,
|
'credentials': true,
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
io.on( 'connection', ( socket ) => {
|
io.on( 'connection', socket => {
|
||||||
socket.on( 'create-room', ( room: { name: string, token: string }, cb: ( res: { status: boolean, msg: string } ) => void ) => {
|
socket.on( 'create-room', ( room: {
|
||||||
|
'name': string,
|
||||||
|
'token': string
|
||||||
|
}, cb: ( res: {
|
||||||
|
'status': boolean,
|
||||||
|
'msg': string
|
||||||
|
} ) => void ) => {
|
||||||
if ( socketData[ room.name ] ) {
|
if ( socketData[ room.name ] ) {
|
||||||
if ( room.token === socketData[ room.name ].roomToken ) {
|
if ( room.token === socketData[ room.name ].roomToken ) {
|
||||||
socket.join( room.name );
|
socket.join( room.name );
|
||||||
cb( {
|
cb( {
|
||||||
status: true,
|
'status': true,
|
||||||
msg: 'ADDED_TO_ROOM'
|
'msg': 'ADDED_TO_ROOM'
|
||||||
} );
|
} );
|
||||||
} else {
|
} else {
|
||||||
cb( {
|
cb( {
|
||||||
status: false,
|
'status': false,
|
||||||
msg: 'ERR_TOKEN_INVALID'
|
'msg': 'ERR_TOKEN_INVALID'
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cb( {
|
cb( {
|
||||||
status: false,
|
'status': false,
|
||||||
msg: 'ERR_NAME_INVALID'
|
'msg': 'ERR_NAME_INVALID'
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
socket.on( 'delete-room', ( room: { name: string, token: string }, cb: ( res: { status: boolean, msg: string } ) => void ) => {
|
socket.on( 'delete-room', ( room: {
|
||||||
|
'name': string,
|
||||||
|
'token': string
|
||||||
|
}, cb: ( res: {
|
||||||
|
'status': boolean,
|
||||||
|
'msg': string
|
||||||
|
} ) => void ) => {
|
||||||
if ( socketData[ room.name ] ) {
|
if ( socketData[ room.name ] ) {
|
||||||
if ( room.token === socketData[ room.name ].roomToken ) {
|
if ( room.token === socketData[ room.name ].roomToken ) {
|
||||||
socket.leave( room.name );
|
socket.leave( room.name );
|
||||||
socket.to( room.name ).emit( 'delete-share', room.name );
|
socket.to( room.name ).emit( 'delete-share', room.name );
|
||||||
socketData[ room.name ] = undefined;
|
socketData[ room.name ] = undefined;
|
||||||
cb( {
|
cb( {
|
||||||
status: true,
|
'status': true,
|
||||||
msg: 'ROOM_DELETED'
|
'msg': 'ROOM_DELETED'
|
||||||
} );
|
} );
|
||||||
} else {
|
} else {
|
||||||
cb( {
|
cb( {
|
||||||
status: false,
|
'status': false,
|
||||||
msg: 'ERR_TOKEN_INVALID'
|
'msg': 'ERR_TOKEN_INVALID'
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cb( {
|
cb( {
|
||||||
status: false,
|
'status': false,
|
||||||
msg: 'ERR_NAME_INVALID'
|
'msg': 'ERR_NAME_INVALID'
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
socket.on( 'join-room', ( room: string, cb: ( res: { status: boolean, msg: string, data?: { playbackStatus: boolean, playbackStart: number, playlist: Song[], playlistIndex: number, useAntiTamper: boolean } } ) => void ) => {
|
socket.on( 'join-room', ( room: string, cb: ( res: {
|
||||||
|
'status': boolean,
|
||||||
|
'msg': string,
|
||||||
|
'data'?: {
|
||||||
|
'playbackStatus': boolean,
|
||||||
|
'playbackStart': number,
|
||||||
|
'playlist': Song[],
|
||||||
|
'playlistIndex': number,
|
||||||
|
'useAntiTamper': boolean
|
||||||
|
}
|
||||||
|
} ) => void ) => {
|
||||||
if ( socketData[ room ] ) {
|
if ( socketData[ room ] ) {
|
||||||
socket.join( room );
|
socket.join( room );
|
||||||
cb( {
|
cb( {
|
||||||
data: {
|
'data': {
|
||||||
playbackStart: socketData[ room ].playbackStart,
|
'playbackStart': socketData[ room ].playbackStart,
|
||||||
playbackStatus: socketData[ room ].playbackStatus,
|
'playbackStatus': socketData[ room ].playbackStatus,
|
||||||
playlist: socketData[ room ].playlist,
|
'playlist': socketData[ room ].playlist,
|
||||||
playlistIndex: socketData[ room ].playlistIndex,
|
'playlistIndex': socketData[ room ].playlistIndex,
|
||||||
useAntiTamper: socketData[ room ].useAntiTamper,
|
'useAntiTamper': socketData[ room ].useAntiTamper,
|
||||||
},
|
},
|
||||||
msg: 'STATUS_OK',
|
'msg': 'STATUS_OK',
|
||||||
status: true,
|
'status': true,
|
||||||
} )
|
} );
|
||||||
} else {
|
} else {
|
||||||
cb( {
|
cb( {
|
||||||
msg: 'ERR_NO_ROOM_WITH_THIS_ID',
|
'msg': 'ERR_NO_ROOM_WITH_THIS_ID',
|
||||||
status: false,
|
'status': false,
|
||||||
} );
|
} );
|
||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
socket.on( 'tampering', ( data: { msg: string, roomName: string } ) => {
|
socket.on( 'tampering', ( data: {
|
||||||
|
'msg': string,
|
||||||
|
'roomName': string
|
||||||
|
} ) => {
|
||||||
if ( data.roomName ) {
|
if ( data.roomName ) {
|
||||||
socket.to( data.roomName ).emit( 'tampering-msg', data.msg );
|
socket.to( data.roomName ).emit( 'tampering-msg', data.msg );
|
||||||
}
|
}
|
||||||
} )
|
} );
|
||||||
|
|
||||||
socket.on( 'playlist-update', ( data: { roomName: string, roomToken: string, data: Song[] } ) => {
|
socket.on( 'playlist-update', ( data: {
|
||||||
|
'roomName': string,
|
||||||
|
'roomToken': string,
|
||||||
|
'data': Song[]
|
||||||
|
} ) => {
|
||||||
if ( socketData[ data.roomName ] ) {
|
if ( socketData[ data.roomName ] ) {
|
||||||
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
||||||
if ( socketData[ data.roomName ].playlist !== data.data ) {
|
if ( socketData[ data.roomName ].playlist !== data.data ) {
|
||||||
@@ -158,7 +208,11 @@ const run = () => {
|
|||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
socket.on( 'playback-update', ( data: { roomName: string, roomToken: string, data: boolean } ) => {
|
socket.on( 'playback-update', ( data: {
|
||||||
|
'roomName': string,
|
||||||
|
'roomToken': string,
|
||||||
|
'data': boolean
|
||||||
|
} ) => {
|
||||||
if ( socketData[ data.roomName ] ) {
|
if ( socketData[ data.roomName ] ) {
|
||||||
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
||||||
socketData[ data.roomName ].playbackStatus = data.data;
|
socketData[ data.roomName ].playbackStatus = data.data;
|
||||||
@@ -167,7 +221,11 @@ const run = () => {
|
|||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
socket.on( 'playlist-index-update', ( data: { roomName: string, roomToken: string, data: number } ) => {
|
socket.on( 'playlist-index-update', ( data: {
|
||||||
|
'roomName': string,
|
||||||
|
'roomToken': string,
|
||||||
|
'data': number
|
||||||
|
} ) => {
|
||||||
if ( socketData[ data.roomName ] ) {
|
if ( socketData[ data.roomName ] ) {
|
||||||
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
||||||
socketData[ data.roomName ].playlistIndex = data.data;
|
socketData[ data.roomName ].playlistIndex = data.data;
|
||||||
@@ -176,7 +234,11 @@ const run = () => {
|
|||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
socket.on( 'playback-start-update', ( data: { roomName: string, roomToken: string, data: number } ) => {
|
socket.on( 'playback-start-update', ( data: {
|
||||||
|
'roomName': string,
|
||||||
|
'roomToken': string,
|
||||||
|
'data': number
|
||||||
|
} ) => {
|
||||||
if ( socketData[ data.roomName ] ) {
|
if ( socketData[ data.roomName ] ) {
|
||||||
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
if ( socketData[ data.roomName ].roomToken === data.roomToken ) {
|
||||||
socketData[ data.roomName ].playbackStart = data.data;
|
socketData[ data.roomName ].playbackStart = data.data;
|
||||||
@@ -187,7 +249,7 @@ const run = () => {
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ROUTES FOR SERVER SENT EVENTS VERSION
|
ROUTES FOR SERVER SENT EVENTS VERSION
|
||||||
*/
|
*/
|
||||||
// Connected clients have their session ID as key
|
// Connected clients have their session ID as key
|
||||||
@@ -196,8 +258,8 @@ const run = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface SocketClient {
|
interface SocketClient {
|
||||||
response: express.Response;
|
'response': express.Response;
|
||||||
room: string;
|
'room': string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ClientReferenceList {
|
interface ClientReferenceList {
|
||||||
@@ -211,240 +273,373 @@ const run = () => {
|
|||||||
const connectedClients: SocketClientList = {};
|
const connectedClients: SocketClientList = {};
|
||||||
const clientReference: ClientReferenceList = {};
|
const clientReference: ClientReferenceList = {};
|
||||||
|
|
||||||
app.get( '/socket/connection', ( request: express.Request, response: express.Response ) => {
|
app.get(
|
||||||
if ( request.query.room ) {
|
'/socket/connection',
|
||||||
if ( socketData[ String( request.query.room ) ] ) {
|
( request: express.Request, response: express.Response ) => {
|
||||||
response.writeHead( 200, {
|
if ( request.query.room ) {
|
||||||
'Content-Type': 'text/event-stream',
|
if ( socketData[ String( request.query.room ) ] ) {
|
||||||
'Cache-Control': 'no-cache',
|
response.writeHead( 200, {
|
||||||
'Connection': 'keep-alive',
|
'Content-Type': 'text/event-stream',
|
||||||
} );
|
'Cache-Control': 'no-cache',
|
||||||
response.status( 200 );
|
'Connection': 'keep-alive',
|
||||||
response.flushHeaders();
|
} );
|
||||||
response.write( `data: ${ JSON.stringify( { 'type': 'basics', 'data': socketData[ String( request.query.room ) ] } ) }\n\n` );
|
response.status( 200 );
|
||||||
const sid = sdk.getSessionID( request );
|
response.flushHeaders();
|
||||||
if ( sdk.checkAuth( request ) ) {
|
response.write( `data: ${ JSON.stringify( {
|
||||||
importantClients[ sid ] = { 'response': response, 'room': String( request.query.room ) };
|
'type': 'basics',
|
||||||
}
|
'data': socketData[ String( request.query.room ) ]
|
||||||
connectedClients[ sid ] = { 'response': response, 'room': String( request.query.room ) };
|
} ) }\n\n` );
|
||||||
if ( !clientReference[ String( request.query.room ) ] ) {
|
const sid = sdk.getSessionID( request );
|
||||||
clientReference[ String( request.query.room ) ] = [];
|
|
||||||
}
|
|
||||||
if ( !clientReference[ String( request.query.room ) ].includes( sid ) ) {
|
|
||||||
clientReference[ String( request.query.room ) ].push( sid );
|
|
||||||
}
|
|
||||||
request.on( 'close', () => {
|
|
||||||
try {
|
|
||||||
importantClients[ sid ] = undefined;
|
|
||||||
} catch ( e ) { /* empty */ }
|
|
||||||
const cl = clientReference[ String( request.query.room ) ];
|
|
||||||
for ( let c in cl ) {
|
|
||||||
if ( cl[ c ] === sid ) {
|
|
||||||
cl.splice( parseInt( c ), 1 );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
connectedClients[ sid ] = undefined;
|
|
||||||
} );
|
|
||||||
} else {
|
|
||||||
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
response.status( 404 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
app.get( '/socket/getData', ( request: express.Request, response: express.Response ) => {
|
|
||||||
if ( request.query.room ) {
|
|
||||||
response.send( socketData[ String( request.query.room ) ] );
|
|
||||||
} else {
|
|
||||||
response.status( 400 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
app.get( '/socket/joinRoom', ( request: express.Request, response: express.Response ) => {
|
|
||||||
if ( request.query.room ) {
|
|
||||||
if ( socketData[ String( request.query.room ) ] ) {
|
|
||||||
response.send( 'ok' );
|
|
||||||
} else {
|
|
||||||
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
response.status( 404 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
app.post( '/socket/update', bodyParser.json(), ( request: express.Request, response: express.Response ) => {
|
|
||||||
if ( socketData[ request.body.roomName ] ) {
|
|
||||||
if ( request.body.event === 'tampering' ) {
|
|
||||||
const clients = clientReference[ request.body.roomName ];
|
|
||||||
for ( let client in clients ) {
|
|
||||||
if ( importantClients[ clients[ client ] ] ) {
|
|
||||||
importantClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'type': 'tampering-msg', 'data': true } ) + '\n\n' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.send( 'ok' );
|
|
||||||
} else {
|
|
||||||
if ( socketData[ request.body.roomName ].roomToken === request.body.roomToken ) {
|
|
||||||
let send = false;
|
|
||||||
let update = '';
|
|
||||||
|
|
||||||
if ( request.body.event === 'playback-start-update' ) {
|
if ( sdk.checkAuth( request ) ) {
|
||||||
send = true;
|
importantClients[ sid ] = {
|
||||||
update = 'playback-start';
|
'response': response,
|
||||||
socketData[ request.body.roomName ].playbackStart = request.body.data;
|
'room': String( request.query.room )
|
||||||
} else if ( request.body.event === 'playback-update' ) {
|
};
|
||||||
send = true;
|
|
||||||
update = 'playback';
|
|
||||||
socketData[ request.body.roomName ].playbackStatus = request.body.data;
|
|
||||||
} else if ( request.body.event === 'playlist-update' ) {
|
|
||||||
send = true;
|
|
||||||
update = 'playlist';
|
|
||||||
socketData[ request.body.roomName ].playlist = request.body.data;
|
|
||||||
} else if ( request.body.event === 'playlist-index-update' ) {
|
|
||||||
send = true;
|
|
||||||
update = 'playlist-index';
|
|
||||||
socketData[ request.body.roomName ].playlistIndex = request.body.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( send ) {
|
connectedClients[ sid ] = {
|
||||||
const clients = clientReference[ request.body.roomName ];
|
'response': response,
|
||||||
for ( let client in clients ) {
|
'room': String( request.query.room )
|
||||||
if ( connectedClients[ clients[ client ] ] ) {
|
};
|
||||||
connectedClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'type': update, 'data': request.body.data } ) + '\n\n' );
|
|
||||||
|
if ( !clientReference[ String( request.query.room ) ] ) {
|
||||||
|
clientReference[ String( request.query.room ) ] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !clientReference[ String( request.query.room ) ]
|
||||||
|
.includes( sid ) ) {
|
||||||
|
clientReference[ String( request.query.room ) ].push( sid );
|
||||||
|
}
|
||||||
|
|
||||||
|
request.on( 'close', () => {
|
||||||
|
try {
|
||||||
|
importantClients[ sid ] = undefined;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
} catch ( e ) { /* empty */ }
|
||||||
|
|
||||||
|
const cl = clientReference[ String( request.query.room ) ];
|
||||||
|
|
||||||
|
for ( const c in cl ) {
|
||||||
|
if ( cl[ c ] === sid ) {
|
||||||
|
cl.splice( parseInt( c ), 1 );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
response.send( 'ok' );
|
|
||||||
} else {
|
|
||||||
response.status( 404 ).send( 'ERR_CANNOT_SEND' );
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
response.status( 403 ).send( 'ERR_UNAUTHORIZED' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
response.status( 400 ).send( 'ERR_WRONG_REQUEST' );
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
|
connectedClients[ sid ] = undefined;
|
||||||
|
} );
|
||||||
app.post( '/socket/deleteRoom', bodyParser.json(), ( request: express.Request, response: express.Response ) => {
|
|
||||||
if ( request.body.roomName ) {
|
|
||||||
if ( socketData[ request.body.roomName ] ) {
|
|
||||||
if ( socketData[ request.body.roomName ].roomToken === request.body.roomToken ) {
|
|
||||||
socketData[ request.body.roomName ] = undefined;
|
|
||||||
const clients = clientReference[ request.body.roomName ];
|
|
||||||
for ( let client in clients ) {
|
|
||||||
if ( connectedClients[ clients[ client ] ] ) {
|
|
||||||
connectedClients[ clients[ client ] ].response.write( 'data: ' + JSON.stringify( { 'type': 'delete-share', 'data': true } ) + '\n\n' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
response.send( 403 ).send( 'ERR_UNAUTHORIZED' );
|
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
response.status( 404 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
response.status( 400 ).send( 'ERR_NO_ROOM_NAME' );
|
|
||||||
}
|
}
|
||||||
} );
|
);
|
||||||
|
|
||||||
|
app.get(
|
||||||
|
'/socket/getData',
|
||||||
|
( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( request.query.room ) {
|
||||||
|
response.send( socketData[ String( request.query.room ) ] );
|
||||||
|
} else {
|
||||||
|
response.status( 400 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
app.get(
|
||||||
|
'/socket/joinRoom',
|
||||||
|
( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( request.query.room ) {
|
||||||
|
if ( socketData[ String( request.query.room ) ] ) {
|
||||||
|
response.send( 'ok' );
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_NO_ROOM_SPECIFIED' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
app.post(
|
||||||
|
'/socket/update',
|
||||||
|
bodyParser.json(),
|
||||||
|
( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( socketData[ request.body.roomName ] ) {
|
||||||
|
if ( request.body.event === 'tampering' ) {
|
||||||
|
const clients = clientReference[ request.body.roomName ];
|
||||||
|
|
||||||
|
for ( const client in clients ) {
|
||||||
|
if ( importantClients[ clients[ client ] ] ) {
|
||||||
|
importantClients[ clients[ client ] ]
|
||||||
|
.response.write( 'data: ' + JSON.stringify( {
|
||||||
|
'type': 'tampering-msg',
|
||||||
|
'data': true
|
||||||
|
} ) + '\n\n' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.send( 'ok' );
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
socketData[ request.body.roomName ].roomToken
|
||||||
|
=== request.body.roomToken
|
||||||
|
) {
|
||||||
|
let send = false;
|
||||||
|
let update = '';
|
||||||
|
|
||||||
|
if ( request.body.event === 'playback-start-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playback-start';
|
||||||
|
socketData[ request.body.roomName ]
|
||||||
|
.playbackStart = request.body.data;
|
||||||
|
} else if ( request.body.event === 'playback-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playback';
|
||||||
|
socketData[ request.body.roomName ]
|
||||||
|
.playbackStatus = request.body.data;
|
||||||
|
} else if ( request.body.event === 'playlist-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playlist';
|
||||||
|
socketData[ request.body.roomName ]
|
||||||
|
.playlist = request.body.data;
|
||||||
|
} else if ( request.body.event === 'playlist-index-update' ) {
|
||||||
|
send = true;
|
||||||
|
update = 'playlist-index';
|
||||||
|
socketData[ request.body.roomName ]
|
||||||
|
.playlistIndex = request.body.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( send ) {
|
||||||
|
const clients = clientReference[ request.body.roomName ];
|
||||||
|
|
||||||
|
for ( const client in clients ) {
|
||||||
|
if ( connectedClients[ clients[ client ] ] ) {
|
||||||
|
connectedClients[ clients[ client ] ]
|
||||||
|
.response.write( 'data: ' + JSON.stringify( {
|
||||||
|
'type': update,
|
||||||
|
'data': request.body.data
|
||||||
|
} ) + '\n\n' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
response.send( 'ok' );
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_CANNOT_SEND' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 403 ).send( 'ERR_UNAUTHORIZED' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 400 ).send( 'ERR_WRONG_REQUEST' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
app.post(
|
||||||
|
'/socket/deleteRoom',
|
||||||
|
bodyParser.json(),
|
||||||
|
( request: express.Request, response: express.Response ) => {
|
||||||
|
if ( request.body.roomName ) {
|
||||||
|
if ( socketData[ request.body.roomName ] ) {
|
||||||
|
if (
|
||||||
|
socketData[ request.body.roomName ].roomToken
|
||||||
|
=== request.body.roomToken
|
||||||
|
) {
|
||||||
|
socketData[ request.body.roomName ] = undefined;
|
||||||
|
const clients = clientReference[ request.body.roomName ];
|
||||||
|
|
||||||
|
for ( const client in clients ) {
|
||||||
|
if ( connectedClients[ clients[ client ] ] ) {
|
||||||
|
connectedClients[ clients[ client ] ]
|
||||||
|
.response.write( 'data: ' + JSON.stringify( {
|
||||||
|
'type': 'delete-share',
|
||||||
|
'data': true
|
||||||
|
} ) + '\n\n' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.send( 403 ).send( 'ERR_UNAUTHORIZED' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 404 ).send( 'ERR_ROOM_NOT_FOUND' );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 400 ).send( 'ERR_NO_ROOM_NAME' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
GENERAL ROUTES
|
GENERAL ROUTES
|
||||||
*/
|
*/
|
||||||
app.get( '/', ( request: express.Request, response: express.Response ) => {
|
app.get( '/', ( _request: express.Request, response: express.Response ) => {
|
||||||
response.send( 'Please visit <a href="https://music.janishutz.com">https://music.janishutz.com</a> to use this service' );
|
response.send( 'Please visit <a href="https://music.janishutz.com">https://music.janishutz.com</a> to use this service' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
||||||
app.get( '/createRoomToken', ( request: express.Request, response: express.Response ) => {
|
app.get(
|
||||||
if ( sdk.checkAuth( request ) ) {
|
'/createRoomToken',
|
||||||
const roomName = String( request.query.roomName ) ?? '';
|
( request: express.Request, response: express.Response ) => {
|
||||||
if ( !socketData[ roomName ] ) {
|
if ( sdk.checkAuth( request ) ) {
|
||||||
const roomToken = crypto.randomUUID();
|
// eslint-disable-next-line no-constant-binary-expression
|
||||||
socketData[ roomName ] = {
|
const roomName = String( request.query.roomName ) ?? '';
|
||||||
playbackStart: 0,
|
|
||||||
playbackStatus: false,
|
if ( !socketData[ roomName ] ) {
|
||||||
playlist: [],
|
const roomToken = crypto.randomUUID();
|
||||||
playlistIndex: 0,
|
|
||||||
roomName: roomName,
|
socketData[ roomName ] = {
|
||||||
roomToken: roomToken,
|
'playbackStart': 0,
|
||||||
ownerUID: sdk.getUserData( request ).uid,
|
'playbackStatus': false,
|
||||||
useAntiTamper: request.query.useAntiTamper === 'true' ? true : false,
|
'playlist': [],
|
||||||
};
|
'playlistIndex': 0,
|
||||||
response.send( roomToken );
|
'roomName': roomName,
|
||||||
} else {
|
'roomToken': roomToken,
|
||||||
if ( socketData[ roomName ].ownerUID === sdk.getUserData( request ).uid ) {
|
'ownerUID': sdk.getUserData( request ).uid,
|
||||||
response.send( socketData[ roomName ].roomToken );
|
'useAntiTamper': request.query.useAntiTamper === 'true'
|
||||||
|
? true : false,
|
||||||
|
};
|
||||||
|
response.send( roomToken );
|
||||||
} else {
|
} else {
|
||||||
response.status( 409 ).send( 'ERR_CONFLICT' );
|
if (
|
||||||
|
socketData[ roomName ].ownerUID
|
||||||
|
=== sdk.getUserData( request ).uid
|
||||||
|
) {
|
||||||
|
response.send( socketData[ roomName ].roomToken );
|
||||||
|
} else {
|
||||||
|
response.status( 409 ).send( 'ERR_CONFLICT' );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
response.status( 403 ).send( 'ERR_FORBIDDEN' );
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
response.status( 403 ).send( 'ERR_FORBIDDEN' );
|
|
||||||
}
|
}
|
||||||
} );
|
);
|
||||||
|
|
||||||
|
|
||||||
app.get( '/getAppleMusicDevToken', ( req, res ) => {
|
app.get( '/getAppleMusicDevToken', ( req, res ) => {
|
||||||
// sign dev token
|
checkIfOwned( req ).then( owned => {
|
||||||
const privateKey = fs.readFileSync( path.join( __dirname + '/config/apple_private_key.p8' ) ).toString();
|
if ( owned ) {
|
||||||
// TODO: Remove secret
|
// sign dev token
|
||||||
const config = JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/apple-music-api.config.secret.json' ) ) );
|
const privateKey = fs.readFileSync( path.join(
|
||||||
const now = new Date().getTime();
|
__dirname,
|
||||||
const tomorrow = now + 24 * 3600 * 1000;
|
'/config/apple_private_key.p8'
|
||||||
const jwtToken = jwt.sign( {
|
) ).toString();
|
||||||
'iss': config.teamID,
|
const config = JSON.parse( fs.readFileSync( path.join(
|
||||||
'iat': Math.floor( now / 1000 ),
|
__dirname,
|
||||||
'exp': Math.floor( tomorrow / 1000 ),
|
'/config/apple-music-api.config.secret.json'
|
||||||
}, privateKey, {
|
) ).toString() );
|
||||||
algorithm: "ES256",
|
|
||||||
keyid: config.keyID
|
|
||||||
} );
|
|
||||||
res.send( jwtToken );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// TODO: Get user's subscriptions using store sdk
|
|
||||||
|
|
||||||
app.get( '/checkUserStatus', ( request: express.Request, response: express.Response ) => {
|
|
||||||
if ( sdk.checkAuth( request ) ) {
|
|
||||||
storeSDK.getSubscriptions( sdk.getUserData( request ).uid ).then( stat => {
|
|
||||||
let owned = false;
|
|
||||||
const now = new Date().getTime();
|
const now = new Date().getTime();
|
||||||
for ( let sub in stat ) {
|
const tomorrow = now + ( 24 * 3600 * 1000 );
|
||||||
if ( stat[ sub ].expires - now > 0
|
const jwtToken = jwt.sign( {
|
||||||
&& ( stat[ sub ].id === 'com.janishutz.MusicPlayer.subscription' || stat[ sub ].id === 'com.janishutz.MusicPlayer.subscription-month' ) ) {
|
'iss': config.teamID,
|
||||||
owned = true;
|
'iat': Math.floor( now / 1000 ),
|
||||||
}
|
'exp': Math.floor( tomorrow / 1000 ),
|
||||||
}
|
}, privateKey, {
|
||||||
if ( owned ) {
|
'algorithm': 'ES256',
|
||||||
response.send( 'ok' );
|
'keyid': config.keyID
|
||||||
|
} );
|
||||||
|
|
||||||
|
res.send( jwtToken );
|
||||||
|
} else {
|
||||||
|
res.status( 402 ).send( 'ERR_NOT_OWNED' );
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
.catch( e => {
|
||||||
|
if ( e === 'ERR_NOT_OWNED' ) {
|
||||||
|
res.status( 402 ).send( e );
|
||||||
|
} else if ( e === 'ERR_AUTH_REQUIRED' ) {
|
||||||
|
res.status( 401 ).send( e );
|
||||||
} else {
|
} else {
|
||||||
response.send( 'ERR_NOT_OWNED' );
|
res.send( 500 ).send( e );
|
||||||
}
|
}
|
||||||
} ).catch( e => {
|
|
||||||
console.error( e );
|
|
||||||
response.status( 404 ).send( 'ERR_NOT_OWNED' );
|
|
||||||
} );
|
} );
|
||||||
} else {
|
|
||||||
response.status( 401 ).send( 'ERR_AUTH_REQUIRED' );
|
|
||||||
}
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
app.use( ( request: express.Request, response: express.Response, next: express.NextFunction ) => {
|
|
||||||
response.status( 404 ).send( 'ERR_NOT_FOUND' );
|
const ownedCache = {};
|
||||||
// response.sendFile( path.join( __dirname + '' ) )
|
|
||||||
|
const checkIfOwned = ( request: express.Request ): Promise<boolean> => {
|
||||||
|
return new Promise( ( resolve, reject ) => {
|
||||||
|
if ( sdk.checkAuth( request ) ) {
|
||||||
|
const userData = sdk.getUserData( request );
|
||||||
|
|
||||||
|
if ( ownedCache[ userData.uid ] ) {
|
||||||
|
resolve( ownedCache[ userData.uid ] );
|
||||||
|
} else {
|
||||||
|
storeSDK.getSubscriptions( userData.uid )
|
||||||
|
.then( stat => {
|
||||||
|
const now = new Date().getTime();
|
||||||
|
|
||||||
|
for ( const sub in stat ) {
|
||||||
|
if ( stat[ sub ].expires - now > 0
|
||||||
|
&& (
|
||||||
|
stat[ sub ].id
|
||||||
|
=== 'com.janishutz.MusicPlayer.subscription'
|
||||||
|
|| stat[ sub ].id
|
||||||
|
=== 'com.janishutz.MusicPlayer.subscription-month'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
ownedCache[ userData.uid ] = true;
|
||||||
|
resolve( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ownedCache[ userData.uid ] = false;
|
||||||
|
resolve( false );
|
||||||
|
} )
|
||||||
|
.catch( e => {
|
||||||
|
console.error( e );
|
||||||
|
reject( 'ERR_NOT_OWNED' );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reject( 'ERR_AUTH_REQUIRED' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
app.get(
|
||||||
|
'/checkUserStatus',
|
||||||
|
( request: express.Request, response: express.Response ) => {
|
||||||
|
checkIfOwned( request )
|
||||||
|
.then( owned => {
|
||||||
|
if ( owned ) {
|
||||||
|
response.send( 'ok' );
|
||||||
|
} else {
|
||||||
|
response.status( 402 ).send( 'ERR_NOT_OWNED' );
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
.catch( e => {
|
||||||
|
if ( e === 'ERR_NOT_OWNED' ) {
|
||||||
|
response.status( 402 ).send( e );
|
||||||
|
} else if ( e === 'ERR_AUTH_REQUIRED' ) {
|
||||||
|
response.status( 401 ).send( e );
|
||||||
|
} else {
|
||||||
|
response.send( 500 ).send( e );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
app.use( ( request: express.Request, response: express.Response ) => {
|
||||||
|
response.status( 404 ).send( 'ERR_NOT_FOUND: ' + request.path );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
|
||||||
const PORT = process.env.PORT || 8082;
|
const PORT = process.env.PORT || 8082;
|
||||||
|
|
||||||
httpServer.listen( PORT );
|
httpServer.listen( PORT );
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
run
|
run
|
||||||
}
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user