- // ==UserScript==
- // @name Plex Freebox
- // @namespace Kalmac
- // @description Add a "play on freebox server" button on plex interface.
- // @include http://plex.tv/web/app*
- // @include https://plex.tv/web/app*
- // @version 1
- // @grant GM_xmlhttpRequest
- // @require https://cdn.jsdelivr.net/jquery.cookie/1.4.1/jquery.cookie.min.js
- // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/hmac-sha1.js
- // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
- // ==/UserScript==
- (function () {
- var HOST = 'http://mafreebox.freebox.fr';
- var APP_ID = 'fr.freebox.kalmac';
- var APP_NAME = 'Plex 4 Freebox';
- var APP_VERSION = '0.1';
- var DEVICE_NAME = 'Plex remote';
- var COOKIE_TRACK_ID = 'freebox_plex_track_id';
- var COOKIE_TOKEN = 'freebox_plex_token';
- var COOKIE_AIRPLAY_PASS = 'freebox_plex_airplay_pass';
- var STATE_UNINITIALIZED = 0;
- var STATE_INITIALIZED = 1;
- var STATE_UNAUTHORIZED = 2;
- var STATE_PENDING = 3;
- var STATE_AUTHORIZED = 4;
-
- var STATE_ERROR = 10;
-
- var track_id, token, state = STATE_UNINITIALIZED;
-
- function callFreeboxApi(path, callback, params, method, headers) {
- if (typeof(params) != 'object') {
- params = {};
- }
- if (method !== 'POST') {
- method = 'GET';
- }
- if (typeof(headers) != 'object') {
- headers = {};
- }
-
- GM_xmlhttpRequest({
- url: HOST + path,
- data: JSON.stringify(params),
- method: method,
- headers: headers,
- onload:function(response) {
- callback(JSON.parse(response.responseText));
- },
- onerror: function(response) {
- state = STATE_ERROR;
- core();
- }
- });
- }
-
- function init() {
- track_id = $.cookie(COOKIE_TRACK_ID);
- token = $.cookie(COOKIE_TOKEN);
- if (typeof(track_id) != 'undefined' && typeof(token) != 'undefined') {
- state = STATE_PENDING;
- } else {
- state = STATE_UNAUTHORIZED;
- }
- }
-
- function login() {
- callFreeboxApi('/api/v3/login/authorize/', function(response) {
- if (response.success) {
- $.cookie(COOKIE_TRACK_ID, response.result.track_id, { expires: 1000, path: '/' });
- $.cookie(COOKIE_TOKEN, response.result.app_token, { expires: 1000, path: '/' });
- state = STATE_INITIALIZED;
- core();
- }
- }, {
- 'app_id': APP_ID,
- 'app_name': APP_NAME,
- 'app_version': APP_VERSION,
- 'device_name': DEVICE_NAME }, 'POST');
-
- var airplay_password = prompt("Veuillez autoriser l\'appli sur votre Freebox (fleche de droite) et saisir le mot de passe AirPlay...", "1111");
- $.cookie(COOKIE_AIRPLAY_PASS, airplay_password, { expires: 1000, path: '/' });
- updateAdminButton('Veuillez autoriser l\'appli sur votre Freebox (fleche de droite).', 'refresh', false);
- }
-
- function pending() {
- callFreeboxApi('/api/v3/login/authorize/' + track_id, function(response) {
- if (response.success) {
- switch(response.result.status) {
- case 'pending':
- break;
- case 'granted':
- state = STATE_AUTHORIZED;
- break;
- default:
- console.log('Freebox returned ' + response.result.status);
- $.removeCookie(COOKIE_TRACK_ID, { path: '/' });
- $.removeCookie(COOKIE_TOKEN, { path: '/' });
- state = STATE_INITIALIZED;
- break;
- }
- }
- });
- }
-
-
- function insertAdminButton() {
- var result = false;
- if (!$('li#plex-freebox-admin').length) {
- var elt = $('li#primary-player-dropdown');
- if (elt.length == 1) {
- elt.after('<li id="plex-freebox-admin"><a class="settings-btn" href="#" title="Plex 4 Freebox" data-toggle="tooltip" data-original-title="Plex 4 Freebox"><i class="glyphicon refresh"></i></a></li>');
-
- state = STATE_INITIALIZED;
- }
- }
- return result;
- }
-
- function updateAdminButton(text, glyph, callback) {
- var button = $('li#plex-freebox-admin > a');
- var icon = $('li#plex-freebox-admin > a > i');
-
- button.unbind('click');
- icon.attr('class', 'glyphicon');
-
- button.attr('data-original-title', text);
- button.attr('title', text);
- icon.addClass(glyph);
- if (callback) {
- button.click(callback);
- }
- }
-
- function decoratePlayer() {
-
- if ($('button#plex-freebox-play').length == 0) {
- $('div.video-controls-right span#player-quality-dropdown').before('<button id="plex-freebox-play" class="btn-link recommend-btn pull-left" title="Play 4 Freebox"><i class="glyphicon play">F</i></button>');
- $('button#plex-freebox-play').click(play);
- }
- }
-
- function play(event) {
-
- login(function(challenge) {
- session(challenge, function(session_token) {
-
- var pass = $.cookie(COOKIE_AIRPLAY_PASS);
- var video = $('video#html-video').attr('src');
- var params = {
- 'action':'start',
- 'media_type': 'video',
- 'media': video,
- 'password': typeof(pass) == 'undefined'?'1111':pass
- };
-
- callFreeboxApi('/api/v3/airmedia/receivers/Freebox%20Player/', function() {
-
- }, params, 'POST', {'X-Fbx-App-Auth': session_token});
- });
- });
-
-
- event.preventDefault();
- return false;
- }
-
- function login(callback) {
- callFreeboxApi('/api/v3/login/', function(response) {
- callback(response.result.challenge);
- });
- }
-
- function session(challenge, callback) {
-
- var params = {
- 'app_id':APP_ID,
- 'password': CryptoJS.HmacSHA1(challenge, token).toString(CryptoJS.enc.Hex)
- };
-
- callFreeboxApi('/api/v3/login/session/', function(response) {
- callback(response.result.session_token);
- }, params, 'POST');
-
- }
-
- function core() {
- var retry = false;
-
- switch(state) {
- case STATE_UNINITIALIZED:
- insertAdminButton();
- retry = 1000;
- break;
- case STATE_INITIALIZED:
- updateAdminButton('Plex 4 Freebox en attente ...', 'refresh', false);
- init();
- retry = 2000;
- break;
- case STATE_UNAUTHORIZED:
- updateAdminButton('Cliquez ici pour authoriser Plex 4 Freebox', 'router', login);
- // no retry core until button is clicked.
- break;
- case STATE_PENDING:
- updateAdminButton('Plex 4 Freebox en attente ...', 'refresh', false);
- pending();
- retry = 2000;
- break;
- case STATE_AUTHORIZED:
- updateAdminButton('Plex 4 Freebox', 'ok', false);
- decoratePlayer();
- retry = 2000;
- break;
-
-
- case STATE_ERROR:
- updateAdminButton('Plex 4 Freebox : ERREUR FATALE!', 'remove', false);
- break;
-
- }
-
- console.log('core with state = ' + state);
-
- if (retry) {
- setTimeout(core, retry);
- }
- }
-
- $( window ).load(function() {
-
- core();
- });
-
- }) ();