Advertisement
Guest User

HookTube Search Restore 0.2.1

a guest
Jul 12th, 2018
306
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name        HookTube Search Restore
  3. // @namespace   hkt_search_restore
  4. // @description Restores search functionality to HookTube.
  5. // @include     *://hooktube.com/*
  6. // @version     0.2.1
  7. // @grant       GM.xmlHttpRequest
  8. // @run-at      document-end
  9. // @noframes
  10. // ==/UserScript==
  11.  
  12. /*
  13.  * CHANGELOG (DD/MM/YY):
  14.  *
  15.  * 11/07/18 -
  16.  *      Initial.
  17.  * 12/07/18 -
  18.  *      HookTube added a redirect from "/channel/CHANNEL_ID" to the homepage, now using "/channel?cid=CHANNEL_ID" to display channels.
  19.  *      Added description, likes, dislikes, views, and links to channel on video view page.
  20.  *      Fixed issues with script re-running on a page it has already run on when going back in history.
  21.  */
  22.  
  23. if (document.getElementById("hkt_search") !== null) {
  24.   return;
  25. }
  26.  
  27. const TIMEOUT             = 15;
  28. const CHANNEL             = "/channel";
  29. const SEARCH              = "/search";
  30. const WATCH               = "/watch";
  31. const CHANNEL_INTROG      = "?cid=";
  32. const SEARCH_INTROG       = "?q=";
  33. const YTNOAD              = "youtubenoad";
  34. const YTNOAD_CHANNEL_URL  = YTNOAD + ".com/" + CHANNEL_INTROG;
  35. const YTNOAD_SEARCH_URL   = YTNOAD + ".com/" + SEARCH_INTROG;
  36. const YTNOAD_TYPE_VIDEO   = "play_circle_filled";
  37. const YTNOAD_TYPE_PLIST   = "playlist_play";
  38. const YTNOAD_TYPE_CHANNEL = "person";
  39. const HKT                 = "hooktube";
  40. const HKT_CHANNEL_URL     = HKT + ".com" + CHANNEL + CHANNEL_INTROG;
  41. const HKT_SEARCH_URL      = HKT + ".com" + SEARCH + SEARCH_INTROG;
  42. const PROTOCOL            = window.location.protocol + "//";
  43.  
  44. /*
  45.  * address - expected to be a youtubenoad.com/?q= (search) or youtubenoad.com/?cid= (channel) address
  46.  * cbload - callback when data is loaded
  47.  * cbtimeout - callback if request to youtubenoad times out
  48.  */
  49. function getVideoEntries(address, cbload, cbtimeout) {
  50.   GM.xmlHttpRequest({
  51.     method: "GET",
  52.     headers: {
  53.       "Accept": "text/html"
  54.     },
  55.     url: address,
  56.     timeout: 1000 * TIMEOUT,
  57.     ontimeout: function(rsp) {
  58.       cbtimeout();
  59.     },
  60.     onload: function(rsp) {
  61.             let temp = document.createElement("span");
  62.       temp.innerHTML = rsp.responseText;
  63.  
  64.       let entries = temp.getElementsByClassName("card");
  65.       let videos_list = [];
  66.       let videos_count = 0;
  67.       let channels_list = [];
  68.       let channels_count = 0;
  69.       let playlists_list = [];
  70.       let playlists_count = 0;
  71.  
  72.       for (let i = 0; i < entries.length; i++) {
  73.         let type = entries[i].children[0].children[1].children[0].innerHTML;
  74.  
  75.         if (type === YTNOAD_TYPE_VIDEO) {
  76.           videos_list[videos_count++] = {
  77.             title: entries[i].children[1].children[0].children[3].dataset.tooltip,
  78.             url: entries[i].children[0].children[0].href.replace(YTNOAD, HKT),
  79.             img: entries[i].children[0].children[0].children[0].src,
  80.             channel: {
  81.               name: entries[i].children[1].children[0].children[1].innerHTML,
  82.               url: entries[i].children[1].children[0].children[1].href.replace(YTNOAD_CHANNEL_URL, HKT_CHANNEL_URL)
  83.             }
  84.           };
  85.         } else if (type === YTNOAD_TYPE_PLIST) {
  86.           // @todo
  87.           // not important, but maybe
  88.         } else if (type === YTNOAD_TYPE_CHANNEL) {
  89.             // not important either
  90.         }
  91.       }
  92.      
  93.       let next_page_url = "";
  94.       let more_btn = temp.getElementsByClassName("main")[0].children[0].children[0].lastChild.previousSibling;
  95.       if (more_btn.children.length !== 0) {
  96.         // first page has only "next" button, subsequent pages have "previous" button
  97.         if (more_btn.children.length == 2) {
  98.           next_page_url = more_btn.children[1].children[0].href;
  99.         } else {
  100.           next_page_url = more_btn.children[0].children[0].href;
  101.         }
  102.       }
  103.      
  104.       cbload({
  105.         videos: videos_list,
  106.         channels: channels_list,
  107.         playlists: playlists_list,
  108.         next: next_page_url
  109.       });
  110.     }
  111.   });
  112. }
  113.  
  114. function createVideoTile(video_data) {
  115.     let outer = document.createElement("div");
  116.   outer.className = "col-lg-4 col-md-6 col-sm-12";
  117.   let inner = document.createElement("div");
  118.   inner.className = "row mb-2";
  119.  
  120.   let thumb = document.createElement("div");
  121.   thumb.className = "col-sm-5 thumb";
  122.   let thumb_link = document.createElement("a");
  123.   thumb_link.href = video_data.url;
  124.   thumb_link.title = video_data.title;
  125.   let thumb_img = document.createElement("img");
  126.   thumb_img.src = video_data.img.replace("hqdefault", "mqdefault");
  127.   thumb_img.alt = video_data.title;
  128.  
  129.   let dets = document.createElement("div");
  130.   dets.className = "col-sm-7";
  131.   dets.style.overflow = "hidden";
  132.   dets.style.textOverflow = "ellipsis";
  133.   let dets_vidlink = document.createElement("a");
  134.   dets_vidlink.href = video_data.url;
  135.   dets_vidlink.title = video_data.title;
  136.   dets_vidlink.innerHTML = video_data.title;
  137.   let dets_channellink = document.createElement("a");
  138.   dets_channellink.href = video_data.channel.url;
  139.   dets_channellink.innerHTML = video_data.channel.name;
  140.   dets_channellink.style.display = "block";
  141.   dets_channellink.style.color = "black";
  142.  
  143.   dets.appendChild(dets_vidlink);
  144.   dets.appendChild(dets_channellink);
  145.   thumb_link.appendChild(thumb_img);
  146.   thumb.appendChild(thumb_link);
  147.   inner.appendChild(thumb);
  148.   inner.appendChild(dets);
  149.   outer.appendChild(inner);
  150.  
  151.   return outer;
  152. }
  153.  
  154.  
  155. // ================================================================
  156.  
  157.  
  158. const do_search  = window.location.pathname === SEARCH;
  159. const do_channel = window.location.pathname === CHANNEL;
  160. const do_watch = window.location.pathname === WATCH;
  161.  
  162. const input = document.createElement("input");
  163. input.type = "text";
  164. input.id = "hkt_search";
  165. input.placeholder = "Search...";
  166. input.addEventListener("keydown", (e) => {
  167.     if (e.key === "Enter") {
  168.     let term = input.value.replace(/ /g, "+");
  169.     window.location.href = PROTOCOL + HKT_SEARCH_URL + term;
  170.   }
  171. }, false);
  172. document.getElementById("search-form").appendChild(input);
  173.  
  174. if (do_search || do_channel) {
  175.   let warning = document.getElementById("warning");
  176.     warning.children[0].innerHTML = "Loading...";
  177.   warning.children[1].style.display = "none";
  178.  
  179.     let main = document.getElementsByClassName("main")[0];
  180.   main.style.display = "none";
  181.   main.children[0].style.display = "none";    
  182.  
  183.   let vlist = document.getElementById("video-list");
  184.   if (vlist == null) {
  185.     vlist = document.createElement("div");
  186.     vlist.id = "video-list";
  187.     vlist.className = "row";
  188.     main.insertBefore(vlist, main.children[0]);
  189.   }
  190.  
  191.   let loadnext = document.createElement("button");
  192.   loadnext.className = "btn btn-primary btn-block";
  193.   loadnext.innerHTML = "Load More...";
  194.   loadnext.style.display = "none";
  195.   if (do_search) {
  196.     main.insertBefore(loadnext, main.children[1]);
  197.   } else {
  198.     main.insertBefore(loadnext, document.getElementById("main-footer"));
  199.   }
  200.  
  201.   let loading = document.createElement("button");
  202.   loading.className = "btn btn-secondary btn-block";
  203.   loading.innerHTML = "Loading...";
  204.   loading.style.display = "none";
  205.   main.insertBefore(loading, loadnext);
  206.  
  207.   let progress = function(address) {
  208.     getVideoEntries(
  209.       address,
  210.       function(rsp) {
  211.         for (let i = 0; i < rsp.videos.length; i++)
  212.           vlist.appendChild(createVideoTile(rsp.videos[i]));
  213.        
  214.         if (do_channel) {
  215.           document.title = rsp.videos[0].channel.name;
  216.         }
  217.  
  218.         warning.style.display = "none";
  219.         main.style.display = "block";
  220.         loading.style.display = "none";
  221.        
  222.         if (rsp.next !== "") {
  223.           loadnext.style.display = "block";
  224.           loadnext.onclick = function(ev) {
  225.             loadnext.style.display = "none";
  226.             loading.style.display = "block";
  227.             progress(rsp.next);
  228.           };
  229.         }
  230.       },
  231.       function() {
  232.         loading.style.display = "none";
  233.         loadnext.style.display = "block";
  234.         loadnext.innerHTML = "Request Timed Out - Try Again";
  235.         loadnext.onclick = function(ev) {
  236.           loadnext.style.display = "none";
  237.           loading.style.display = "block";
  238.           progress(address);
  239.         }
  240.     });
  241.   }
  242.  
  243.   if (do_search) {
  244.     progress(PROTOCOL + YTNOAD_SEARCH_URL + window.location.search.substring(3) + "&nocache=true");
  245.   } else {
  246.     progress(PROTOCOL + YTNOAD_CHANNEL_URL + window.location.search.substring(5));
  247.   }
  248. } else if (do_watch) {
  249.   GM.xmlHttpRequest({
  250.     method: "GET",
  251.     headers: {
  252.       "Accept": "text/html"
  253.     },
  254.     url: window.location.href.replace(HKT, YTNOAD),
  255.     timeout: 1000 * TIMEOUT,
  256.     ontimeout: function(rsp) {
  257.       console.log("TIMEOUT");
  258.     },
  259.     onload: function(rsp) {
  260.       let temp = document.createElement("span");
  261.       temp.innerHTML = rsp.responseText;
  262.            
  263.       let section = temp.getElementsByClassName("section")[0];
  264.       let channel_id = section.children[0].children[0].children[0].children[0].href;
  265.       channel_id = channel_id.substring(channel_id.indexOf("=") + 1);
  266.       let views = section.children[0].children[0].children[0].lastChild.data.substring(9);
  267.       let likes = "0";
  268.       let dislikes = "0";
  269.       let lds = section.children[0].children[0].children[1].innerHTML.split(" ");
  270.        
  271.       for (let i = 0; i < lds.length; i++) {
  272.         if (lds[i] !== "") {
  273.             if (lds[i] === "Likes:") {
  274.             likes = lds[i + 1].substring(0, lds[i++ + 1].indexOf("&"));
  275.           } else if (lds[i] === "Dislikes:") {
  276.             dislikes = lds[i + 1].substring(0, lds[i++ + 1].indexOf("&"));
  277.           }
  278.         }
  279.       }
  280.      
  281.       let description = section.children[1].children[0];
  282.       description.children[0].remove();
  283.       description = description.innerHTML;
  284.       let date = section.children[1].children[1].children[0].innerHTML.substring(11);
  285.      
  286.       let video_channel_name_el = document.getElementById("video-channel-name");
  287.       video_channel_name_el.style.borderBottom = "1px solid #727b84";
  288.       let channel_name = video_channel_name_el.innerHTML.substring(13);
  289.       let video_channel_link_el = document.createElement("a");
  290.       video_channel_link_el.href = CHANNEL + CHANNEL_INTROG + channel_id;
  291.       video_channel_link_el.innerHTML = channel_name;
  292.       video_channel_name_el.innerHTML = "Published by ";
  293.       video_channel_name_el.appendChild(video_channel_link_el);
  294.       video_channel_name_el.appendChild(document.createTextNode(" on "));
  295.       video_channel_name_el.appendChild(document.createTextNode(date));
  296.      
  297.       let description_el = document.getElementById("video-description");
  298.       description_el.innerHTML = description;
  299.      
  300.       let vstats_el = document.getElementById("video-stats");
  301.             let views_el = document.createElement("span");
  302.       views_el.innerHTML = "<i class='fa fa-eye'></i> " + views;
  303.       views_el.style.marginLeft = "20px";
  304.       vstats_el.appendChild(views_el);
  305.       let likes_el = document.createElement("span");
  306.       likes_el.innerHTML = "<i class='fa fa-thumbs-o-up'></i> " + likes;
  307.       likes_el.style.marginLeft = "20px";
  308.       vstats_el.appendChild(likes_el);
  309.       let dislikes_el = document.createElement("span");
  310.       dislikes_el.innerHTML = "<i class='fa fa-thumbs-o-down'></i> " + dislikes;
  311.       dislikes_el.style.marginLeft = "20px";
  312.       vstats_el.appendChild(dislikes_el);
  313.     }
  314.   });
  315. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement