Bandcamp: I'm Not A Fan

Removes playback limitation and dialog "The time has come to open thy heart/wallet"

  1. // ==UserScript==
  2. // @name Bandcamp: I'm Not A Fan
  3. // @name:ru Bandcamp: Я не фанат
  4. // @description Removes playback limitation and dialog "The time has come to open thy heart/wallet"
  5. // @description:ru Снимает ограничение воспроизведений и убирает диалог "Пришло время открыть свое сердце/кошелек"
  6. // @namespace bc-inotafan.user.js
  7. // @version 1.2.0
  8. // @license MIT
  9. // @author askornot
  10. // @icon https://s4.bcbits.com/img/favicon/safari-pinned-tab.svg
  11. // @match https://*.bandcamp.com/*
  12. // @homepageURL https://greasyfork.org/ru/scripts/438039-bandcamp-i-m-not-a-fan
  13. // @supportURL https://greasyfork.org/ru/scripts/438039-bandcamp-i-m-not-a-fan/feedback
  14. // @grant none
  15. // @run-at document-start
  16. // @compatible chrome Violentmonkey 2.14.0
  17. // @compatible firefox Greasemonkey 4.11
  18. // @compatible firefox Violentmonkey 2.14.0
  19. // ==/UserScript==
  20.  
  21. function inject() {
  22. 'use strict';
  23.  
  24. const uncap = (o) => (o.is_capped = false);
  25.  
  26. const protect = (...namespaces) => {
  27. for (const namespace of namespaces) {
  28. const names = Object.keys(namespace);
  29. for (const name of names) {
  30. const target = namespace[name];
  31. Object.freeze(target);
  32. }
  33. }
  34. };
  35.  
  36. const freeze = (data) => {
  37. data.trackinfo.map(uncap);
  38. data.is_purchased = true;
  39. data.play_cap_data = {
  40. streaming_limits_enabled: false,
  41. streaming_limit: Infinity,
  42. };
  43. protect(data);
  44. };
  45.  
  46. const patch = () => {
  47. if (!Object.prototype.hasOwnProperty.call(window, 'Player')) return false;
  48.  
  49. const target = 'init';
  50.  
  51. const descriptor = Object.getOwnPropertyDescriptor(Player, target);
  52. if (descriptor === void 0) {
  53. console.error(`Failed extract "${target}" descriptor of "Player"!`);
  54. return false;
  55. }
  56.  
  57. Object.defineProperty(Player, target, {
  58. ...descriptor,
  59. value: function () {
  60. freeze(...arguments);
  61. return descriptor.value.apply(this, arguments);
  62. },
  63. });
  64. console.info('The injection was successful!');
  65. return true;
  66. };
  67.  
  68. new MutationObserver((_, observer) => {
  69. if (patch()) observer.disconnect();
  70. }).observe(document.documentElement, {
  71. childList: true,
  72. subtree: true,
  73. });
  74. }
  75.  
  76. (function (source) {
  77. (
  78. document.getElementsByTagName('head')[0] ||
  79. document.body ||
  80. document.documentElement
  81. ).appendChild(
  82. Object.assign(document.createElement('script'), {
  83. textContent: '(' + source.toString() + ')()',
  84. })
  85. );
  86. })(inject);