Platform Spoofer

Modify platform Only.

目前为 2025-03-18 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Platform Spoofer
  3. // @namespace https://viayoo.com/
  4. // @version 0.4
  5. // @description Modify platform Only.
  6. // @author Via
  7. // @match *://*/*
  8. // @exclude *://rebang.today/*
  9. // @exclude *://*.github.com/*
  10. // @exclude *://scriptcat.org/*
  11. // @exclude *://greasyfork.org/*
  12. // @exclude *://github.com/*
  13. // @exclude *://*.google.*/*
  14. // @exclude *://x.com/*
  15. // @exclude *://twitter.com/*
  16. // @exclude *://*.bing.*/*
  17. // @exclude *://*.baidu.*/*
  18. // @exclude *://*.yandex.*/*
  19. // @exclude *://*.iqiyi.com/*
  20. // @exclude *://*.qq.com/*
  21. // @exclude *://*.v.qq.com/*
  22. // @exclude *://*.sohu.com/*
  23. // @exclude *://*.mgtv.com/*
  24. // @exclude *://*.ifeng.com/*
  25. // @exclude *://*.pptv.com/*
  26. // @exclude *://*.sina.com.cn/*
  27. // @license MIT
  28. // @grant none
  29. // @run-at document-start
  30. // ==/UserScript==
  31.  
  32. (function() {
  33. 'use strict';
  34.  
  35. const FAKE_PLATFORM = 'Mac';
  36. const platformGetter = () => FAKE_PLATFORM;
  37. if (navigator.platform === FAKE_PLATFORM) return;
  38. const descriptor = Object.getOwnPropertyDescriptor(navigator, 'platform');
  39. if (descriptor?.configurable) {
  40. Object.defineProperty(navigator, 'platform', {
  41. get: platformGetter,
  42. configurable: true,
  43. enumerable: true
  44. });
  45. if (navigator.platform === FAKE_PLATFORM) return;
  46. } else if (navigator.__defineGetter__) {
  47. navigator.__defineGetter__('platform', platformGetter);
  48. if (navigator.platform === FAKE_PLATFORM) return;
  49. }
  50.  
  51. const spoofNavigator = new Proxy(navigator, {
  52. get(target, prop) {
  53. return prop === 'platform' ? FAKE_PLATFORM : Reflect.get(target, prop);
  54. }
  55. });
  56.  
  57. try {
  58. Object.defineProperty(window, 'navigator', {
  59. value: spoofNavigator,
  60. writable: false,
  61. configurable: true
  62. });
  63. } catch (e) {
  64. console.warn('Navigator redefinition failed:', e);
  65. window.navigator = spoofNavigator;
  66. }
  67.  
  68. const protoDescriptor = Object.getOwnPropertyDescriptor(Navigator.prototype, 'platform');
  69. if (protoDescriptor?.configurable) {
  70. Object.defineProperty(Navigator.prototype, 'platform', {
  71. get: platformGetter,
  72. configurable: true,
  73. enumerable: true
  74. });
  75. }
  76. const originalIndexOf = String.prototype.indexOf;
  77. const blockedTerms = new Set(['Win', 'Linux', 'X11']);
  78. String.prototype.indexOf = function(searchString) {
  79. if (this === FAKE_PLATFORM) {
  80. if (blockedTerms.has(searchString)) return -1;
  81. if (searchString === 'Mac') return 0;
  82. }
  83. return originalIndexOf.call(this, searchString);
  84. };
  85.  
  86. // 仅在必要时添加DOMContentLoaded监听
  87. if (document.readyState === 'loading' && navigator.platform !== FAKE_PLATFORM) {
  88. document.addEventListener('DOMContentLoaded', () => {
  89. if (navigator.platform !== FAKE_PLATFORM) {
  90. Object.defineProperty(window, 'navigator', {
  91. value: new Proxy(navigator, {
  92. get: (target, prop) => prop === 'platform' ? FAKE_PLATFORM : target[prop]
  93. }),
  94. writable: false
  95. });
  96. }
  97. }, {
  98. once: true
  99. });
  100. }
  101. })();