Facebook HD Video Downloader (Not working!)

(Not working! Read more at Additional info.) Adds a download link for Facebook videos. Works for HD videos.

  1. // ==UserScript==
  2. // @name Facebook HD Video Downloader (Not working!)
  3. // @description (Not working! Read more at Additional info.) Adds a download link for Facebook videos. Works for HD videos.
  4. // @author EThaiZone
  5. // @include http://facebook.com/video.php*
  6. // @include http://*.facebook.com/video.php*
  7. // @include https://facebook.com/video.php*
  8. // @include https://*.facebook.com/video.php*
  9. // @include http://facebook.com/video/*
  10. // @include http://*.facebook.com/video/*
  11. // @include https://facebook.com/video/*
  12. // @include https://*.facebook.com/video/*
  13. // @include http://facebook.com/*/videos/*
  14. // @include http://*.facebook.com/*/videos/*
  15. // @include https://facebook.com/*/videos/*
  16. // @include https://*.facebook.com/*/videos/*
  17. // @include https://*.facebook.com/*
  18. // @version 0.1.6.8
  19. // @namespace https://greasyfork.org/users/3747
  20. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
  21. // ==/UserScript==
  22.  
  23.  
  24. // My code
  25. (function () {
  26.  
  27. function insertAfter(newNode, referenceNode) {
  28. referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
  29. }
  30. if (typeof jQuery == 'undefined') {
  31. alert('[Facebook HD Video Downloader]\n\nYour greasemonkey or tampermonkey is too old. Please update.');
  32. return;
  33. }
  34.  
  35. var patternfbh = /facebook\.com\/(.*?)/;
  36. if (! document.URL.match(patternfbh)) {
  37. return;
  38. }
  39.  
  40. jQuery('head').append('<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">');
  41.  
  42. var css = "\
  43. .dl {\
  44. display: inline-block;\
  45. width: 1em;\
  46. height: 1em;\
  47. }\
  48. .dl_container {\
  49. z-index: 9999;\
  50. position: relative;\
  51. float: right;\
  52. margin: 5px 5px 0 0;\
  53. padding: 2px 4px 2px 4px;\
  54. background: white;\
  55. border-radius: 4px;\
  56. opacity: 0.5;\
  57. transition: opacity 1s, max-width 1s ease-in-out;\
  58. -moz-transition: opacity 1s, max-width 1s ease-in-out;\
  59. -webkit-transition: opacity 1s, max-width 1s ease-in-out;\
  60. color: black !important;\
  61. text-decoration: none;\
  62. display: block;\
  63. height: 1.2em;\
  64. overflow: hidden;\
  65. text-align: center;\
  66. max-width: 1em;\
  67. white-space: nowrap;\
  68. }\
  69. span[display=\"inline\"] .dl_container {\
  70. margin: 5px 30px 0 0;\
  71. display: none !important;\
  72. }\
  73. .dl_container:hover {\
  74. max-width: 140px;\
  75. opacity: 1;\
  76. text-decoration: none;\
  77. }\
  78. ";
  79.  
  80. jQuery('head').append('<style type="text/css">' + css + '</style>');
  81.  
  82. var iconDownload = jQuery('<div/>');
  83. iconDownload = jQuery('<i class="fa fa-download dl"></i>');
  84. function renderFBDownloader(counter) {
  85.  
  86. // Get the base so we can append to it later
  87. var base = jQuery('.comment_link').parent('span').parent('div');
  88. if (base.length === 0) {
  89. base = jQuery('.UFILikeLink').parent('div').parent('span').parent('div'); // check link like
  90. }
  91. if (base.length === 0) {
  92. base = jQuery('.userContent'); // or else I will attach to userContent.
  93. }
  94. base = base[0];
  95.  
  96. /*
  97. * NOTE: Don't use jquery on <video>, it will broke them.
  98. */
  99.  
  100. // Get all the <embed> elements
  101. var videoElements = document.querySelectorAll('video:not([fb_download_link_ethaizone])');
  102. var embedElements = document.querySelectorAll('embed[flashvars]');
  103.  
  104. for (var i = 0; i < videoElements.length; i++) {
  105.  
  106. var embed = videoElements[i].querySelectorAll('embed[flashvars]');
  107.  
  108. if (embed.length === 0) {
  109. continue;
  110. }
  111.  
  112. videoElements[i].setAttribute('fb_download_link_ethaizone', '1');
  113.  
  114. embed = embed[0];
  115.  
  116. // Get the flashvars attribute and decode it
  117. var flashvars = decodeURIComponent(embed.getAttribute('flashvars'));
  118.  
  119. // Check if this string contains the code we're looking for
  120. var hd_src_index = flashvars.indexOf('hd_src');
  121. var p_width_index = flashvars.indexOf('&width=');
  122. if (hd_src_index > -1 && p_width_index > -1) {
  123. // This string contains the payload we are looking for so parse it
  124. var obj = JSON.parse(flashvars.slice(7, p_width_index));
  125.  
  126. if (typeof obj.video_data.progressive == 'undefined') {
  127. log('Something wrong in obj.');
  128. console.log(obj);
  129. continue;
  130. }
  131. var video_data = obj.video_data.progressive;
  132.  
  133. //console.log(video_data);
  134. if (typeof video_data.video_id == 'undefined') {
  135. console.log(video_data);
  136. } else {
  137. var title = video_data.video_id;
  138. }
  139. //var title = document.querySelectorAll('h2.uiHeaderTitle')[0].innerText;
  140.  
  141. // thank css style from fork of nhtera.
  142. var link = jQuery('<a/>');
  143. link.addClass('dl_container');
  144. link.addClass('fbPhotosPhotoActionsItem');
  145. link.addClass('fb_download_link_ethaizone');
  146. link.attr('fb_download_link_ethaizone');
  147. link.append(iconDownload[0].outerHTML);
  148. link.append('&nbsp;');
  149.  
  150. var labelText = null;
  151. var downloadUrl = null;
  152. var filename = null;
  153.  
  154. // High Def
  155. if (typeof video_data.hd_src != 'undefined' && video_data.hd_src) {
  156. labelText = 'Download (HD)';
  157. filename = title + '_hd.mp4';
  158. downloadUrl = video_data.hd_src;
  159. } else if (typeof video_data.sd_src != 'undefined' && video_data.sd_src) {
  160. labelText = 'Download (SD)';
  161. filename = title + '_sd.mp4';
  162. downloadUrl = video_data.sd_src;
  163. }
  164.  
  165. if (downloadUrl) {
  166. link.append('<span class="status">' + labelText + '</span>');
  167. link.prop('download', filename);
  168. link.prop('href', downloadUrl);
  169. link.prop('target', '_blank');
  170. insertAfter(link[0], videoElements[i]);
  171. } else {
  172. log('Something wrong in video_data.');
  173. console.log(video_data);
  174. continue;
  175. }
  176.  
  177. log('Success.');
  178. } // end if
  179.  
  180. } // end loop
  181.  
  182. return videoElements.length;
  183. }
  184.  
  185. var counter = 0;
  186. var delay = 1500;
  187. function doExec() {
  188. if (jQuery('#mainContainer').length < 1) {
  189. // log('No maincontaimer.');
  190. return false;
  191. }
  192. counter++;
  193. try {
  194. var found = renderFBDownloader(counter);
  195. // if (found !== 0 && delay == 1000) {
  196. // delay = 3000;
  197. // log('First found. Decrease delay. ('+ delay +')');
  198. // }
  199.  
  200. // if (counter > 10 && delay == 1000) {
  201. // delay = 5000;
  202. // log('Too long and not found anything. Decrease delay. ('+ delay +')');
  203. // }
  204. // if (counter < 30) {
  205. // setTimeout(doExec, delay);
  206. // }
  207. setTimeout(doExec, delay);
  208. // log('Check!! No:'+counter+' Found: ' + renderFBDownloader(counter));
  209. } catch(e) {
  210. log("Found error!");
  211. console.log(e);
  212. //setTimeout(doExec, 1000);
  213. }
  214.  
  215. return true;
  216. }
  217.  
  218. function log(msg) {
  219. //alert(msg);
  220. console.log("[FB Video Downloader] " + msg);
  221. }
  222. if (doExec()) {
  223. var myVersion = GM_info.script.version;
  224. log("First start. Version "+myVersion);
  225. }
  226. })();