Advertisement
Guest User

Untitled

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