diff --git a/electron/index3.html b/electron/index3.html index 1ce605f..905c55e 100644 --- a/electron/index3.html +++ b/electron/index3.html @@ -92,6 +92,7 @@ const superagent = require('superagent'); const path = require('path'); const fs = require('fs'); + const crypto = require('crypto') const Login = require('../modules/login'); const shell = require('electron').shell @@ -377,6 +378,8 @@ ', }); + + var userAccordionHolder; Vue.component('user-accordion', { data: function() { return { @@ -398,7 +401,7 @@ \ \
\ -
{{key}}
\ +
{{key}}{{displayName(value)}}
\
\ \ {{folderList(value.vpaths)}}\ @@ -406,6 +409,8 @@
\
\
\ + Remove last.fm account\ + Add last.fm account\
\ Reset Password\ Edit\ @@ -417,12 +422,20 @@ \ ', mounted: function () { + userAccordionHolder = this; this.instances = M.Collapsible.init(document.querySelectorAll('.collapsible-folders'), { onCloseEnd: this.closeOverride }); }, beforeDestroy: function() { + userAccordionHolder = null; this.instances[0].destroy(); }, methods: { + displayName: function(arr) { + if(arr['lastfm-user']) { + return ' (last.fm: ' + arr['lastfm-user'] + ')'; + } + return ''; + }, folderList: function(arr) { var returnThis = ''; arr.forEach((element) => { @@ -473,6 +486,40 @@ ] }); }, + openLastFmModal: function(value, key, index) { + editThisUser = key; + if (vModal.$children[0]) { + vModal.componentKey = !vModal.componentKey; + } + vModal.currentViewModal = 'user-lastfm-view'; + modalInstance[0].open(); + }, + removeLastFmUser: function(value, key, index) { + iziToast.question({ + timeout: 20000, + close: false, + overlayClose: true, + overlay: true, + displayMode: 'once', + id: 'question', + zindex: 99999, + title: "Remove last.fm login for '" + key + "'?", + position: 'center', + buttons: [ + ['', (instance, toast) => { + loadJson.users[key]['lastfm-user'] = undefined; + loadJson.users[key]['lastfm-password'] = undefined; + fs.writeFileSync(configFile, JSON.stringify(loadJson), 'utf8'); + // this.instances[0].close(index); + instance.hide({ transitionOut: 'fadeOut' }, toast, 'button'); + this.$forceUpdate() + }, true], + ['', (instance, toast) => { + instance.hide({ transitionOut: 'fadeOut' }, toast, 'button'); + }], + ] + }); + }, toggleOptions: function(index, el) { if(el.target.classList.contains('btn')){ return; @@ -526,6 +573,7 @@
\
\
\ + \
\
\
\
\ -
\ +
\
\ \ \ @@ -926,9 +982,6 @@ this.selectInstance[0].destroy(); }, methods: { - maybeResetForm: function() { - - }, updateFolders: function() { loadJson.users[this.currentUser].vpaths = this.selectInstance[0].getSelectedValues(); fs.writeFileSync(configFile, JSON.stringify(loadJson), 'utf8'); @@ -942,6 +995,94 @@ } } }); + + const userLastFmView = Vue.component('user-lastfm-view', { + data() { + return { + currentUser: editThisUser, + users: loadJson.users, + lastFmUser: '', + lastFmPassword: '', + lastFmVerified: false, + pending: false + }; + }, + template: '\ +
\ + \ + \ +
', + methods: { + addLastFmAccount: async function() { + this.pending = true; + // validate last.fm credentials + if(await testLastFm(this.lastFmUser, this.lastFmPassword) === false) { + this.pending = false; + iziToast.warning({ + title: 'Failed to Login to Last.fm', + position: 'topCenter', + timeout: 3500 + }); + return; + } + + this.pending = false; + + if (this.currentUser) { + loadJson.users[this.currentUser]['lastfm-user'] = this.lastFmUser; + loadJson.users[this.currentUser]['lastfm-password'] = this.lastFmPassword; + + fs.writeFileSync(configFile, JSON.stringify(loadJson), 'utf8'); + modalInstance[0].close(); + + // Force update component if it exists + if(userAccordionHolder) { + userAccordionHolder.$forceUpdate(); + } + return; + } + }, + maybeResetForm: function() { + if (this.lastFmUser === '' && this.lastFmPassword === '') { + document.getElementById("add-lastfm-user-form").reset(); + } + }, + } + }); + + async function testLastFm(username, password) { + const apiKey1 = '25627de528b6603d6471cd331ac819e0'; + const apiKey2 = 'a9df934fc504174d4cb68853d9feb143'; + + const token = crypto.createHash('md5').update(username + crypto.createHash('md5').update(password, 'utf8').digest("hex"), 'utf8').digest("hex"); + const cryptoString = `api_key${apiKey1}authToken${token}methodauth.getMobileSessionusername${username}${apiKey2}`; + const hash = crypto.createHash('md5').update(cryptoString, 'utf8').digest("hex"); + + // Try logging in + try { + await superagent.get(`http://ws.audioscrobbler.com/2.0/?method=auth.getMobileSession&username=${username}&authToken=${token}&api_key=${apiKey1}&api_sig=${hash}`).send(); + }catch (err) { + return false; + } + + return true; + } const bootView = Vue.component('boot-view', { template: "\ @@ -1109,6 +1250,7 @@ components: { 'user-password-view': userPasswordView, 'user-folders-view': userFoldersView, + 'user-lastfm-view': userLastFmView }, data: { componentKey: false, diff --git a/mstream.js b/mstream.js index 7590da9..48434c8 100755 --- a/mstream.js +++ b/mstream.js @@ -126,10 +126,9 @@ exports.serveIt = function (program) { sharedModule.setupAfterSecurity(mstream, program); // Start the server! - // TODO: Check if port is in use before firing up server server.on('request', mstream); server.listen(program.port, () => { - let protocol = program.ssl && program.ssl.cert && program.ssl.key ? 'https' : 'http'; + const protocol = program.ssl && program.ssl.cert && program.ssl.key ? 'https' : 'http'; winston.info(`Access mStream locally: ${protocol + '://localhost:' + program.port}`); winston.info(`Try the WinAmp Demo: ${protocol + '://localhost:' + program.port}/winamp`); diff --git a/public/js/api2.js b/public/js/api2.js index 1bbae90..449f2bc 100644 --- a/public/js/api2.js +++ b/public/js/api2.js @@ -15,17 +15,6 @@ var MSTREAMAPI = (function () { } }); - - // TODO: Special functions for handling multiple servers - // Add Server - // Delete Server - // Select Server - // Edit Server - // Test Sever - // Login server and save credentials - - - function makeRequest(url, type, dataObject, callback) { var request = $.ajax({ url: url, @@ -44,7 +33,6 @@ var MSTREAMAPI = (function () { }); } - function makePOSTRequest(url, dataObject, callback) { makeRequest(url, "POST", dataObject, callback); } @@ -53,8 +41,6 @@ var MSTREAMAPI = (function () { makeRequest(url, "GET", dataObject, callback); } - - mstreamModule.dirparser = function (directory, filetypes, callback) { makePOSTRequest('/dirparser', { dir: directory }, callback); }