Twitch Sort by Newest/Oldest

Sorts Twitch clips by newest or oldest on the 24-hour clips page

  1. // ==UserScript==
  2. // @name Twitch Sort by Newest/Oldest
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0
  5. // @description Sorts Twitch clips by newest or oldest on the 24-hour clips page
  6. // @author MahdeenSky
  7. // @match https://www.twitch.tv/*/clips?filter=clips&range=24hr
  8. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  9. // @grant none
  10. // @license GNU GPLv3
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. let sortByNewest = true;
  17. function sortClips() {
  18. console.log(`Sorting clips by ${sortByNewest ? 'newest' : 'oldest'}...`);
  19. const clipTowers = document.querySelectorAll('.ScTower-sc-1sjzzes-0');
  20. const clipTower = clipTowers[1];
  21. if (clipTower) {
  22. console.log("Found clip tower element:", clipTower);
  23. } else {
  24. console.error("Clip tower element not found!");
  25. return; // Exit if the main container is not found
  26. }
  27. const clipCards = Array.from(clipTower.querySelectorAll('.Layout-sc-1xcs6mc-0[data-a-target^="clips-card-"]'));
  28. console.log("Found", clipCards.length, "clip cards.");
  29. clipCards.sort((a, b) => {
  30. const elementA = a.querySelectorAll('.ScPositionCorner-sc-1shjvnv-1');
  31. const elementB = b.querySelectorAll('.ScPositionCorner-sc-1shjvnv-1');
  32. const timeA = elementA[elementA.length - 1].textContent.trim();
  33. const timeB = elementB[elementB.length - 1].textContent.trim();
  34. // edge case, if there is 'Yesterday' in the time, it should be considered as the oldest or newest
  35. if (timeA.includes('Yesterday')) {
  36. return sortByNewest ? -999 : 999;
  37. } else if (timeB.includes('Yesterday')) {
  38. return sortByNewest ? 999 : -999;
  39. }
  40. // handle hours ago and minutes ago cases
  41. let timeAValue = parseInt(timeA);
  42. let timeBValue = parseInt(timeB);
  43. if (timeA.includes('hour')) {
  44. timeAValue *= 60;
  45. }
  46. if (timeB.includes('hour')) {
  47. timeBValue *= 60;
  48. }
  49. return sortByNewest ? timeBValue - timeAValue : timeAValue - timeBValue;
  50. });
  51. clipTower.innerHTML = '';
  52. clipCards.forEach(card => clipTower.appendChild(card));
  53. console.log("Clips sorted successfully.");
  54. }
  55. // Create sort button
  56. const sortButton = document.createElement('button');
  57. sortButton.textContent = 'Sort by Newest';
  58. sortButton.style.backgroundColor = '#6441A5';
  59. sortButton.style.color = 'white';
  60. sortButton.style.padding = '10px 20px';
  61. sortButton.style.border = 'none';
  62. sortButton.style.cursor = 'pointer';
  63. sortButton.style.borderRadius = '5px';
  64. sortButton.style.marginTop = '10px';
  65. sortButton.addEventListener('click', () => {
  66. sortByNewest = !sortByNewest;
  67. sortButton.textContent = `Sort by ${sortByNewest ? 'Newest' : 'Oldest'}`;
  68. sortClips();
  69. });
  70. function addSortButton() {
  71. const sortContainer = document.querySelector('div[data-test-selector="sort"]');
  72. if (sortContainer) {
  73. console.log("Found sort container element:", sortContainer);
  74. sortContainer.appendChild(sortButton);
  75. console.log("Sort button added.");
  76. } else {
  77. console.log("Sort container element not found. Setting up observer...");
  78. const observer = new MutationObserver(mutations => {
  79. const sortContainer = document.querySelector('div[data-test-selector="sort"]');
  80. if (sortContainer) {
  81. console.log("Sort container element found by observer:", sortContainer);
  82. sortContainer.appendChild(sortButton);
  83. console.log("Sort button added.");
  84. observer.disconnect();
  85. }
  86. });
  87. observer.observe(document.body, { childList: true, subtree: true });
  88. }
  89. }
  90. addSortButton();
  91. })();