Fixed invites

This commit is contained in:
samcm 2017-06-04 17:05:30 +10:00
parent 75fdc36e22
commit 41a9e40ea5
8 changed files with 150 additions and 140 deletions

4
.gitignore vendored
View File

@ -5,6 +5,4 @@ npm-debug.log
test/unit/coverage
test/e2e/reports
selenium-debug.log
npm-debug.log.3732580485
npm-debug.log.2139949888
.idea/

View File

@ -7,7 +7,7 @@
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js",
"webapp": "node webapp.js",
"webapp": "node webapp.js -- ",
"server": "node server.js",
"unit": "karma start test/unit/karma.conf.js --single-run",
"e2e": "node test/e2e/runner.js",
@ -15,6 +15,7 @@
"lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
},
"dependencies": {
"args-parser": "^1.1.0",
"bootstrap-sass": "^3.3.7",
"connect-history-api-fallback": "^1.3.0",
"cors": "^2.8.3",

View File

@ -7,13 +7,14 @@
<script>
import Navbar from './components/Navbar'
import 'assets/css/materialize.css';
import 'assets/js/materialize.js';
import 'assets/css/materialize.css';
import 'assets/js/materialize.js';
export default {
mounted (){
console.log('route',this.$route)
if (this.$route.query.ptserver && this.$route.query.ptroom){
console.log('We should auto join')
// Looks like a valid request...
@ -31,4 +32,4 @@ export default {
},
components: { Navbar }
}
</script>
</script>

View File

@ -7,7 +7,7 @@
</div>
<h2> Libraries </h2>
<div v-if="libraries && !browsingLibrary" v-for="library in filteredLibraries">
<v-card v-on:click.native="setLibrary(library)" class="blue-grey darken-1 col l3 s12 hoverable" style="box-shadow:none">
<v-card v-on:click.native="setLibrary(library)" class="row blue-grey darken-1 col l3 s12 hoverable" style="box-shadow:none">
<div class="col s3 l3" style="height:100%">
<img :src="getThumb(library)" style="height:100%; width:100%" >
</div>

View File

@ -1,7 +1,7 @@
<template>
<div style="height: calc(100% - 64px" class="row">
<div class="col s12 l4 offset-l4">
<div class="row" style="padding-top:10%">
<div class="row" style="padding-top:10%">
<div class="col l4 s12 left">
<img :src="logo" style="width:100%"/>
</div>
@ -9,29 +9,35 @@
<h2 class="center"> Welcome to Plex Together!</h2>
<div class="row">
<div class="col l12 s12 center">
<div> <span style="font-weight:900">{{ owner }}</span> has invited to join the room <span style="font-weight:900">{{ room }}</span>.</div>
<small>Sit tight! You'll be in sync in no time.</small>
</div>
<div style="color:white">
<span style="font-weight:900">{{ owner }}</span> has invited you to join the room "<span style="font-weight:900">{{ room }}</span>"
</div>
<div class="row" style="margin:5%">
<div class="col l12 s12">
<v-btn class="center" style="background-color: #E5A00D" v-on:click.native="letsGo()">Accept Invite</v-btn>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
// CSS imports
import 'assets/css/material-components-web.css';
import 'assets/css/grid.css';
import 'assets/css/style2.css';
import 'assets/css/material-components-web.css';
import 'assets/css/grid.css';
import 'assets/css/style2.css';
export default {
name: 'join',
mounted: function(){
var that = this
mounted: function(){
var that = this
console.log('Hello from join...')
this.password = this.$route.query.ptpassword
this.room = this.$route.query.ptroom
@ -46,11 +52,8 @@ export default {
this.$store.commit('SET_AUTOJOINPASSWORD',this.password)
this.$store.commit('SET_AUTOJOINURL',this.server)
}
setTimeout(function(){
that.$router.push('/sync')
},2500)
},
created: function(){
created: function(){
},
data () {
return {
@ -62,16 +65,15 @@ export default {
},
computed:{
logo: function(){
if (this.$store.getters.getSettingDARKMODE){
return 'static/logo-small-light.png'
}
return 'static/logo-small-dark.png'
},
}
},
methods: {
letsGo(){
this.$router.push('/sync')
}
}
}
</script>

View File

@ -1,5 +1,5 @@
<template>
<div class="window">
<div class="window">
<div class="window-content">
<div class="container">
<div class="row">
@ -7,42 +7,40 @@
<div>
<h1 class="center">Sign in to Plex.tv</h1>
</div>
<div v-if="!pin" class="center">
<v-progress-circular active large></v-progress-circular>
</div>
</div>
<div v-if="token" class="center row">
<div class="col s12 l4 offset-l4">
<i style="font-size:150px; color:green" class="material-icons">done</i>
</div>
<div class="col s12 l4 offset-l4">
</div>
<div class="col s12 l4 offset-l4" style="color:white">
Signed in!
</div>
</div>
<div v-if="pin && !token">
</div>
<div v-if="pin && !token">
<div class="row">
<div class="col s12 l4 offset-l4">
<h1 class="center">{{ pin }}</h1>
</div>
</div>
<div class="row">
<div class="col s4 l4 offset-l4 offset-s4">
</div>
<div class="row">
<div class="col s4 l4 offset-l4 offset-s4">
<button style="width:100%;background-color: #E5A00D" class="waves-effect waves-light btn" v-clipboard="pin"><i class="material-icons left">content_paste</i>Copy</button>
</div>
<div class="col s12 l12">
<p class="center">Enter the pin above at <a target="_blank" href="https://plex.tv/link"> https://plex.tv/link </a></p>
</div>
</div>
</div>
<div class="row center">
<label class="col s12"> Your Plex account is used to fetch the details of your Plex devices. None of your private details are sent to our servers. If you would like to install and run Plex Together yourself
have a look <a target="_blank" href="https://github.com/samcm/plextogether"> here </a> for details. </label>
have a look <a target="_blank" href="https://github.com/samcm/plextogether"> here </a> for details. </label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
@ -142,13 +140,13 @@ export default {
}
request(options, callback);
},2000)
}
}
})
return
})
}
getPin()
},
methods: {
signout: function(){
@ -161,7 +159,7 @@ export default {
var that = this
var base64encoded = new Buffer(this.user + ":" + this.pass).toString('base64')
}
}
}

View File

@ -28,7 +28,7 @@ if(!getSetting('INIT')){
setSetting('CLIENTPOLLINTERVAL',1000)
setSetting('DARKMODE',false)
setSetting('SYNCMODE','cleanseek')
setSetting('SYNCFLEXABILITY',4000)
setSetting('SYNCFLEXABILITY',3000)
setSetting('CUSTOMSERVER','http://')
setSetting('INIT',true)
}
@ -36,20 +36,20 @@ if(!getSetting('INIT')){
let _webapp_socket = null
if (process.env.NODE_ENV == 'development'){
console.log('running in development')
/*
_webapp_socket = socketio.connect(''+window.location.hostname+':8088',{'forceNew':true,'connect timeout': 1000,path: '/ptweb/socket.io'})
_webapp_socket.on('connection',function(){
})
})
_webapp_socket.on('connect_error',function(){
})
*/
})
} else {
_webapp_socket = socketio.connect({'forceNew':true,
'connect timeout': 1000,path: '/ptweb/socket.io'})
'connect timeout': 1000, path: '/ptweb/socket.io'})
_webapp_socket.on('connection',function(){
})
})
_webapp_socket.on('connect_error',function(){
})
})
}
const state = {
@ -57,7 +57,7 @@ const state = {
appTitle: 'PlexTogether',
appVersion: '1.0.0',
shownChat: false,
plex: null,
plex: null,
chosenClient: null,
chosenClientTimeSet: (new Date).getTime(),
plexuser: JSON.parse(window['localStorage'].getItem('plexuser')),
@ -79,10 +79,10 @@ const state = {
}
const mutations = {
SET_CHOSENCLIENT(state,client){
SET_CHOSENCLIENT(state,client){
function playbackChange(ratingKey){
console.log('Playback change!')
if (ratingKey != null) {
if (ratingKey != null) {
// Playing something different!
let server = state.plex.getServerById(state.chosenClient.lastTimelineObject.machineIdentifier)
if (!server){
@ -96,9 +96,9 @@ const mutations = {
}
if (metadata.type == 'movie'){
sendNotification('Now Playing: ' + metadata.title + ' from ' + state.plex.getServerById(metadata.machineIdentifier).name )
}
}
if (metadata.type == 'episode'){
sendNotification('Now Playing: ' + metadata.grandparentTitle + ' S' + metadata.parentIndex + 'E' + metadata.index + ' from ' + state.plex.getServerById(metadata.machineIdentifier).name )
sendNotification('Now Playing: ' + metadata.grandparentTitle + ' S' + metadata.parentIndex + 'E' + metadata.index + ' from ' + state.plex.getServerById(metadata.machineIdentifier).name)
}
state.chosenClient.clientPlayingMetadata = metadata
})
@ -106,7 +106,7 @@ const mutations = {
state.chosenClient.clientPlayingMetadata = null
}
}
function newTimeline(timeline){
function newTimeline(timeline){
console.log('Got timeline')
if (!state.plextogether.connected){
return
@ -140,15 +140,15 @@ const mutations = {
state.plextogether._socket.pollStartTime = (new Date).getTime()
state.plextogether._socket.emit('poll',end_obj)
}
// Set up our client poller
// Set up our client poller
function clientPoller(time){
if (state.chosenClient == null){
return
}
if (state.chosenClientTimeSet != time){
// We have a new chosen client, we need to stop
return
// We have a new chosen client, we need to stop
return
}
state.chosenClient.getTimeline(function(timeline){
//console.log(timeline)
@ -156,43 +156,43 @@ const mutations = {
setTimeout(function(){
clientPoller(time)
},state.CLIENTPOLLINTERVAL)
}
}
// Check if we need to remove old handlers
if (state.chosenClient){
state.chosenClient.events.removeAllListeners();
state.chosenClient.events.removeAllListeners();
}
state.chosenClient = client
state.chosenClient = client
if (state.chosenClient && state.chosenClient.lastTimelineObject){
state.chosenClient.lastTimelineObject.ratingKey = -1
}
}
if (state.chosenClient == null){
return
}
state.chosenClient.events.on('new_timeline',newTimeline)
state.chosenClient.events.on('playback_change',playbackChange)
state.chosenClient.events.on('new_timeline',newTimeline)
state.chosenClient.events.on('playback_change',playbackChange)
state.chosenClientTimeSet = (new Date).getTime()
clientPoller(state.chosenClientTimeSet)
state.chosenClient.getTimeline(function(timeline){})
state.chosenClient.getTimeline(function(timeline){})
},
SET_PLEX(state,value){
state.plex = value
},
},
SET_AUTOJOIN(state,value){
state.autoJoin = value
},
},
SET_AUTOJOINROOM(state,value){
state.autoJoinRoom = value
},
},
SET_AUTOJOINPASSWORD(state,value){
state.autoJoinPassword = value
},
},
SET_AUTOJOINURL(state,value){
state.autoJoinUrl = value
},
},
SET_SHORTLINK(state,value){
state.shortLink = value
},
@ -208,11 +208,11 @@ const mutations = {
setSettingSYNCMODE(state,data){
setSetting('SYNCMODE',data)
state.SYNCMODE = data
},
},
setSettingSYNCFLEXABILITY(state,data){
setSetting('SYNCFLEXABILITY',data)
state.SYNCFLEXABILITY = data
},
},
setSettingCUSTOMSERVER(state,data){
setSetting('CUSTOMSERVER',data)
state.CUSTOMSERVER = data
@ -220,7 +220,7 @@ const mutations = {
setSettingDARKMODE(state,data){
setSetting('DARKMODE',data)
state.DARKMODE = data
},
},
setSettingHOMEINIT(state,data){
setSetting('HOMEINIT',data)
state.HOMEINIT = data
@ -230,13 +230,13 @@ const mutations = {
},
SET_BLOCKAUTOPLAY(state,value){
state.blockAutoPlay = value
},
},
SET_DECISIONBLOCKED(state,value){
state.decisionBlocked = value
},
},
REFRESH_PLEXDEVICES(state){
store.state.plex.getDevices(function(){
})
},
@ -273,36 +273,36 @@ const getters = {
},
getBlockAutoPlay: state => {
return state.blockAutoPlay
},
},
getAutoJoin: state => {
return state.autoJoin
},
},
getAutoJoinRoom: state => {
return state.autoJoinRoom
},
},
getAutoJoinPassword: state => {
return state.autoJoinPassword
},
},
getAutoJoinUrl: state => {
return state.autoJoinUrl
},
},
getShortLink: state => {
return state.shortLink
},
// SETTINGS
// SETTINGS
getSettingCLIENTPOLLINTERVAL: state => {
return state.CLIENTPOLLINTERVAL
},
},
getSettingSYNCMODE: state => {
return state.SYNCMODE
},
},
getSettingSYNCFLEXABILITY: state => {
return state.SYNCFLEXABILITY
},
},
getSettingCUSTOMSERVER: state => {
return state.CUSTOMSERVER
},
},
getSettingDARKMODE: state => {
return state.DARKMODE
},
@ -325,8 +325,8 @@ const actions = {
}
const plexTogether = {
state: {
_io: require('socket.io-client'),
state: {
_io: require('socket.io-client'),
_socket:null,
ptevents: new EventEmitter(),
ptservers: [],
@ -342,13 +342,13 @@ const plexTogether = {
getters: {
getServer: state => {
return state.server
},
},
getMe: state => {
return state.me
},
getRoom: state => {
return state.room
},
},
getPassword: state => {
return state.password
},
@ -365,7 +365,7 @@ const plexTogether = {
return state._socket
}
},
mutations: {
mutations: {
SET_CONNECTED(state, value) {
state.connected = value
},
@ -389,14 +389,14 @@ const plexTogether = {
},
ADD_MESSAGE(state,msg){
msg.time = moment().format('h:mm A')
state.messages.push(msg)
state.messages.push(msg)
},
CLEAR_MESSAGES(state,msg){
state.messages = []
}
},
actions: {
actions: {
autoJoin({ state, commit, rootState, dispatch }, data){
console.log('Attempting to auto join..')
console.log(rootState)
@ -420,7 +420,7 @@ const plexTogether = {
}
}
})
},
},
socketConnect({ state, commit, rootState },data) {
let address = data.address
let callback = data.callback
@ -474,8 +474,8 @@ const plexTogether = {
sendNotification('Joined room: ' + _data.room)
// Generate our short url/invite link
console.log('generating our invite link')
// Generate our short url/invite link
console.log('generating our invite link')
console.log(state)
let webapp_socket = rootState.webapp_socket
let url = window.location.origin
@ -487,7 +487,7 @@ const plexTogether = {
ptserver: state.server,
ptroom: state.room,
ptpassword: state.password
}
var that = this
if (process.env.NODE_ENV != 'development'){
@ -506,16 +506,16 @@ const plexTogether = {
state._socket.on('poll-result',function(users){
commit('SET_OURCLIENTRESPONSETIME', Math.abs((new Date().getTime()) - state._socket.pollStartTime))
commit('SET_USERS',users)
})
})
state._socket.on('user-joined',function(users,user){
commit('SET_USERS',users)
commit('SET_USERS',users)
commit('ADD_MESSAGE',{
msg: user.username + ' joined',
user: user,
type: 'alert'
})
console.log(users)
})
})
state._socket.on('user-left',function(users,user){
commit('SET_USERS',users)
commit('ADD_MESSAGE',{
@ -523,7 +523,7 @@ const plexTogether = {
user: user,
type: 'alert'
})
})
})
state._socket.on('host-swap',function(user){
if (!user){
return
@ -540,8 +540,8 @@ const plexTogether = {
We need to limit how ourself to make sure we dont hit the client too hard.
We'll only fetch new data if our data is older than 1000ms.
If we need to fetch new data, we'll do that and then decide
if we need to seek or start playing something.
If we need to fetch new data, we'll do that and then decide
if we need to seek or start playing something.
*/
rootState.hostClientResponseTime = data.clientResponseTime
if (state.decisionBlocked){
@ -557,7 +557,7 @@ const plexTogether = {
console.log('Dont have our first timeline data yet.')
return
}
// Check previous timeline data age
// Check previous timeline data age
let timelineAge = new Date().getTime() - rootState.chosenClient.lastTimelineObject.recievedAt
if (timelineAge > 1000){
rootState.chosenClient.getTimeline(function(newtimeline){
@ -591,7 +591,7 @@ const plexTogether = {
}
// Check if we need to autoplay
if ((ourTimeline.state == 'stopped' || !ourTimeline.state) && (hostTimeline.playerState != 'stopped')){
if (rootState.blockAutoPlay){
if (rootState.blockAutoPlay || !hostTimeline.rawTitle){
return
}
// We need to autoplay!
@ -629,7 +629,7 @@ const plexTogether = {
checkForSeek()
function checkForSeek(){
if (parseInt(difference) > parseInt(rootState.SYNCFLEXABILITY) ){
// We need to seek!
// We need to seek!
console.log('STORE: we need to seek')
// Decide what seeking method we want to use
if (rootState.SYNCMODE == 'cleanseek'){
@ -672,7 +672,7 @@ const plexTogether = {
},difference)
}
rootState.chosenClient.pressPause(function(result,responseTime){
})
})
} else {
state.decisionBlocked = true
rootState.chosenClient.seekTo(parseInt(hostTimeline.time) + 10000,function(){
@ -686,7 +686,7 @@ const plexTogether = {
rootState.chosenClient.seekTo(parseInt(hostTimeline.time),function(result){
console.log('Result from within store for seek was ' + result)
console.log('Setting decision blocked to false ')
state.decisionBlocked = false
state.decisionBlocked = false
})
}
}
@ -696,10 +696,10 @@ const plexTogether = {
state._socket.on('disconnect',function(data){
sendNotification('Disconnected from the PlexTogether server')
if (data == 'io client disconnect'){
console.log('We disconnected from the server')
console.log('We disconnected from the server')
commit('SET_ROOM',null)
commit('SET_PASSWORD',null)
commit('SET_USERS',[])
commit('SET_USERS',[])
commit('SET_CONNECTED',false)
commit('SET_SERVER',null)
commit('SET_CHAT',false)
@ -712,22 +712,22 @@ const plexTogether = {
state._socket.on('new_message',function(msgObj){
commit('ADD_MESSAGE',msgObj)
})
} else {
commit('SET_ME',null)
commit('SET_ME',null)
commit('SET_ROOM',null)
commit('SET_PASSWORD',null)
commit('SET_USERS',[])
commit('SET_CHAT',false)
}
return data.callback(result)
}
return data.callback(result)
})
},
disconnectServer({state, commit, rootState}){
state._socket.disconnect()
state._socket.disconnect()
commit('SET_ROOM',null)
commit('SET_PASSWORD',null)
commit('SET_USERS',[])
commit('SET_USERS',[])
commit('SET_CONNECTED',false)
commit('SET_SERVER',null)
commit('SET_CHAT',false)
@ -749,7 +749,7 @@ const plexTogether = {
}
},
getServerList(){
},
},
}
}
function getHandshakeUser(user,room,password){
@ -760,7 +760,7 @@ function getHandshakeUser(user,room,password){
'avatarUrl':user.thumb
}
return tempUser
}
}
const store = new Vuex.Store({
state,
mutations,

View File

@ -1,15 +1,24 @@
// ABOUT
// Runs the Plex Together Web App - handles serving the static web content and link shortening services
// Defaults to 8088
// Port defaults to 8088
// REQUIRED: --url argument
// USER CONFIG
const args = require("args-parser")(process.argv)
if (!args['url']){
console.log('Missing required argument -url. EG. "node webapp.js --url=http://example.com/ptweb". This URL is used for redirecting invite links.')
return
}
var accessIp = args['url'] // EG 'http://95.231.444.12:8088/ptweb' or 'http://example.com/ptweb'
if (accessIp.indexOf('/ptweb') == -1){
console.log('WARNING: /ptweb was not found in your url. Unless you have changed the URL Base make sure to include this.')
}
var PORT = 8088
var accessIp = 'http://ip:port/ptweb' // EG 'http://95.231.444.12:8088/ptweb' or 'http://example.com/ptweb'
if (args['port']){
PORT = parseInt(args['port'])
} else {
console.log('Defaulting to port 8088')
}
// USER CONFIG
// END USER CONFIG
var express = require('express');
@ -34,14 +43,15 @@ webapp.get('/invite/:id',function(req,res){
console.log('handling an invite')
let shortObj = shortenedLinks[req.params.id]
if (!shortObj){
return res.send('Whoops, looks like youve made a wrong turn..')
return res.send('Invite expired')
}
console.log('Redirecting an invite link')
console.log(JSON.stringify(shortObj,null,4))
return res.redirect(shortObj.fullUrl)
})
root.use('/ptweb',webapp)
root.get('*',function(req,res){
console.log('Catch all')
console.log('Catch all - have you run `npm run build`?')
return res.redirect('/ptweb')
})
@ -56,7 +66,7 @@ var webapp_io = require('socket.io')(rootserver,{path: '/ptweb/socket.io'});
var shortenedLinks = {}
function getUniqueId(){
function getUniqueId(){
while (true){
let testId = (0|Math.random()*9e6).toString(36)
if (!shortenedLinks[testId]){ // Check if we already have a shortURL using that id
@ -91,14 +101,14 @@ function shortenObj(data){
for (let key in params) {
query += encodeURIComponent(key)+'='+encodeURIComponent(params[key])+'&';
}
returnable.fullUrl = accessIp + '/#/?' + query
returnable.fullUrl = accessIp + '/#/join?' + query
shortenedLinks[returnable.id] = returnable
return returnable.shortUrl
}
}
webapp_io.on('connection', function(socket){
console.log('Someone connected to the webapp socket')
console.log('New connection to the webapp socket')
socket.on('shorten',function(data){
console.log('Creating a shortened link')
socket.emit('shorten-result',shortenObj(data))