Play Video Locally

Gives you a simple button on certain media servers to send the video to a local player.

  1. // ==UserScript==
  2. // @name Play Video Locally
  3. // @namespace https://naeembolchhi.github.io/
  4. // @version 0.7
  5. // @description Gives you a simple button on certain media servers to send the video to a local player.
  6. // @author NaeemBolchhi
  7. // @match http*://circleftp.net/*
  8. // @match http*://10.16.100.244/*
  9. // @match http*://freedrivemovie.com/*
  10. // @match http*://movies.discoveryftp.net/*
  11. // @license GPL-3.0-or-later
  12. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDkuMC1jMDAwIDc5LjE3MWMyN2ZhYiwgMjAyMi8wOC8xNi0yMjozNTo0MSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3ZjA1MzA4NC02ODgzLWQ5NDgtYjg0Yy1iMTVlMzgyZmJhNjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QTQ0REMwMkMyQkM1MTFFRkIxRTZDMzBFNEJFMkQ4NDciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QTQ0REMwMkIyQkM1MTFFRkIxRTZDMzBFNEJFMkQ4NDciIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDI0LjAgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6N2YwNTMwODQtNjg4My1kOTQ4LWI4NGMtYjE1ZTM4MmZiYTY0IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjdmMDUzMDg0LTY4ODMtZDk0OC1iODRjLWIxNWUzODJmYmE2NCIv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
  13. // @run-at document-idle
  14. // @grant none
  15. // ==/UserScript==
  16.  
  17. // Supported video formats
  18. const vform = [".mp4",".mkv"];
  19.  
  20. // Hide video players (change value to "invisible" to hide a player, and to "visible" to show it)
  21. const vvid = {
  22. "potplayer": "visible",
  23. "vlcplayer": "visible",
  24. "xplayer": "visible",
  25. "mxplayer": "visible",
  26. "mxplayerpro": "visible"
  27. };
  28.  
  29. // SVG Icons
  30. const icons = {
  31. "toggle":`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M7 11H1v2h6v-2zm2.17-3.24L7.05 5.64 5.64 7.05l2.12 2.12 1.41-1.41zM13 1h-2v6h2V1zm5.36 6.05l-1.41-1.41-2.12 2.12 1.41 1.41 2.12-2.12zM17 11v2h6v-2h-6zm-5-2c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm2.83 7.24l2.12 2.12 1.41-1.41-2.12-2.12-1.41 1.41zm-9.19.71l1.41 1.41 2.12-2.12-1.41-1.41-2.12 2.12zM11 23h2v-6h-2v6z"/></svg>`,
  32. "next":`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><path d="M150.4 180.1c-5.1-5.6-9.7-10.6-14.2-15.7-29.7-32.7-59.3-65.4-89-98.1-4.9-5.4-10.8-8.8-18.2-9.6C15.6 55.2 2.5 65.3.4 78.5c-1.4 9.4 1.7 17.2 8 24.1 24.9 27.3 49.7 54.7 74.5 82 14.8 16.3 30.1 32.1 44.1 49 10.9 13.1 34.8 12.8 46.1 0 38.9-43.9 78.6-87 118-130.4 6.1-6.7 9.9-14 8.7-23.3-1.4-10.7-7.3-18.3-17.5-21.8-10.9-3.8-20.7-1.1-28.5 7.3-18.5 20.1-36.7 40.3-55 60.5l-47.1 51.9c-.4.7-.7 1.4-1.3 2.3z"/></svg>`,
  33. "prev":`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300"><path d="M150.4 119.7c-5.1 5.6-9.7 10.6-14.2 15.7-29.7 32.7-59.3 65.4-89 98.1-4.9 5.4-10.8 8.8-18.2 9.6-13.4 1.5-26.5-8.6-28.6-21.8-1.4-9.4 1.7-17.2 8-24.1 24.9-27.3 49.7-54.7 74.5-82 14.8-16.3 30.1-32.1 44.1-49 10.9-13.1 34.8-12.8 46.1 0 38.9 43.9 78.6 87 118 130.4 6.1 6.7 9.9 14 8.7 23.3-1.4 10.7-7.3 18.3-17.5 21.8-10.9 3.8-20.7 1.1-28.5-7.3-18.5-20.1-36.7-40.3-55-60.5L151.7 122c-.4-.7-.7-1.4-1.3-2.3z"/></svg>`,
  34. "player":``,
  35. "mobile":``,
  36. "pc":``
  37. };
  38.  
  39. // Get URL variables
  40. function getVar(vlink) {
  41. let vars = {};
  42. let parts = vlink.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
  43. vars[key] = value;
  44. });
  45. return vars;
  46. }
  47.  
  48. // Generate protocol URL
  49. function getURL(player, url, text) {
  50. let matchList = [
  51. {"key": "none", "val": `${url}`},
  52. {"key": "potplayer", "val": `potplayer://${url}`},
  53. {"key": "vlcplayer", "val": `vlc://${url}`},
  54. {"key": "xplayer", "val": `intent:${url}#Intent;package=video.player.videoplayer;S.title=${text};end`},
  55. {"key": "mxplayer", "val": `intent:${url}#Intent;package=com.mxtech.videoplayer.ad;S.title=${text};end`},
  56. {"key": "mxplayerpro", "val": `intent:${url}#Intent;package=com.mxtech.videoplayer.pro;S.title=${text};end`}
  57. ]
  58.  
  59. for (let x = 0; x < matchList.length; x++) {
  60. if (player === matchList[x].key) {
  61. return matchList[x].val;
  62. }
  63. }
  64. }
  65.  
  66. // Make any new element
  67. function elemake(tag, innr, attr) {
  68. let element = document.createElement(tag);
  69. if (innr) {element.innerHTML = innr;}
  70. if (!attr) {return element;}
  71.  
  72. for (let x = 0; x < attr.key.length; x++) {
  73. element.setAttribute(attr.key[x], attr.val[x]);
  74. }
  75. return element;
  76. }
  77.  
  78. // let sample = elemake("div","ja monchay",{"key":["id","class"],"val":["oneDiv","nav pointer"]});
  79. // document.body.appendChild(sample);
  80.  
  81. // Find supported videos in "src" and "href" of all tags
  82. function getVids() {
  83. let allLinks = document.querySelectorAll('*[src], *[href]'),
  84. print = [];
  85.  
  86. for (let x = 0; x < allLinks.length; x++) {
  87. var tmpl = "";
  88. if (allLinks[x].href !== undefined) {tmpl = allLinks[x].href;}
  89. if (allLinks[x].src !== undefined) {tmpl = allLinks[x].src;}
  90.  
  91. if (tmpl.match(/source/)) {
  92. tmpl = decodeURIComponent(getVar(tmpl).source);
  93. }
  94.  
  95. var ext = tmpl.replace(/.*(....)$/,'$1'),
  96. okay = 'no';
  97.  
  98. for (let y = 0; y < vform.length; y++) {
  99. if (ext === vform[y]) {okay = 'yes';}
  100. }
  101.  
  102. if (okay === 'yes' && print.indexOf(tmpl) === -1) {
  103. print.push(tmpl);
  104. }
  105. }
  106.  
  107. window.vidlinks = JSON.stringify(print);
  108. }
  109.  
  110. // Determine visibility
  111. function visble(what, txt) {
  112. if (vvid[what] === "visible") {
  113. return `<a class="avid ${what}">Open with ${txt}</a>`;
  114. } else {
  115. return `<a class="avid ${what} hidden">Open with ${txt}</a>`;
  116. }
  117. }
  118.  
  119. // Visualize the interface
  120. function inTerface() {
  121. const inStyle = `<style type="text/css">
  122. #playVideoLocally, #playVideoLocally * {
  123. outline: none;
  124. }
  125. #playVideoLocally {
  126. position: fixed;
  127. display: block;
  128. z-index: 2147483647;
  129. }
  130. #playVideoLocally section {
  131. position: fixed;
  132. bottom: 0;
  133. left: 0;
  134. background: transparent;
  135. height: 100%;
  136. width: 100%;
  137. display: block;
  138. z-index: 2147483641;
  139. transition: opacity .1s linear, filter .1s linear, transform .1s linear;
  140. }
  141. #playVideoLocally section:not(.clicked) {
  142. opacity: 0;
  143. filter: blur(6px);
  144. transform: translateY(100%);
  145. }
  146. #playVideoLocally section > backdrop {
  147. position: fixed;
  148. background: transparent;
  149. height: 100svh;
  150. width: 100svw;
  151. display: block;
  152. z-index: 2147483640;
  153. }
  154. #playVideoLocally > .btn-main {
  155. position: fixed;
  156. bottom: 0;
  157. left: 0;
  158. z-index: 2147483642;
  159. display: flex;
  160. align-items: center;
  161. justify-content: center;
  162. height: 40px;
  163. width: 40px;
  164. padding: 10px;
  165. margin: 0 0 20px 20px;
  166. border-radius: 100%;
  167. fill: #cdd6f4;
  168. background: #11111b;
  169. cursor: pointer;
  170. box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.25);
  171. transition: opacity .1s linear;
  172. }
  173. #playVideoLocally > .btn-main > svg {
  174. transition: transform .1s linear;
  175. }
  176. #playVideoLocally > .btn-main.clicked > svg {
  177. transform: rotate(-90deg);
  178. }
  179. #playVideoLocally > .btn-main:not(.clicked) {
  180. opacity: .5;
  181. }
  182. #playVideoLocally > .btn-main:not(.clicked):hover {
  183. fill: #ffffff;
  184. opacity: 1;
  185. }
  186. #playVideoLocally > .btn-main.clicked:hover {
  187. opacity: 1;
  188. color: #ffffff;
  189. fill: #ffffff;
  190. background: #444654;
  191. }
  192. #playVideoLocally section > .section-sub {
  193. position: fixed;
  194. bottom: 0;
  195. left: 0;
  196. z-index: 2147483641;
  197. margin: 0 0 70px 20px;
  198. display: flex;
  199. flex-direction: column;
  200. gap: 10px;
  201. }
  202. #playVideoLocally section > .section-sub > span {
  203. height: 40px;
  204. width: 40px;
  205. padding: 10px;
  206. border-radius: 100%;
  207. display: flex;
  208. align-items: center;
  209. justify-content: center;
  210. font-size: 14px;
  211. font-weight: 700;
  212. color: #cdd6f4;
  213. fill: #cdd6f4;
  214. background: #11111b;
  215. box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.25);
  216. cursor: pointer;
  217. }
  218. #playVideoLocally section > .section-sub > .current {
  219. cursor: default;
  220. }
  221. #playVideoLocally section > .section-sub > span:hover {
  222. color: #ffffff;
  223. fill: #ffffff;
  224. background: #444654;
  225. }
  226. #playVideoLocally section > .section-sub > span.disabled {
  227. fill: #999999 !important;
  228. cursor: not-allowed;
  229. }
  230. #playVideoLocally section > .section-main {
  231. position: fixed;
  232. bottom: 0;
  233. left: 0;
  234. z-index: 2147483641;
  235. margin: 0 0 20px 70px;
  236. display: flex;
  237. flex-direction: column;
  238. gap: 10px;
  239. }
  240. #playVideoLocally section > .section-main > a {
  241. height: 40px;
  242. min-width: 40px;
  243. width: fit-content;
  244. display: flex;
  245. align-items: center;
  246. padding: 15px;
  247. font-size: 14px;
  248. border-radius: 500px;
  249. color: #cdd6f4;
  250. fill: #cdd6f4;
  251. background: #11111b;
  252. text-decoration: none;
  253. box-shadow: 0 0 4px 1px rgba(0, 0, 0, 0.25);
  254. }
  255. #playVideoLocally section > .section-main > a:hover {
  256. color: #ffffff;
  257. fill: #ffffff;
  258. background: #444654;
  259. }
  260. #playVideoLocally .next > svg {
  261. transform: translateY(1px);
  262. }
  263. #playVideoLocally .prev > svg {
  264. transform: translateY(-1px);
  265. }
  266. #playVideoLocally .next:not(.disabled):active, #playVideoLocally .prev:not(.disabled):active {
  267. transform: scale(.75);
  268. }
  269. #playVideoLocally .hidden {
  270. display: none !important;
  271. }
  272. </style>`;
  273.  
  274. const inSide = `
  275. <div class="btn-main">${icons.toggle}</div>
  276. <section>
  277. <div class="section-sub">
  278. <span class="prev">${icons.prev}</span>
  279. <span class="current"></span>
  280. <span class="next">${icons.next}</span>
  281. </div>
  282. <div class="section-main">
  283. ${visble('potplayer', 'PotPlayer')}
  284. ${visble('vlcplayer', 'VLC Player')}
  285. ${visble('xplayer', 'XPlayer')}
  286. ${visble('mxplayer', 'MX Player')}
  287. ${visble('mxplayerpro', 'MX Player Pro')}
  288. <a class="avid raw filename"></a>
  289. </div>
  290. <backdrop></backdrop>
  291. </section>
  292. `;
  293.  
  294. let mainDiv = elemake("div", inStyle + inSide, {"key":["id"],"val":["playVideoLocally"]});
  295. document.body.appendChild(mainDiv);
  296. }
  297.  
  298. // Make it interactive
  299. function inTeract(num) {
  300. if (num > JSON.parse(window.vidlinks).length - 1) {
  301. var numX = JSON.parse(window.vidlinks).length - 1;
  302. } else if (num < 0) {
  303. var numX = 0;
  304. } else {
  305. var numX = num;
  306. }
  307.  
  308. let disLink = JSON.parse(window.vidlinks)[numX],
  309. disTitle = decodeURIComponent(disLink.replace(/.*\/(.*)$/,'$1'));
  310.  
  311. document.querySelector('#playVideoLocally .filename').innerText = disTitle;
  312.  
  313. document.querySelector('#playVideoLocally .avid.raw').href = getURL('none', disLink, disTitle);
  314. document.querySelector('#playVideoLocally .avid.potplayer').href = getURL('potplayer', disLink, disTitle);
  315. document.querySelector('#playVideoLocally .avid.vlcplayer').href = getURL('vlcplayer', disLink, disTitle);
  316. document.querySelector('#playVideoLocally .avid.xplayer').href = getURL('xplayer', disLink, disTitle);
  317. document.querySelector('#playVideoLocally .avid.mxplayer').href = getURL('mxplayer', disLink, disTitle);
  318. document.querySelector('#playVideoLocally .avid.mxplayerpro').href = getURL('mxplayerpro', disLink, disTitle);
  319.  
  320. document.querySelector('#playVideoLocally .prev').classList.remove('disabled','hidden');
  321. document.querySelector('#playVideoLocally .next').classList.remove('disabled','hidden');
  322.  
  323. document.querySelector('#playVideoLocally .current').innerText = numX + 1;
  324. document.querySelector('#playVideoLocally .current').setAttribute('data-num', numX);
  325.  
  326. if (numX === 0) {
  327. document.querySelector('#playVideoLocally .prev').classList.add('disabled');
  328. } else if (numX === JSON.parse(window.vidlinks).length - 1) {
  329. document.querySelector('#playVideoLocally .next').classList.add('disabled');
  330. }
  331.  
  332. if (JSON.parse(window.vidlinks).length === 1) {
  333. document.querySelector('#playVideoLocally .prev').classList.add('hidden');
  334. document.querySelector('#playVideoLocally .next').classList.add('hidden');
  335. }
  336. }
  337.  
  338. // Event listeners
  339. function inVent() {
  340. let prev = document.querySelector('#playVideoLocally .prev'),
  341. next = document.querySelector('#playVideoLocally .next'),
  342. current = document.querySelector('#playVideoLocally .current'),
  343. main = document.querySelector('#playVideoLocally .btn-main'),
  344. section = document.querySelector('#playVideoLocally section'),
  345. backdrop = document.querySelector('#playVideoLocally backdrop');
  346.  
  347. document.addEventListener('click', function(e) {
  348. if (e.target == prev || prev.contains(e.target)) {
  349. inTeract(parseInt(current.getAttribute('data-num')) - 1);
  350. }
  351. if (e.target == next || next.contains(e.target)) {
  352. inTeract(parseInt(current.getAttribute('data-num')) + 1);
  353. }
  354. if (e.target == main || main.contains(e.target)) {
  355. try {getVids();} catch {}
  356. try {inTeract(0);} catch {}
  357. if (main.classList.contains('clicked')) {
  358. main.classList.remove('clicked');
  359. section.classList.remove('clicked');
  360. } else {
  361. main.classList.add('clicked');
  362. section.classList.add('clicked');
  363. }
  364. }
  365. if (e.target == backdrop || backdrop.contains(e.target)) {
  366. main.click();
  367. }
  368. });
  369. }
  370.  
  371. if (!document.body.classList.contains('jwplayer')) {
  372. try {getVids();} catch {}
  373. try {inTerface();} catch {}
  374. try {inTeract(0);} catch {}
  375. try {inVent();} catch {}
  376. }