Webroot and autojoin support

This commit is contained in:
Sam 2018-07-16 18:04:32 +10:00
parent b3da77011c
commit df25079309
14 changed files with 236 additions and 203 deletions

View File

@ -1,18 +1,15 @@
{
"presets": [
["env",
{ "modules": false }
],
"presets": [
[ "env", { "modules": false } ],
"stage-2",
"es2015",
"es2016"
],
"plugins": [
"transform-runtime"],
"plugins": ["transform-runtime"],
"comments": false,
"env": {
"test": {
"presets": ["env", "stage-2"],
"presets": [ "env", "stage-2" ],
"plugins": [ "istanbul" ]
}
}

31
SettingsHelper.js Normal file
View File

@ -0,0 +1,31 @@
var jsonfile = require('jsonfile')
module.exports = function () {
const fields = [
'webroot',
'serverRoot',
'accessUrl',
'autoJoin',
'autoJoinServer',
'autoJoinRoom',
'autoJoinPassword'
]
// Load and export our settings in preference of ENV -> settings.json -> example_settings.json
let output = {}
let settingsFile
try {
settingsFile = require('./settings.json')
} catch (e) {
console.log('Creating default settings.json')
let defaults = require('./example_settings.json')
jsonfile.writeFileSync('./settings.json', defaults)
settingsFile = defaults
}
let defaults = require('./example_settings.json')
for (let i = 0; i < fields.length; i++) {
let setting = fields[i]
output[setting] = process.env[setting] || settingsFile[setting] || defaults[setting]
}
return output
}

View File

@ -2,7 +2,7 @@ require('./check-versions')()
var config = require('../config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
@ -24,28 +24,28 @@ var app = express()
var compiler = webpack(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
publicPath: webpackConfig.output.publicPath,
quiet: true
})
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
@ -66,24 +66,24 @@ var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
_resolve = resolve
})
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
ready: readyPromise,
close: () => {
server.close()
}
}

View File

@ -3,69 +3,69 @@ var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
options = options || {}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
var cssLoader = {
loader: 'css-loader',
options: {
minimize: process.env.NODE_ENV === 'production',
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
var loaders = [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}

View File

@ -1,38 +1,41 @@
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
let SettingsHelper = require('../SettingsHelper.js')
let settings = new SettingsHelper()
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: '',
assetsPublicPath: '/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: '',
assetsPublicPath: '/',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: '',
assetsPublicPath: settings.webroot || '/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: '',
assetsPublicPath: settings.webroot || '/',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}

View File

@ -1,14 +1,9 @@
{
"webroot": "",
"serverRoot": "",
"webapp_port": 8088,
"server_port": 8089,
"database": {
"datastores": {
"defaults": {
"adapter": "sails-disk",
"filePath": "./"
}
}
}
"accessUrl": "",
"autoJoin": false,
"autoJoinServer": "",
"autoJoinRoom": "",
"autoJoinPassword": ""
}

View File

@ -10,6 +10,9 @@
var express = require('express')
var cors = require('cors')
let SettingsHelper = require('./SettingsHelper')
let settings = new SettingsHelper()
var root = express()
root.use(cors({ credentials: false }))
root.use((req, res, next) => {
@ -18,7 +21,7 @@ root.use((req, res, next) => {
})
var ptserver = express()
var PORT = process.env.port || 8089
var PORT = process.env.server_port || 8089
// Setup our PTServer
ptserver.get('/', (req, res) => {
@ -27,7 +30,7 @@ ptserver.get('/', (req, res) => {
// Merge everything together
let serverRoot = '/'
let serverRoot = '/' || settings.serverRoot
root.use(serverRoot, ptserver)
root.get('*', function (req, res) {
return res.send('You\'ve connected to the SLServer, you\'re probably looking for the webapp.')

View File

@ -72,6 +72,9 @@ import leftsidebar from './leftsidebar'
import upnext from './upnext'
import donate from './donate'
let SettingsHelper = require('../SettingsHelper')
let settings = new SettingsHelper()
export default {
components: {
drawerright,
@ -145,15 +148,6 @@ export default {
// Browser is not Chrome
window.localStorage.setItem('EXTAVAILABLE', false)
}
if (process.env.autojoin && process.env.autojoin_room && process.env.autojoin_server) {
this.$store.commit('SET_AUTOJOIN', true)
this.$store.commit('SET_AUTOJOINROOM', process.env.autojoin_room)
this.$store.commit('SET_AUTOJOINURL', process.env.autojoin_server)
if (process.env.autojoin_password) {
this.$store.commit('SET_AUTOJOINPASSWORD', process.env.autojoin_password)
}
}
if (this.$route.query.autojoin) {
this.$store.commit('SET_AUTOJOIN', true)
this.$store.commit('SET_AUTOJOINROOM', this.$route.query.room)
@ -197,8 +191,16 @@ export default {
await this.$store.dispatch('PLEX_LOGIN_TOKEN', plexstorage.authToken)
} catch (e) {
console.log('Login failed', e)
this.$router.push('/signin')
return this.$router.push('/signin')
}
if (settings.autoJoin) {
await this.$store.dispatch('autoJoin', {
server: settings.autoJoinServer,
password: settings.autoJoinPassword,
room: settings.autoJoinRoom
})
}
// if (this.$store.getters.getAutoJoin) {
// // Attempt to auto join
// this.$store.dispatch('socketConnect', {

View File

@ -5,12 +5,15 @@ import signin from '../components/signin'
import signout from '../components/signout'
import join from '../components/join'
let SettingsHelper = require('../../SettingsHelper.js')
let settings = new SettingsHelper()
Vue.use(Router)
// ==================== Router registration ====================
export default new Router({
mode: 'hash',
base: '/',
base: settings.webroot || '/',
routes: [{
path: '/',
meta: {

View File

@ -102,14 +102,11 @@ const mutations = {
// We have a new chosen client, we need to stop
return
}
console.log('commandInProgress', commandInProgress)
if (state.chosenClient.clientIdentifier !== 'PTPLAYER9PLUS10') {
if (!commandInProgress) {
state.chosenClient.getTimeline().then(() => {
console.log('Fetch timeline done')
commandInProgress = false
}).catch((e) => {
console.log('Fetch timeline done', e)
commandInProgress = false
})
commandInProgress = true

View File

@ -154,7 +154,6 @@ export default {
for (let y in server.plexConnections) {
let serverConnection = server.plexConnections[y]
if (serverConnection.uri === clientConnection.uri) {
console.log('ADDING ACCESS TOKEN FOR MATCHING URL', client, server)
client.accessToken = server.accessToken
}
}

View File

@ -2,6 +2,9 @@ const EventEmitter = require('events')
var moment = require('moment')
var axios = require('axios')
let SettingsHelper = require('../../../SettingsHelper.js')
let settings = new SettingsHelper()
function sendNotification (message) {
return window.EventBus.$emit('notification', message)
}
@ -179,8 +182,8 @@ export default {
// Generate our short url/invite link
console.log('generating our invite link')
console.log(state)
let urlOrigin = window.location.origin
console.log('Loaded settings', settings)
let urlOrigin = window.location.origin + (settings.webroot || '')
if (process.env.NODE_ENV === 'development') {
urlOrigin = 'http://localhost:8088'
}

View File

@ -1,40 +1,50 @@
{
"models": {
"invite": {
"waterline": {
"models": {
"invite": {
"attributes": {
"server": {
"type": "string",
"required": true
},
"room": {
"type": "string",
"required": true
},
"password": {
"type": "string"
},
"owner": {
"type": "string",
"required": true
},
"code": {
"type": "string"
},
"fullUrl": {
"type": "string"
}
}
}
},
"defaultModelSettings": {
"primaryKey": "id",
"datastore": "defaults",
"attributes": {
"server": {
"type": "string",
"required": true
},
"room": {
"type": "string",
"required": true
},
"password": {
"type": "string"
},
"owner": {
"type": "string",
"required": true
},
"code": {
"type": "string"
},
"fullUrl": {
"type": "string"
"id": {
"type": "number",
"autoMigrations": {
"autoIncrement": true
}
}
}
}
},
"defaultModelSettings": {
"primaryKey": "id",
"datastore": "defaults",
"attributes": {
"id": {
"type": "number",
"autoMigrations": {
"autoIncrement": true
}
}
},
"database": {
"datastores": {
"defaults": {
"adapter": "sails-disk",
"filePath": "./"
}
}
}

View File

@ -6,49 +6,39 @@
var express = require('express')
var path = require('path')
var cors = require('cors')
var jsonfile = require('jsonfile')
var bodyParser = require('body-parser')
var Waterline = require('waterline')
var WaterlineMysql = require('waterline-mysql')
var SailsDisk = require('sails-disk')
let settings = {}
let SettingsHelper = require('./SettingsHelper')
let settings = new SettingsHelper()
console.log('Settings', settings)
var accessIp = ''
var PORT = 8088
const bootstrap = () => {
return new Promise(async (resolve, reject) => {
try {
settings = require('./settings.json')
} catch (e) {
console.log(e)
console.log('Creating default settings.json')
let defaults = require('./example_settings.json')
jsonfile.writeFileSync('./settings.json', defaults)
await new Promise((resolve, reject) => {
setTimeout(() => resolve(), 500)
})
settings = require('./settings.json')
}
const args = require('args-parser')(process.argv)
if (!args['url'] && !process.env.url) {
console.log('Missing required argument -url. EG. "node webapp.js --url=http://example.com/ptweb". This URL is used for redirecting invite links.')
if (!args['accessUrl'] && !settings.accessUrl) {
console.log('Missing required argument -accessUrl. EG. "node webapp.js --accessUrl=http://sl.example.com". This URL is used for redirecting invite links.')
return reject(new Error('Missing URL for invite links'))
}
accessIp = args['url'] || process.env.url // EG 'http://95.231.444.12:8088/ptweb' or 'http://example.com/ptweb'
if (args['port'] || process.env.port || settings.webapp_port) {
PORT = args['port'] || process.env.port || settings.webapp_port
accessIp = args['url'] || settings.accessUrl// EG 'http://95.231.444.12:8088/slweb' or 'http://example.com/slweb'
if (args['webapp_port'] || process.env.webapp_port) {
PORT = args['webapp_port'] || process.env.webapp_port
} else {
console.log('Defaulting webapp to port 8088')
}
PORT = parseInt(PORT)
let baseSettings = require('./waterline_settings.json')
baseSettings.adapters = {
console.log('Basesettings', baseSettings)
baseSettings.waterline.adapters = {
'waterline-mysql': WaterlineMysql,
'sails-disk': SailsDisk
}
baseSettings.datastores = settings.database.datastores
baseSettings.models.invite.beforeCreate = async (data, cb) => {
baseSettings.waterline.datastores = baseSettings.database.datastores
baseSettings.waterline.models.invite.beforeCreate = async (data, cb) => {
console.log('Creating Invite', data)
let fullUrl
let params = {
@ -68,7 +58,7 @@ const bootstrap = () => {
data.code = (0 | Math.random() * 9e6).toString(36)
cb()
}
Waterline.start(baseSettings, (err, orm) => {
Waterline.start(baseSettings.waterline, (err, orm) => {
if (err) {
return reject(err)
}
@ -82,7 +72,7 @@ const app = async (orm) => {
root.use(cors())
root.use(bodyParser())
// Setup our web app
root.use(settings.webroot + '/', express.static(path.join(__dirname, 'dist')))
root.use((settings.webroot) + '/', express.static(path.join(__dirname, 'dist')))
root.get(settings.webroot + '/invite/:id', async (req, res) => {
console.log('handling an invite', req.params.id)
let shortObj = await Waterline.getModel('invite', orm).findOne({ code: req.params.id })