Guest User

4soundpost.user.js

a guest
Aug 29th, 2023
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 8.38 KB | Source Code | 0 0
  1. // ==UserScript==
  2. // @name        4soundpost
  3. // @namespace   b4k
  4. // @description Plays audio associated with images on 4chan. | Modified
  5. // @author      Bakugo
  6. // @version     1.7.1
  7. // @match       *://boards.4chan.org/*
  8. // @match       *://boards.4channel.org/*
  9. // @include     *://yuki.la/*
  10. // @run-at      document-start
  11. // @grant       none
  12. // @icon        https://abs-0.twimg.com/emoji/v2/svg/1f340.svg
  13. // ==/UserScript==
  14.  
  15. (function() {
  16.     var doInit;
  17.     var doParseFile;
  18.     var doParseFiles;
  19.     var doPlayFile;
  20.     var doMakeKey;
  21.  
  22.     var allow;
  23.     var players;
  24.     var isChanX;
  25.  
  26.     allow = [
  27.         "4cdn.org",
  28.         "catbox.moe",
  29.         "dmca.gripe",
  30.         "lewd.se",
  31.         "pomf.cat",
  32.         "zz.ht"
  33.     ];
  34.  
  35.     document.addEventListener(
  36.         "DOMContentLoaded",
  37.         function (event) {
  38.             setTimeout(
  39.                 function () {
  40.                     if (
  41.                         document.body.classList.contains("ws") ||
  42.                         document.body.classList.contains("nws")
  43.                     ) {
  44.                         isChanX = false;
  45.                         doInit();
  46.                     }
  47.                 },
  48.                 (1)
  49.             );
  50.         }
  51.     );
  52.  
  53.     document.addEventListener(
  54.         "4chanXInitFinished",
  55.         function (event) {
  56.             if (
  57.                 document.documentElement.classList.contains("fourchan-x") &&
  58.                 document.documentElement.classList.contains("sw-yotsuba")
  59.             ) {
  60.                 isChanX = true;
  61.                 doInit();
  62.             }
  63.         }
  64.     );
  65.  
  66.     doInit = function () {
  67.         var observer;
  68.  
  69.         if (players) {
  70.             return;
  71.         }
  72.  
  73.         players = {};
  74.  
  75.         doParseFiles(document.body);
  76.  
  77.         observer =
  78.             new MutationObserver(
  79.                 function (mutations) {
  80.                     mutations.forEach(
  81.                         function (mutation) {
  82.                             if (mutation.type === "childList") {
  83.                                 mutation.addedNodes.forEach(
  84.                                     function (node) {
  85.                                         if (node.nodeType === Node.ELEMENT_NODE) {
  86.                                             doParseFiles(node);
  87.                                             doPlayFile(node);
  88.                                         }
  89.                                     }
  90.                                 );
  91.                             }
  92.                         }
  93.                     );
  94.                 }
  95.             );
  96.  
  97.         observer
  98.             .observe(
  99.                 document.body,
  100.                 {
  101.                     childList: true,
  102.                     subtree: true
  103.                 }
  104.             );
  105.     };
  106.  
  107.     doParseFile = function (file) {
  108.         var fileLink;
  109.         var fileName;
  110.         var key;
  111.         var match;
  112.         var player;
  113.         var link;
  114.  
  115.         if (!file.classList.contains("file")) {
  116.             return;
  117.         }
  118.  
  119.         if (isChanX) {
  120.             fileLink = file.querySelector(".fileText .file-info > a");
  121.         } else {
  122.             fileLink = file.querySelector(".fileText > a");
  123.         }
  124.  
  125.         if (!fileLink) {
  126.             return;
  127.         }
  128.  
  129.         if (!fileLink.href) {
  130.             return;
  131.         }
  132.  
  133.         fileName = null;
  134.     var __linknode = null;    //MOD
  135.  
  136.         if (isChanX) {
  137.             [
  138.                 file.querySelector(".fileText .file-info .fnfull"),
  139.                 file.querySelector(".fileText .file-info > a")
  140.             ].some(
  141.                 function (node) {
  142.                     if (node) {
  143.                         if (node.textContent) {
  144.                             fileName = node.textContent;
  145.               __linknode = node;    //MOD
  146.                             return true;
  147.                         }
  148.                     }
  149.  
  150.                     return false;
  151.                 }
  152.             );
  153.         } else {
  154.             [
  155.                 file.querySelector(".fileText"),
  156.                 file.querySelector(".fileText > a")
  157.             ].some(
  158.                 function (node) {
  159.                     if (node) {
  160.                         if (node.title) {
  161.                             fileName = node.title;
  162.               __linknode = node;    //MOD
  163.                             return true;
  164.                         }
  165.  
  166.                         if (
  167.                             node.tagName === "A" &&
  168.                             node.textContent
  169.                         ) {
  170.                             fileName = node.textContent;
  171.               __linknode = node;    //MOD
  172.                             return true;
  173.                         }
  174.                     }
  175.  
  176.                     return false;
  177.                 }
  178.             );
  179.         }
  180.  
  181.         if (!fileName) {
  182.             return;
  183.         }
  184.  
  185.         fileName = fileName.replace(/\-/, "/");
  186.  
  187.         key = doMakeKey(fileLink.href);
  188.  
  189.         if (!key) {
  190.             return;
  191.         }
  192.  
  193.         if (players[key]) {
  194.             return;
  195.         }
  196.  
  197.         match = fileName.match(/[\[\(\{](?:audio|sound)[ \=\:\|\$](.*?)[\]\)\}]/i);
  198.  
  199.         if (!match) {
  200.             return;
  201.         }
  202.  
  203.         link = match[1];
  204.  
  205.         if (link.includes("%")) {
  206.             try {
  207.                 link = decodeURIComponent(link);
  208.             } catch (error) {
  209.                 return;
  210.             }
  211.         }
  212.  
  213.         if (link.match(/^(https?\:)?\/\//) === null) {
  214.             link = (location.protocol + "//" + link);
  215.         }
  216.  
  217.     //MOD START
  218.  
  219.     if(__linknode.tagName === "A")
  220.     {
  221.       try
  222.       {
  223.         let __br  = document.createElement("BR");
  224.         let __txt = document.createTextNode(" Sound: ");
  225.         let __a   = document.createElement("A");
  226.         let __lnk = document.createTextNode(link);
  227.         __a.href = link;
  228.         __linknode.parentNode.appendChild(__br);
  229.         __linknode.parentNode.appendChild(__txt);
  230.         __linknode.parentNode.appendChild(__a);
  231.         __a.appendChild(__lnk);
  232.       }
  233.       catch(error)
  234.       {
  235.         //
  236.       }
  237.     }
  238.  
  239.     //MOD END
  240.  
  241.         try {
  242.             link = new URL(link);
  243.         } catch (error) {
  244.             return;
  245.         }
  246.  
  247.         if (
  248.             allow.some(
  249.                 function (item) {
  250.                     return (
  251.                         link.hostname.toLowerCase() === item ||
  252.                         link.hostname.toLowerCase().endsWith("." + item)
  253.                     );
  254.                 }
  255.             ) == false
  256.         ) {
  257.             return;
  258.         }
  259.  
  260.         player = new Audio();
  261.  
  262.         player.preload = "none";
  263.         player.volume = 0.50;
  264.         player.loop = true;
  265.  
  266.         player.src = link.href;
  267.  
  268.         players[key] = player;
  269.     };
  270.  
  271.     doParseFiles = function (target) {
  272.         target.querySelectorAll(".post")
  273.             .forEach(
  274.                 function (post) {
  275.                     if (post.parentElement.parentElement.id === "qp") {
  276.                         return;
  277.                     }
  278.  
  279.                     if (post.parentElement.classList.contains("noFile")) {
  280.                         return;
  281.                     }
  282.  
  283.                     post.querySelectorAll(".file")
  284.                         .forEach(
  285.                             function (file) {
  286.                                 doParseFile(file);
  287.                             }
  288.                         );
  289.                 }
  290.             );
  291.     };
  292.  
  293.     doPlayFile = function (target) {
  294.         var key;
  295.         var player;
  296.         var interval;
  297.  
  298.         if (isChanX) {
  299.             if (!(
  300.                 target.id === "ihover" ||
  301.                 target.className === "full-image"
  302.             )) {
  303.                 return;
  304.             }
  305.         } else {
  306.             if (!(
  307.                 target.id === "image-hover" ||
  308.                 target.className === "expanded-thumb" ||
  309.                 target.className === "expandedWebm"
  310.             )) {
  311.                 return;
  312.             }
  313.         }
  314.  
  315.         if (!target.src) {
  316.             return;
  317.         }
  318.  
  319.         key = doMakeKey(target.src);
  320.  
  321.         if (!key) {
  322.             return;
  323.         }
  324.  
  325.         player = players[key];
  326.  
  327.         if (!player) {
  328.             return;
  329.         }
  330.  
  331.         if (!player.paused) {
  332.             if (player.dataset.play == 1) {
  333.                 if (isChanX) {
  334.                     return;
  335.                 } else {
  336.                     player.dataset.again = 1;
  337.                 }
  338.             } else {
  339.                 player.pause();
  340.             }
  341.         }
  342.  
  343.         if (player.dataset.play != 1){
  344.             player.dataset.play = 1;
  345.             player.dataset.again = 0;
  346.             player.dataset.moveTime = 0;
  347.             player.dataset.moveLast = 0;
  348.         }
  349.  
  350.         switch (target.tagName) {
  351.             case "IMG":
  352.                 player.loop = true;
  353.  
  354.                 if (player.dataset.again != 1) {
  355.                     player.currentTime = 0;
  356.                     player.play();
  357.                 }
  358.  
  359.                 break;
  360.  
  361.             case "VIDEO":
  362.                 player.loop = false;
  363.                 player.currentTime = target.currentTime;
  364.                 player.play();
  365.                 break;
  366.  
  367.             default:
  368.                 return;
  369.         }
  370.  
  371.         if (player.paused) {
  372.             document.dispatchEvent(
  373.                 new CustomEvent(
  374.                     "CreateNotification",
  375.                     {
  376.                         bubbles: true,
  377.                         detail: {
  378.                             type: "warning",
  379.                             content: "Your browser blocked autoplay, click anywhere on the page to activate it and try again.",
  380.                             lifetime: 5
  381.                         }
  382.                     }
  383.                 )
  384.             );
  385.         }
  386.  
  387.         interval =
  388.             setInterval(
  389.                 function () {
  390.                     if (document.body.contains(target)) {
  391.                         if (target.tagName === "VIDEO") {
  392.                             if (target.currentTime != (+player.dataset.moveLast)) {
  393.                                 player.dataset.moveTime = Date.now();
  394.                                 player.dataset.moveLast = target.currentTime;
  395.                             }
  396.  
  397.                             if (player.duration != NaN) {
  398.                                 if (
  399.                                     target.paused == true ||
  400.                                     target.duration == NaN ||
  401.                                     target.currentTime > player.duration ||
  402.                                     ((Date.now() - (+player.dataset.moveTime)) > 300)
  403.                                 ) {
  404.                                     if (!player.paused) {
  405.                                         player.pause();
  406.                                     }
  407.                                 } else {
  408.                                     if (
  409.                                         player.paused ||
  410.                                         Math.abs(target.currentTime - player.currentTime) > 0.100
  411.                                     ) {
  412.                                         player.currentTime = target.currentTime;
  413.                                     }
  414.  
  415.                                     if (player.paused) {
  416.                                         player.play();
  417.                                     }
  418.                                 }
  419.                             }
  420.                         }
  421.                     } else {
  422.                         clearInterval(interval);
  423.  
  424.                         if (player.dataset.again == 1) {
  425.                             player.dataset.again = 0;
  426.                         } else {
  427.                             player.pause();
  428.                             player.dataset.play = 0;
  429.                         }
  430.                     }
  431.                 },
  432.                 (1000/30)
  433.             );
  434.     };
  435.  
  436.     doMakeKey = function (link) {
  437.         var match;
  438.  
  439.         if(link.includes('yuki')){
  440.             match = link.match(/\.(?:yuki)\.la\/(.+?)\/(.+?)\/(.+?)\.(.+?)$/);
  441.  
  442.             if (match) {
  443.                 return (match[3] + "." + match[4]);
  444.           }
  445.         }
  446.         else{
  447.             match = link.match(/\.(?:4cdn|4chan)\.org\/(.+?)\/(\d+?)\.(.+?)$/);
  448.  
  449.             if (match) {
  450.                 return (match[1] + "." + match[2]);
  451.           }
  452.         }
  453.  
  454.         return null;
  455.     };
  456. })();
Add Comment
Please, Sign In to add comment