Twitch Enhancer

aiueo

目前為 2025-02-23 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Twitch Enhancer
  3. // @name:en Twitch Enhancer
  4. // @name:ja Twitch Enhancer
  5. // @namespace https://greasyfork.org/ja/users/941284-ぐらんぴ
  6. // @version 2025-02-23
  7. // @description aiueo
  8. // @description:en aiueo
  9. // @description:ja aiueo
  10. // @author ぐらんぴ
  11. // @match https://www.twitch.tv/*
  12. // @icon https://www.google.com/s2/favicons?sz=64&domain=twitch.tv
  13. // @license MIT
  14. // @run-at document-start
  15. // @grant none
  16. // ==/UserScript==
  17.  
  18. const origFetch = window.fetch;
  19. window.fetch = async function(url, init) {
  20. let res = await origFetch(url, init);
  21. // Check for null body status codes
  22. if(res.status === 204 || res.status === 205) {
  23. return res; // Return the response as is for these status codes
  24. }
  25. let data;
  26. try{
  27. // Check if the response is not empty before parsing
  28. const text = await res.text();
  29. data = text ? JSON.parse(text) : {};
  30. }catch(err){
  31. console.log('Failed to parse JSON:', err);
  32. return res;
  33. }
  34.  
  35. // console.log(url, data, data.length);
  36. try{
  37. if(url.startsWith('https://edge.ads.twitch.tv/ads')){//Prime Pop-up
  38. data = '';
  39. }
  40. if(url == 'https://gql.twitch.tv/gql#origin=twilight'){// twilight
  41. data.forEach(i =>{
  42. // login
  43. if(i.extensions.operationName == 'CoreActionsCurrentUser'){
  44. i.data.currentUser.roles.isStaff = true
  45. }
  46. if(i.extensions.operationName == 'FrontPageNew_User'){// followedGames
  47. i.data.currentUser.roles.isStaff = true
  48. }
  49. // moderator -- unstable
  50. if(i.extensions.operationName == "PlayerTrackingContextQuery"){
  51. i.data.currentUser.hasTurbo = true
  52. i.data.currentUser.isStaff = true
  53. i.data.user.self.isModerator = true
  54. i.data.user.self.subscriptionBenefit = true
  55. i.data.user.subscriptionProducts[0].hasAdFree = true
  56. i.data.user.subscriptionProducts[1].hasAdFree = true
  57. i.data.user.subscriptionProducts[2].hasAdFree = true
  58. }
  59. if(i.extensions.operationName == 'ChatRestrictions'){
  60. i.data.channel.self.isFirstTimeChatter = true
  61. i.data.channel.self.isModerator = true
  62. i.data.channel.self.isVIP = true
  63. i.data.channel.self.subscriptionBenefit = true
  64. i.data.currentUser.isPhoneNumberVerified = true
  65. }
  66. if(i.extensions.operationName == "CommunityPointsRewardRedemptionContext"){
  67. i.data.community.self.isModerator = true
  68. i.data.community.self.subscriptionBenefit = true
  69. }
  70. if(i.extensions.operationName == 'ChannelPointsContext'){
  71. i.data.community.self.isModerator = true
  72. }
  73. if(i.extensions.operationName == 'Chat_ChannelData'){
  74. i.data.channel.self.isEditor = true
  75. i.data.channel.self.isModerator = true
  76. i.data.channel.self.isVIP = true
  77. }
  78. if(i.extensions.operationName == 'StreamChat'){
  79. i.data.channel.self.isChannelMember = true
  80. i.data.channel.self.isModerator = true
  81. i.data.channel.self.subscriptionBenefit = true
  82. }
  83. if(i.extensions.operationName == 'CurrentUserModeratorStatus'){
  84. i.data.user.self.isModerator = true
  85. }
  86. });
  87. }
  88. }catch(err){
  89. console.log('err modifying data:', err);
  90. }
  91.  
  92. return new Response(JSON.stringify(data), {
  93. headers: res.headers,
  94. status: res.status,
  95. statusText: res.statusText,
  96. });
  97. };
  98.  
  99. const origAppendChild = Element.prototype.appendChild;
  100. Element.prototype.appendChild = function(...args){
  101. try{
  102. if(args[0].className.includes('ScCoreButton-sc-ocjdkq-0')){// Auto Channel Points Claimer
  103. document.querySelectorAll(".claimable-bonus__icon")[0].click()
  104. }
  105. }catch(err){// console.log(err);
  106. }
  107. return origAppendChild.apply(this, args);
  108. };