ph_user_video

redirect link to user video list / muti select & copy video links

  1. // ==UserScript==
  2. // @name ph_user_video
  3. // @namespace https://github.com/x94fujo6rpg/SomeTampermonkeyScripts
  4. // @version 0.11
  5. // @description redirect link to user video list / muti select & copy video links
  6. // @author x94fujo6
  7. // @match https://*.pornhub.com/*
  8. // ==/UserScript==
  9.  
  10.  
  11. (function () {
  12. 'use strict';
  13. let itemIndex = 0;
  14. let trycount = 0;
  15. let listener = false;
  16.  
  17. window.onload = startScript();
  18.  
  19. function startScript() {
  20. if (document.visibilityState == "visible") {
  21. if (listener) document.removeEventListener("visibilitychange", startScript);
  22. main();
  23. } else {
  24. document.addEventListener("visibilitychange", startScript);
  25. listener = true;
  26. }
  27. }
  28.  
  29. function main() {
  30. myCss();
  31. let link = document.location.href,
  32. target_list = ["/videos", "/playlist", "video/search",];
  33.  
  34. //enable this if you want auto switch to EN
  35. //switchLan();
  36.  
  37. if (link.includes("viewkey")) {
  38. setLink();
  39. } else if (target_list.some(t => link.includes(t))) {
  40. reDirect(link);
  41. } else {
  42. replaceLink(".usernameWrap");
  43. }
  44.  
  45. function switchLan() {
  46. let host = document.location.host,
  47. target_host = "www.pornhub.com";
  48. if (host != target_host) {
  49. setTimeout(() => {
  50. document.querySelector(`li[data-lang="en"] a`).click();
  51. }, 1000);
  52. }
  53. }
  54.  
  55. function setLink() {
  56. let info = document.querySelector(".video-detailed-info");
  57. info = info.querySelector(".usernameBadgesWrapper");
  58. if (!info) return print("no user info");
  59. info = info.querySelector("a");
  60. let username = info.textContent;
  61. print("username", username);
  62.  
  63. let link = `${info.href}/videos/public`;
  64. info.setAttribute("href", link);
  65.  
  66. replaceLink(".usernameWrap");
  67. markSameUser(username);
  68.  
  69. let button = newButton("myButtonB", "Copy Video link", copyLink);
  70. let div = document.createElement("div");
  71. div.appendChild(button);
  72.  
  73. let pos = document.querySelector("#player");
  74. pos.insertAdjacentElement("afterend", div);
  75.  
  76. function copyLink() {
  77. let link = window.location.href;
  78. navigator.clipboard.writeText(link);
  79. }
  80. }
  81.  
  82. function markSameUser(username = "") {
  83. mark("#relatedVideosCenter");
  84. mark("#recommendedVideosVPage");
  85.  
  86. function mark(css_selector) {
  87. let target = document.querySelector(css_selector);
  88. if (target) {
  89. target = target.querySelectorAll("li");
  90. if (target) {
  91. target.forEach(e => {
  92. let uploader = e.querySelector(".usernameWrap a");
  93. if (uploader) {
  94. if (uploader.textContent == username) {
  95. e.style = "border: red 0.2rem solid;";
  96. }
  97. }
  98. });
  99. }
  100. }
  101. }
  102. }
  103.  
  104. function replaceLink(css_selector) {
  105. let target = document.querySelectorAll(css_selector);
  106. if (target) {
  107. target.forEach(e => {
  108. let a = e.querySelector("a");
  109. if (a) if (!a.href.includes("/videos")) a.href = `${a.href}/videos/public`;
  110. });
  111. } else {
  112. print(`target ${css_selector} not found`);
  113. }
  114. }
  115.  
  116. function reDirect(link) {
  117. let vids = document.querySelector(".profileVids"); // profileVids videoUList
  118. if (!vids) {
  119. if (link.includes("/public")) {
  120. console.log("public");
  121. setTimeout(() => document.location.href = link.replace("/public", ""), 1000);
  122. }
  123. if (link.includes("/playlist")) {
  124. console.log("playlist");
  125. vids = document.querySelector(".container.playlistSectionWrapper");
  126. if (vids) mutiSelect(vids);
  127. }
  128. if (link.includes("/search")) {
  129. console.log("search");
  130. vids = document.querySelector("#videoSearchResult").parentElement;
  131. if (vids) mutiSelect(vids);
  132. }
  133. console.log("can't found video list, abort");
  134. return;
  135. } else {
  136. mutiSelect(vids);
  137. }
  138.  
  139. function mutiSelect(vid_list) {
  140. let
  141. select_box = document.createElement("div"),
  142. textbox = document.createElement("textarea"),
  143. textbox_style = `
  144. width: 100%;
  145. height: auto;
  146. display: block;
  147. margin: auto;
  148. `;
  149.  
  150. select_box.style = `
  151. display: flex;
  152. text-align: center;
  153. flex-wrap: wrap;
  154. width: 50%;
  155. margin: auto;
  156. `;
  157. select_box.innerHTML = `<textarea id="selected_vid_list" rows="10" cols="70" style="${textbox_style}"></textarea>`;
  158. vid_list.insertAdjacentElement("afterbegin", select_box);
  159.  
  160. let button,
  161. button_class = "myButton line-4-item",
  162. button_box = document.createElement("div");
  163. button_box.style = `width: 100%;`;
  164. [
  165. { text: "Select All", click: secectAll },
  166. { text: "Unselect All", click: unsecectAll },
  167. { text: "Invert Select", click: invertSecect },
  168. { text: "Copy", click: copyAll },
  169. ].forEach(o => {
  170. button = newButton(button_class, o.text, o.click);
  171. button_box.appendChild(button);
  172. });
  173. select_box.appendChild(button_box);
  174.  
  175. vid_list = vid_list.querySelectorAll(".pcVideoListItem");
  176. addCheckbox(vid_list);
  177.  
  178. let more = document.getElementById("moreDataBtn");
  179. if (more) {
  180. more.addEventListener("click", loadEvent);
  181. let ele = document.createElement("span");
  182. ele.textContent = "Load button found, this user video list is ajax. Recommend using other tools to extract the list.";
  183. textbox.insertAdjacentElement("beforebegin", ele);
  184. }
  185.  
  186. function addCheckbox(nodelist) {
  187. let e, key, vlink;
  188. console.log(`itemIndex:${itemIndex}, nodecount:${nodelist.length}`);
  189. for (itemIndex; itemIndex < nodelist.length; itemIndex++) {
  190. e = nodelist[itemIndex];
  191. key = e.attributes["data-video-vkey"].value;
  192. vlink = `https://www.pornhub.com/view_video.php?viewkey=${key}`;
  193.  
  194. let ck = Object.assign(document.createElement("input"), {
  195. type: "checkbox",
  196. name: "selected_vid_list",
  197. value: vlink,
  198. });
  199. ck.addEventListener("click", updateTextBox);
  200.  
  201. let label = Object.assign(document.createElement("label"), { className: "myLable", });
  202. label.appendChild(ck);
  203.  
  204. let div = Object.assign(document.createElement("div"), { textContent: "Add to List", });
  205. label.appendChild(div);
  206.  
  207. div = document.createElement("div");
  208. div.appendChild(label);
  209.  
  210. let pos = e.querySelector(".thumbnail-info-wrapper");
  211. pos.insertAdjacentElement("beforebegin", document.createElement("br"));
  212. pos.insertAdjacentElement("beforebegin", div);
  213.  
  214. pos = e.querySelector("span.title").querySelector("a");
  215. pos.removeAttribute("href");
  216. }
  217. itemIndex = nodelist.length;
  218. }
  219.  
  220. function loadEvent() {
  221. let vids = document.querySelector(".profileVids").querySelectorAll(".pcVideoListItem");
  222. if (vids.length === itemIndex) {
  223. if (trycount < 100) {
  224. console.log(`no new item found, waiting for page to load [retry:${trycount}]`);
  225. setTimeout(loadEvent, 100);
  226. } else {
  227. console.log("retry too much, script stop");
  228. }
  229. trycount++;
  230. } else {
  231. trycount = 0;
  232. addCheckbox(vids);
  233. }
  234. }
  235.  
  236. function copyAll() {
  237. let textbox = document.getElementById("selected_vid_list");
  238. navigator.clipboard.writeText(textbox.value);
  239. }
  240.  
  241. function invertSecect() {
  242. let inputs = document.querySelectorAll("input[name='selected_vid_list']");
  243. inputs.forEach(e => {
  244. if (e.checked) {
  245. e.checked = false;
  246. } else {
  247. e.checked = true;
  248. }
  249. });
  250. updateTextBox();
  251. }
  252.  
  253. function unsecectAll() {
  254. let inputs = document.querySelectorAll("input[name='selected_vid_list']:checked");
  255. inputs.forEach(e => {
  256. e.checked = false;
  257. });
  258. updateTextBox();
  259. }
  260.  
  261. function secectAll() {
  262. let inputs = document.querySelectorAll("input[name='selected_vid_list']");
  263. inputs.forEach(e => {
  264. if (!e.checked) e.checked = true;
  265. });
  266. updateTextBox();
  267. }
  268.  
  269. function updateTextBox() {
  270. let inputs = document.querySelectorAll("input[name='selected_vid_list']:checked");
  271. let newtext = "";
  272. if (inputs) {
  273. inputs.forEach(ck => {
  274. if (!newtext.includes(ck.value)) newtext += `${ck.value}\n`;
  275. });
  276. }
  277. let box = document.getElementById("selected_vid_list");
  278. box.value = newtext;
  279. }
  280. }
  281. }
  282. }
  283.  
  284. function print(...any) {
  285. console.log(...any);
  286. }
  287.  
  288. function newButton(bclass, btext, handeler) {
  289. let button = document.createElement("button");
  290. Object.assign(button, {
  291. className: bclass,
  292. textContent: btext,
  293. onclick: handeler,
  294. });
  295. return button;
  296. }
  297.  
  298. function myCss() {
  299. let s = document.createElement("style");
  300. s.className = "myCssSheet";
  301. document.head.appendChild(s);
  302. s.textContent = `
  303. .added {
  304. display:initial !important;
  305. }
  306.  
  307. .myButtonB {
  308. position: relative;
  309. padding: 1rem;
  310. width: 100%;
  311. border-style: solid;
  312. font-size: 1rem;
  313. background: transparent;
  314. color: white;
  315. }
  316.  
  317. .myButton {
  318. position: relative;
  319. padding: 0.5rem 0;
  320. margin: 0.5rem;
  321. width: max-content;
  322. font-size: 1rem;
  323. }
  324.  
  325. .line-4-item {
  326. max-width: 100%;
  327. width: calc(80% / 4);
  328. }
  329.  
  330. .myButton:active, .myButtonB:active {
  331. background-color: DeepPink;
  332. }
  333.  
  334. .myLable {
  335. position: relative;
  336. width: auto;
  337. padding: 0.5rem;
  338. border-style: solid;
  339. border-width: 0.1rem;
  340. border-color: gray;
  341. display: flex;
  342. }
  343.  
  344. .myLable>input {
  345. position: relative;
  346. margin: auto;
  347. margin-left: 0rem;
  348. margin-right: 0.2rem;
  349. }
  350.  
  351. .myLable>div {
  352. position: relative;
  353. margin: 0.1rem;
  354. }
  355. `;
  356. }
  357. })();