theYNC.com Underground bypass

Watch theYNC Underground videos without needing an account

当前为 2024-12-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name theYNC.com Underground bypass
  3. // @description Watch theYNC Underground videos without needing an account
  4. // @require https://update.greasyfork.org/scripts/421384/1134973/GM_fetch.js
  5. // @grant GM_xmlhttpRequest
  6. // @connect media.theync.com
  7. // @namespace Violentmonkey Scripts
  8. // @match https://*.theync.com/*
  9. // @match https://*.theync.net/*
  10. // @match https://*.theync.com/*
  11. // @match https://theync.com/*
  12. // @match https://theync.net/*
  13. // @match https://theync.com/*
  14. // @grant none
  15. // @version 2.2
  16. // @license MIT
  17. // @author -
  18. // ==/UserScript==
  19. function getTheYNCVideoURL(url) {
  20. for (const [, group_url] of url.matchAll(
  21. /\/media\/thumbs\/(.*?)\.[a-zA-Z0-9_.-]*\//gm
  22. )) {
  23. return `https://media.theync.com/videos/${group_url}.mp4`;
  24. }
  25. }
  26. function waitForElement(selector) {
  27. return new Promise((resolve) => {
  28. {
  29. const element = document.querySelector(selector);
  30. if (element) {
  31. return resolve(element);
  32. }
  33. }
  34.  
  35. const observer = new MutationObserver(() => {
  36. const element = document.querySelector(selector);
  37. if (element) {
  38. observer.disconnect();
  39. resolve(element);
  40. }
  41. });
  42.  
  43. // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
  44. observer.observe(document.body, {
  45. childList: true,
  46. subtree: true,
  47. });
  48. });
  49. }
  50.  
  51. waitForElement(".content-block").then((contentBlock) => {
  52. for (const element of contentBlock.querySelectorAll(
  53. ".upgrade-profile > .upgrade-info-block"
  54. )) {
  55. const thumbnailURL = element.querySelector(
  56. ".image-block > .image > img"
  57. ).src;
  58. if (!thumbnailURL) continue;
  59. const videoURL = getTheYNCVideoURL(thumbnailURL);
  60. if (!videoURL) continue;
  61. GM_fetch(videoURL, { method: "head" }).then((response) => {
  62. if (response.status !== 200) {
  63. return;
  64. }
  65. location.href = videoURL;
  66. });
  67.  
  68. return;
  69. }
  70. for (const element of contentBlock.querySelectorAll(".inner-block > a")) {
  71. const undergroundLogo = element.querySelector(".item-info > .border-gold");
  72. if (!undergroundLogo) continue;
  73.  
  74. const thumbnailURL = element.querySelector(".image > img").src;
  75. if (!thumbnailURL) continue;
  76. const videoURL = getTheYNCVideoURL(thumbnailURL);
  77. if (!videoURL) continue;
  78.  
  79. GM_fetch(videoURL, { method: "head" }).then((response) => {
  80. if (response.status === 200) {
  81. undergroundLogo.textContent = "BYPASSED";
  82. undergroundLogo.style.backgroundColor = "green";
  83. element.href = videoURL;
  84. return;
  85. }
  86. GM_fetch(`https://archive.org/wayback/available?url=${element.href}`, {
  87. method: "GET",
  88. })
  89. .then((response) => response.json())
  90. .then(({ archived_snapshots }) => {
  91. if (!archived_snapshots.closest) {
  92. return;
  93. }
  94. undergroundLogo.textContent = "ARCHIVED";
  95. undergroundLogo.style.backgroundColor = "blue";
  96. element.href = archived_snapshots.closest.url;
  97. });
  98. });
  99. }
  100. });