PlayIt-Monkey-Script

Configurable frontend for PlayIt Service

  1. // ==UserScript==
  2. // @name PlayIt-Monkey-Script
  3. // @namespace https://github.com/rkaradas
  4. // @version 0.5
  5. // @description Configurable frontend for PlayIt Service
  6. // @author Recep Karadas
  7. // @include http*
  8. // @include https*
  9. // @connect *
  10. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js
  11. // @resource customCSS https://raw.githubusercontent.com/rkaradas/PlayIt-Monkey-Script/master/playit.css
  12. // @grant GM_addStyle
  13. // @grant GM_getResourceText
  14. // @grant GM_xmlhttpRequest
  15. // @grant GM_getValue
  16. // @grant GM_setValue
  17. // @grant GM_deleteValue
  18. // ==/UserScript==
  19.  
  20.  
  21.  
  22. /**/
  23. var newCSS = GM_getResourceText ("customCSS");
  24. GM_addStyle (newCSS);
  25.  
  26.  
  27.  
  28. // runs at the end
  29. (function() {
  30. 'use strict';
  31. var connections = [];
  32. var selectedConnectionIdx = -1;
  33. var editingObject;
  34. var selectedElement;
  35. $("head").append (`<link href="//cdnjs.cloudflare.com/ajax/libs/octicons/3.5.0/octicons.min.css" rel="stylesheet" type="text/css">`);
  36. /*$("head").append (`<link href="//localhost/PlayIt_Tampermonkey/playit.css" rel="stylesheet" type="text/css">`);*/
  37. var container = `
  38. <div class='play-it-container' >
  39. <div class='play-it-container-inner' >
  40. <div class='play-it-sidebar' >
  41. <div class='octicon octicon-triangle-right play-it-play-btn' title='Send to PlayIt'> </div>
  42. <div class='octicon octicon-settings play-it-settings-btn' title='Settings'> </div>
  43. <div class='octicon octicon-settings play-it-test-btn' style='display:none !important;' > </div>
  44. <a href='https://github.com/rkaradas/PlayIt-Monkey-Script' title='Show on GitHub' target='_blank'><div class='octicon octicon-mark-github'> </div></a>
  45. <div class='play-it-settings' >
  46. <div class='play-it-settings-wrapper'>
  47. <div class='play-it-settings-header'>SETTINGS</div>
  48. <div class='play-it-settings-content'>
  49. <div class='play-it-settings-add-connection'>
  50. <div class='play-it-settings-add-connection-row'>
  51. <div><input type='text' class="play-it-settings-add-name" placeholder='Connection name, e.g. Kitchen' /></div>
  52. <div><input type='text' class="play-it-settings-add-ip" placeholder='Ip address, e.g. 192.168.1.49' /></div>
  53. <div><input type='text' class="play-it-settings-add-port" placeholder='Port (default:8181)' /></div>
  54. <div class='play-it-settings-add-connection-actions'><button class='play-it-settings-add octicon octicon-plus'></button></div>
  55. </div>
  56. </div>
  57. <div class='play-it-settings-connections'>
  58.  
  59. </div>
  60.  
  61. </div>
  62. <div class='play-it-settings-actions'>
  63. <button class='play-it-settings-save'>SAVE</button>
  64. <button class='play-it-settings-close'>CLOSE</button>
  65. <button class='play-it-settings-clear'>CLEAR ALL</button>
  66.  
  67. </div>
  68. </div>
  69. </div>
  70.  
  71. </div>
  72.  
  73. <div class="play-it-footer">
  74. <div>&lt;&gt;</div>
  75. <div>with ❤️ by </div>
  76. <div>R.Karadas</div>
  77. </div>
  78. </div>
  79. </div>
  80. `;
  81. Init();
  82.  
  83. function Init()
  84. {
  85. editingObject = null;
  86. let containerEl = $(container);//.addClass("play-it-play-btn");
  87. containerEl.mouseenter(function(){
  88. $(this).animate({left: 0});
  89. });
  90. containerEl.mouseleave(function(){
  91. $(this).animate({left: "-" + $(this).css("width")});
  92. });
  93. containerEl.find(".play-it-settings-btn").click(function(){
  94. toggleSettings();
  95. });
  96. containerEl.find(".play-it-play-btn").click(function(){
  97. sendToKodi(location.href);
  98. });
  99. containerEl.find(".play-it-test-btn").click(function(){
  100. let source = document.getElementsByTagName('html')[0].innerHTML;
  101. let mp4Links = source.match(/(https?:\/\/.*\.mp4)/gm);
  102. mp4Links.forEach((itm)=>
  103. {
  104. console.log(itm);
  105. });
  106. //sendToKodi(location.href);
  107. });
  108. containerEl.find(".play-it-settings-close").click(function(){
  109. toggleSettings();
  110. });
  111. containerEl.find(".play-it-settings-save").click(function(){
  112. saveSettings(true);
  113. });
  114. containerEl.find(".play-it-settings-add").click(function(){
  115. addConnection();
  116. });
  117. containerEl.find(".play-it-settings-clear").click(function(){
  118. clearSettings();
  119. });
  120. $("body").filter(function() {
  121. return (self==top);
  122. }).prepend(containerEl);
  123. }
  124. // Functions
  125. function sendToKodi(videoUrl)
  126. {
  127. if(!selectedElement)
  128. loadSelectedElement();
  129. // if
  130. if(selectedElement){
  131. var url= "http://" + selectedElement.ip +":"+selectedElement.port + "/PlayIt";//'http://192.168.1.102:8181/PlayIt';
  132. console.log(url);
  133. var request={version:'1.1',
  134. method:'playHostedVideo',
  135. id:1,
  136. params:{videoLink:videoUrl}
  137. };
  138. GM_xmlhttpRequest({
  139. method: "POST",
  140. url: url,
  141. data: JSON.stringify(request),
  142. headers: {
  143. "Content-Type": "application/x-www-form-urlencoded"
  144. },
  145. onload: function(response) {
  146. console.log("onload");
  147. }
  148. });
  149. }
  150. else{
  151. alert("Please select a connection first");
  152. }
  153. }
  154.  
  155.  
  156. function toggleSettings()
  157. {
  158. let value = $('.play-it-settings').css('opacity') == 1 ? 0 : 1;
  159. let disp = (value==1?"block":"none");
  160. console.log("value: " + value + " - " + disp);
  161. if(disp=="block"){
  162. loadSettings();
  163. $('body').css("overflow","hidden");
  164. $('.play-it-settings').css("display",disp).animate({
  165. opacity: value
  166. });
  167. }else{
  168. $('.play-it-settings').animate({
  169. opacity: value
  170. },function(){ $(this).css("display",disp); $('body').css("overflow","visible"); } );
  171. }
  172. }
  173. function saveSettings(toggle)
  174. {
  175. GM_setValue("connections", JSON.stringify(connections));
  176. GM_setValue("selectedConnectionIdx", selectedConnectionIdx);
  177.  
  178. if(toggle)
  179. {
  180. toggleSettings();
  181. }
  182. }
  183. // this function is needed, if the user does not go to the settings
  184. function loadSelectedElement()
  185. {
  186. connections = JSON.parse(GM_getValue("connections","[]"));
  187. selectedConnectionIdx = GM_getValue("selectedConnectionIdx",-1);
  188. connections.forEach((connection, idx)=>{
  189. if(selectedConnectionIdx == idx)
  190. selectedElement = connection;
  191. });
  192. }
  193. function loadSettings()
  194. {
  195. editingObject = null;
  196. $(".play-it-settings-connections").html("");
  197. connections = JSON.parse(GM_getValue("connections","[]"));
  198. selectedConnectionIdx = GM_getValue("selectedConnectionIdx",-1);
  199. connections.forEach((connection, idx)=>{
  200. console.log("selectedConnectionIdx: "+ selectedConnectionIdx + "|idx: "+idx);
  201. if(selectedConnectionIdx == idx){
  202. selectedElement = connection;
  203. }
  204. addConnectionVisual(connection, (selectedConnectionIdx == idx) );
  205. });
  206. }
  207. function clearSettings()
  208. {
  209. $(".play-it-settings-connections").html("");
  210. connections = [];
  211. selectedConnectionIdx = -1;
  212. GM_deleteValue("connections");
  213. GM_deleteValue("selectedConnectionIdx");
  214. }
  215. function addConnection()
  216. {
  217. let ip = $(".play-it-settings-add-ip").val().trim();
  218. if(isIpV4(ip)){
  219. let name = $(".play-it-settings-add-name").val().trim();
  220. let port = parseInt($(".play-it-settings-add-port").val().trim(),10);
  221. name = name?name:"Kodi";
  222. port = isNaN(port) ? 8181 : port;
  223. let connection = {
  224. name: name,
  225. ip: ip,
  226. port: port
  227. };
  228. addConnectionVisual(connection, true);
  229. connections.push(connection);
  230.  
  231. $(".play-it-settings-add-name").val("");
  232. $(".play-it-settings-add-ip").val("");
  233. $(".play-it-settings-add-port").val("");
  234. saveSettings();
  235. }else
  236. {
  237. alert("Ip address must be a valid ipv4 address.");
  238. }
  239. }
  240. // UI functions
  241. function addConnectionVisual(connection, isSelected)
  242. {
  243. if(isSelected)
  244. {
  245. setSelectedConnection();
  246. }
  247. let connectionContainer = $(`
  248. <div class='play-it-settings-connection' >
  249. <div title='`+connection.name+ `'><span class='play-it-settings-connection-name'>`+connection.name+ `</span></div>
  250. <div title='`+connection.ip+ `'><span class='play-it-settings-connection-ip'>`+connection.ip+ `</span></div>
  251. <div title='`+connection.port+ `'><span class='play-it-settings-connection-port'>`+connection.port+ `</span></div>
  252. <div class="play-it-settings-connection-actions">
  253. <button title='Remove Connection' class='play-it-settings-connection-remove octicon octicon-trashcan'></button>
  254. <button title='Edit Connection' class='play-it-settings-connection-edit octicon octicon-pencil'></button>
  255. <button title='Save' class='play-it-settings-connection-save octicon octicon-check' style='display:none' ></button>
  256. <button title='Select' class='play-it-settings-connection-select octicon octicon-verified' `+(isSelected?`disabled`:``)+` ></button>
  257. </div>
  258. </div>
  259. `);
  260. $(".play-it-settings-connections").append(connectionContainer);
  261. connectionContainer.find(".play-it-settings-connection-remove").click(function(){
  262. connectionRemoveClick($(this));
  263. });
  264. connectionContainer.find(".play-it-settings-connection-edit").click(function(){
  265. connectionEditClick($(this));
  266. });
  267. connectionContainer.find(".play-it-settings-connection-save").click(function(){
  268. connectionSaveClick($(this));
  269. });
  270. connectionContainer.find(".play-it-settings-connection-select").click(function(){
  271. connectionSelectClick($(this));
  272. });
  273. if(isSelected)
  274. {
  275. selectedElement = connections[selectedConnectionIdx];
  276. saveSettings();
  277. }
  278. }
  279. function clearSelectedConnection()
  280. {
  281. selectedElement = null;
  282. selectedConnectionIdx = -1;
  283. $('.play-it-settings-connection-select').prop("disabled",false);
  284. }
  285. function setSelectedConnection(el)
  286. {
  287. $('.play-it-settings-connection-select').prop("disabled",false);
  288. if(el)
  289. el.prop("disabled", true);
  290. }
  291. /**
  292. BEGIN Connection editing click functions
  293. **/
  294. function connectionRemoveClick(el)
  295. {
  296. if(isInEditMode())
  297. return;
  298. let parent = el.closest(".play-it-settings-connection");
  299. let idx = $('.play-it-settings-connection').index(parent);
  300. if(selectedConnectionIdx == idx)
  301. {
  302. clearSelectedConnection();
  303. }
  304. console.log(idx);
  305. el.closest(".play-it-settings-connection").remove();
  306. connections.splice(idx,1);
  307. printConnections();
  308. }
  309. function connectionSelectClick(el)
  310. {
  311. if(isInEditMode())
  312. return;
  313. let parent = el.closest(".play-it-settings-connection");
  314. let idx = $('.play-it-settings-connection').index(parent);
  315. console.log(idx);
  316. selectedConnectionIdx = idx;
  317.  
  318. setSelectedConnection(el);
  319. selectedElement = connections[idx];
  320. saveSettings();
  321. }
  322. function connectionSaveClick(el)
  323. {
  324. let parent = el.closest(".play-it-settings-connection");
  325. let ip = parent.find(".play-it-settings-connection-ip").val().trim();
  326. if(isIpV4(ip)){
  327. let name = parent.find(".play-it-settings-connection-name").val().trim();
  328. let port = parseInt(parent.find(".play-it-settings-connection-port").val().trim(),10);
  329. name = name?name:"Kodi";
  330. port = isNaN(port) ? 8181 : port;
  331.  
  332. let connection = {
  333. name: name,
  334. ip: ip,
  335. port: port
  336. };
  337. if(editingObject.name != connection.name ||editingObject.ip != connection.ip ||editingObject.port != connection.port)
  338. {
  339. connections[editingObject.idx].name = connection.name;
  340. connections[editingObject.idx].ip = connection.ip;
  341. connections[editingObject.idx].port = connection.port;
  342. }
  343. replaceInputWithSpan(parent, "play-it-settings-connection-name");
  344. replaceInputWithSpan(parent, "play-it-settings-connection-ip");
  345. replaceInputWithSpan(parent, "play-it-settings-connection-port");
  346. editingObject = null;
  347. saveSettings();
  348.  
  349. parent.find(".play-it-settings-connection-save").hide();
  350. $(".play-it-settings-connection-edit").show();
  351. }else
  352. {
  353. alert("something went wrong please fix the issues");
  354. }
  355. }
  356. function connectionEditClick(el)
  357. {
  358. if(isInEditMode())
  359. return;
  360.  
  361. let parent = el.closest(".play-it-settings-connection");
  362. let idx = $('.play-it-settings-connection').index(parent);
  363. console.log(idx);
  364. editingObject = {idx:idx,
  365. name: parent.find(".play-it-settings-connection-name").html(),
  366. ip: parent.find(".play-it-settings-connection-ip").html(),
  367. port: parent.find(".play-it-settings-connection-port").html()
  368. };
  369. replaceSpanWithInput(parent, "play-it-settings-connection-name");
  370. replaceSpanWithInput(parent, "play-it-settings-connection-ip");
  371. replaceSpanWithInput(parent, "play-it-settings-connection-port");
  372.  
  373. parent.find(".play-it-settings-connection-save").show();
  374. $(".play-it-settings-connection-edit").hide();
  375. }
  376. function isInEditMode()
  377. {
  378. if(editingObject){
  379. alert("Already in editing mode.\nPlease save changes, before you start editing the next element. ");
  380. return true;
  381. }
  382. return false;
  383. }
  384. /**
  385. END Connection editing click functions
  386. **/
  387. function replaceSpanWithInput(parent, spanClass)
  388. {
  389. var spanEl = parent.find("." + spanClass);
  390. let inp = $(`<input type='text' value='`+spanEl.html()+`' />`).addClass(spanClass);
  391. spanEl.replaceWith(inp);
  392. }
  393. function replaceInputWithSpan(parent, inputClass)
  394. {
  395. var inputEl = parent.find("." + inputClass);
  396. let span = $(`<span>`+inputEl.val()+`</span>`).addClass(inputClass);
  397. inputEl.replaceWith(span);
  398. }
  399. function printConnections()
  400. {
  401. connections.forEach((connection)=>{
  402. console.log(connection.name);
  403. });
  404. }
  405. function isIpV4(ip) {
  406. var x = ip.split("."), x1, x2, x3, x4;
  407.  
  408. if (x.length == 4) {
  409. x1 = parseInt(x[0], 10);
  410. x2 = parseInt(x[1], 10);
  411. x3 = parseInt(x[2], 10);
  412. x4 = parseInt(x[3], 10);
  413.  
  414. if (isNaN(x1) || isNaN(x2) || isNaN(x3) || isNaN(x4)) {
  415. return false;
  416. }
  417.  
  418. if ((x1 >= 0 && x1 <= 255) && (x2 >= 0 && x2 <= 255) && (x3 >= 0 && x3 <= 255) && (x4 >= 0 && x4 <= 255)) {
  419. return true;
  420. }
  421. }
  422. return false;
  423. }
  424. })();
  425.