Plex External Player

Play plex videos in an external player

当前为 2015-12-29 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Plex External Player
  3. // @namespace https://github.com/Kayomani/PlexExternalPlayer
  4. // @version 1.1
  5. // @description Play plex videos in an external player
  6. // @author Kayomani
  7. // @include /^https?://.*:32400/web.*
  8. // @include http://*:32400/web/index.html*
  9. // @require http://code.jquery.com/jquery-1.11.3.min.js
  10. // @grant GM_xmlhttpRequest
  11. // ==/UserScript==
  12.  
  13. var makeRequest = function(url){
  14. return new Promise( function (resolve, reject) {
  15. GM_xmlhttpRequest({
  16. method: "GET",
  17. url: url,
  18. onload: resolve,
  19. onerror: reject
  20. });
  21. });
  22. };
  23.  
  24. var logMessage = function(msg){
  25. console.log('Plex External: ' + msg);
  26. };
  27.  
  28. var markAsPlayedInPlex = function(id) {
  29. logMessage('Marking ' + id + ' as played');
  30. return makeRequest(window.location.origin + '/:/scrobble?key='+ id +'&identifier=com.plexapp.plugins.library');
  31. };
  32.  
  33. var playFileUsingAgent = function(path, id) {
  34. logMessage('Playing ' + path);
  35. var url = 'http://localhost:7251/' + btoa(path);
  36. return new Promise(function (resolve, reject) {
  37. makeRequest(url).then(function(){
  38. markAsPlayedInPlex(id).then(resolve, reject);
  39. },reject);
  40. });
  41. };
  42.  
  43. var clickListener = function(e) {
  44. e.preventDefault();
  45. e.stopPropagation();
  46. var a = jQuery(e.target).closest('a');
  47. var link = a.attr('href');
  48. var url = link;
  49. if (link === '#' || link === undefined) {
  50. url = window.location.hash;
  51. }
  52.  
  53. if (url.indexOf('%2Fmetadata%2F') > -1) {
  54. var idx = url.indexOf('%2Fmetadata%2F');
  55. var id = url.substr(idx + 14);
  56.  
  57. // Get metadata
  58. makeRequest(window.location.origin + '/library/metadata/' + id + '?checkFiles=1&includeExtras=1')
  59. .then(function(response){
  60. // Play the first availible part
  61. var parts = response.responseXML.getElementsByTagName('Part');
  62. for (var i = 0; i < parts.length; i++) {
  63. if (parts[i].attributes['file'] !== undefined) {
  64. playFileUsingAgent(parts[i].attributes['file'].value, id);
  65. return;
  66. }
  67. }
  68.  
  69. if (parts.length === 0) {
  70. // If we got a directory/Season back then get the files in it
  71. var dirs = response.responseXML.getElementsByTagName('Directory');
  72. if (dirs.length > 0) {
  73. makeRequest(window.location.origin + dirs[0].attributes['key'].value)
  74. .then(function(response){
  75. var videos = response.responseXML.getElementsByTagName('Video');
  76. var file = null;
  77. var id = null;
  78. for (var i = 0; i < videos.length; i++) {
  79. var vparts = videos[i].getElementsByTagName('Part');
  80. if (vparts.length > 0) {
  81. file = vparts[0].attributes['file'].value;
  82. id = vparts[0].attributes['id'].value;
  83. if (videos[i].attributes['lastViewedAt'] === null || videos[i].attributes['lastViewedAt'] === undefined) {
  84. break;
  85. }
  86. }
  87. }
  88.  
  89. if (file !== null) {
  90. playFileUsingAgent(file, id);
  91. }
  92. });
  93. }
  94. }
  95. });
  96. }
  97. };
  98.  
  99. var bindClicks = function() {
  100. jQuery(".glyphicon.play").each(function(i, e) {
  101. e = jQuery(e);
  102. if (!e.hasClass('plexextplayer')) {
  103. if (!e.parent().hasClass('hidden')) {
  104. e.addClass('plexextplayer');
  105. var parent = e.parent().parent();
  106. if (parent.is('li')) {
  107. var template = jQuery('<li><a class="btn-gray" href="#" title="Play Externally" data-toggle="Play Externally" data-original-title="Play Externally"><i style="color: #41D677" class="glyphicon play plexextplayer plexextplayerico"></i></a></li>');
  108. parent.after(template);
  109. template.click(clickListener);
  110. } else if (parent.is('div') && parent.hasClass('media-poster-actions')) {
  111. var template = jQuery('<button class="play-btn media-poster-btn btn-link" tabindex="-1"><i style="color: #41D677" class="glyphicon play plexextplayer plexextplayerico"></i></button>');
  112. parent.prepend(template);
  113. template.click(clickListener);
  114. }
  115. }
  116. }
  117. });
  118. };
  119.  
  120. // Make buttons smaller
  121. jQuery('body').append('<style>.media-poster-btn { padding: 8px !important; }</style>');
  122.  
  123. // Bind buttons and check for new ones every 100ms
  124. setInterval(bindClicks, 100);
  125. bindClicks();