scientificamerican.com Paywall Bypass

Hooks react on scientificamerican.com to bypass paywalls :D

  1. // ==UserScript==
  2. // @name scientificamerican.com Paywall Bypass
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Hooks react on scientificamerican.com to bypass paywalls :D
  6. // @author November2246
  7. // @match https://*.scientificamerican.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=scientificamerican.com
  9. // @grant none
  10. // @license ISC
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14. const { log, warn, error, debug } = window.console;
  15.  
  16. // Object containing prop replacements, used in hook on JSX
  17. const propReplacements = {
  18. 'paywall_exempt': true,
  19. };
  20.  
  21. // Hooks React Fragments
  22. Object.defineProperty(Object.prototype, 'jsxs', {
  23. set(value) {
  24. if (this.Fragment === Symbol.for('react.fragment')) {
  25. hookJSX(this);
  26. }
  27. this._jsxs = value;
  28. },
  29. get() {
  30. return this._jsxs;
  31. }
  32. });
  33.  
  34. // Hooks JSX on the fragment
  35. function hookJSX(fragment) {
  36. if (typeof fragment.jsx !== 'function') return warn('fragment.jsx is not a function!', fragment.jsx);
  37. fragment.jsx = new Proxy(fragment.jsx, {
  38. apply(target, thisArg, argArr) {
  39. argArr = hookProps(argArr);
  40. return Reflect.apply(...arguments);
  41. },
  42. });
  43. }
  44.  
  45. // Hooks props on the JSX
  46. function hookProps(args) {
  47. if (!Array.isArray(args)) return args;
  48. args.forEach(arg => {
  49. if (typeof arg !== 'object') return; // Ignore functions
  50. if (typeof arg?.children !== 'object' || typeof arg?.children?.props !== 'object') return; // Find prop with children object containing props
  51.  
  52. const props = arg.children.props;
  53. if (!props.data) return; // Skip props without data
  54.  
  55. Object.entries(propReplacements).forEach(([key, value]) => {
  56. props.data[key] = value;
  57. });
  58. });
  59. return args;
  60. }