YesPlease

A (not yet) drop-in replacement for the No, thanks. extension.

  1. // ==UserScript==
  2. // @name YesPlease
  3. // @name:de YesPlease
  4. // @name:en YesPlease
  5. // @namespace sun/userscripts
  6. // @version 1.0.17
  7. // @description A (not yet) drop-in replacement for the No, thanks. extension.
  8. // @description:de (Noch k)ein Ersatz für die No, thanks.-Browsererweiterung.
  9. // @description:en A (not yet) drop-in replacement for the No, thanks. extension.
  10. // @compatible chrome
  11. // @compatible edge
  12. // @compatible firefox
  13. // @compatible opera
  14. // @compatible safari
  15. // @homepageURL https://forgejo.sny.sh/sun/userscripts
  16. // @supportURL https://forgejo.sny.sh/sun/userscripts/issues
  17. // @contributionURL https://liberapay.com/sun
  18. // @contributionAmount €1.00
  19. // @author Sunny <sunny@sny.sh>
  20. // @include *://*/*
  21. // @match *://*/*
  22. // @connect no-thanks-extension.com
  23. // @connect *
  24. // @run-at document-end
  25. // @inject-into auto
  26. // @grant GM.addStyle
  27. // @grant GM_addStyle
  28. // @grant GM.getValue
  29. // @grant GM_getValue
  30. // @grant GM.openInTab
  31. // @grant GM_openInTab
  32. // @grant GM.registerMenuCommand
  33. // @grant GM_registerMenuCommand
  34. // @grant GM.setValue
  35. // @grant GM_setValue
  36. // @grant GM.xmlHttpRequest
  37. // @grant GM_xmlhttpRequest
  38. // @noframes
  39. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  40. // @require https://openuserjs.org/src/libs/sizzle/GM_config.js
  41. // @icon https://forgejo.sny.sh/sun/userscripts/raw/branch/main/icons/YesPlease.png
  42. // @copyright 2021-present, Sunny (https://sny.sh/)
  43. // @license Hippocratic License; https://forgejo.sny.sh/sun/userscripts/src/branch/main/LICENSE.md
  44. // ==/UserScript==
  45.  
  46. (() => {
  47. GM_config.init({
  48. id: "options",
  49. title: "YesPlease",
  50. fields: {
  51. host: {
  52. label: "Extension host",
  53. section: ["Access", "Configure access to the extension server"],
  54. type: "text",
  55. title: "Base URL of the host to send requests to when updating rules",
  56. default: "https://www.no-thanks-extension.com",
  57. },
  58. hash: {
  59. label: "Subscription hash",
  60. type: "text",
  61. title:
  62. "Valid subscription identifier, required when using the official host",
  63. size: 64,
  64. default:
  65. "abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz12",
  66. },
  67. "group-newsletter": {
  68. label: "Newsletter pop-ups",
  69. section: ["Groups", "Choose which element groups to hide"],
  70. type: "checkbox",
  71. title: "Block and auto-close all kinds of newsletter pop-ups",
  72. default: true,
  73. },
  74. "group-chat": {
  75. label: "Chat boxes",
  76. type: "checkbox",
  77. title: "Block chat, feedback and contact boxes in the corner",
  78. default: true,
  79. },
  80. "group-app": {
  81. label: "'Install our app' boxes",
  82. type: "checkbox",
  83. title: "Block 'Install our app' boxes and toolbars",
  84. default: true,
  85. },
  86. "group-push": {
  87. label: "Notification pop-ups",
  88. type: "checkbox",
  89. title: "Block 'Allow notifications' pop-ups",
  90. default: true,
  91. },
  92. "group-location": {
  93. label: "Location requests",
  94. type: "checkbox",
  95. title: "Block 'Allow us to know your location' requests",
  96. default: true,
  97. },
  98. "group-survey": {
  99. label: "Survey pop-ups",
  100. type: "checkbox",
  101. title: "Block and auto-close all kinds of surveys and opinion pop-ups",
  102. default: true,
  103. },
  104. "group-rating": {
  105. label: "Website ratings",
  106. type: "checkbox",
  107. title:
  108. "Block website ratings, 'website protected by...' and similar boxes",
  109. default: true,
  110. },
  111. "group-translation": {
  112. label: "Translation toolbars",
  113. type: "checkbox",
  114. title: "Block toolbars offering website translation",
  115. default: true,
  116. },
  117. "group-top": {
  118. label: "'Scroll to top' buttons",
  119. type: "checkbox",
  120. title: "Block 'Scroll to top' buttons",
  121. default: true,
  122. },
  123. "group-signup": {
  124. label: "Sign-up prompts",
  125. type: "checkbox",
  126. title: "Block big 'Login / Register' pop-ups",
  127. default: true,
  128. },
  129. "group-video": {
  130. label: "Video boxes",
  131. type: "checkbox",
  132. title: "Block video boxes in the corner",
  133. default: true,
  134. },
  135. "group-subscribe": {
  136. label: "Subscription boxes",
  137. type: "checkbox",
  138. title: "Block 'Pay' and 'Subscribe' boxes offering premium services",
  139. default: true,
  140. },
  141. "group-suggestion": {
  142. label: "Suggestion pop-ups",
  143. type: "checkbox",
  144. title:
  145. "Block pop-ups offering shopping, reading and similar suggestions",
  146. default: true,
  147. },
  148. "group-iam18": {
  149. label: "Age confirmations",
  150. type: "checkbox",
  151. title:
  152. "Automatically confirm you are 18+ years old when needed, if you really are",
  153. default: false,
  154. },
  155. version: {
  156. label: "Rules version",
  157. section: ["Metadata", "Information about the current rules file"],
  158. type: "text",
  159. title:
  160. "Version of the currently cached rules file, will be updated automatically",
  161. size: 7,
  162. default: "0.0.0.0",
  163. },
  164. rules: {
  165. label: "Extension rules",
  166. type: "textarea",
  167. title: "Currently cached rules file, changes may be overwritten",
  168. default: "{}",
  169. },
  170. timestamp: {
  171. label: "Last update",
  172. type: "int",
  173. title: "Timestamp of the last rule file update check",
  174. default: 0,
  175. },
  176. update: {
  177. label: "Update interval",
  178. section: ["Miscellaneous", "Other userscript-related preferences"],
  179. type: "int",
  180. title:
  181. "Interval in milliseconds in which to automatically check for updates",
  182. default: 86400000,
  183. },
  184. notify: {
  185. label: "Send notifications",
  186. type: "select",
  187. title: "Whether to send notifications when updating rules",
  188. options: ["Always", "Only manual updates", "Never"],
  189. default: "Only manual updates",
  190. },
  191. },
  192. events: {
  193. init,
  194. },
  195. });
  196.  
  197. GM.registerMenuCommand("Report issue on this page", () => {
  198. GM.openInTab(
  199. `https://www.no-thanks-extension.com/report/problem/on/${encodeURIComponent(encodeURIComponent(location.href))}`,
  200. {
  201. active: true,
  202. },
  203. );
  204. });
  205.  
  206. GM.registerMenuCommand("Userscript options", () => {
  207. GM_config.open();
  208. });
  209.  
  210. GM.registerMenuCommand("Manual update", () => {
  211. request(true);
  212. });
  213.  
  214. GM.registerMenuCommand("Visit homepage", () => {
  215. GM.openInTab("https://www.no-thanks-extension.com/", {
  216. active: true,
  217. });
  218. });
  219.  
  220. function init() {
  221. if (
  222. GM_config.get("update") &&
  223. Date.now() - GM_config.get("update") > GM_config.get("timestamp")
  224. )
  225. request();
  226.  
  227. const groups = JSON.parse(GM_config.get("rules"));
  228. for (const group in groups) {
  229. if (GM_config.get(`group-${group}`)) {
  230. for (const css in groups[group].css) {
  231. if (css === "common" || css === location.hostname) {
  232. GM.addStyle(groups[group].css[css]);
  233. }
  234. }
  235. for (const js in groups[group].js) {
  236. // groups[group].js[js]
  237. }
  238. for (const block in groups[group].block) {
  239. // groups[group].block[block]
  240. }
  241. }
  242. }
  243. }
  244.  
  245. function request(manual) {
  246. GM.xmlHttpRequest({
  247. method: "GET",
  248. url: `${GM_config.get("host")}/api/get`,
  249. headers: {
  250. "nothanks-hash": GM_config.get("hash"),
  251. "nothanks-version": GM_config.get("version"),
  252. },
  253. onload: (response) => {
  254. GM_config.set("timestamp", Date.now());
  255.  
  256. switch (response.responseText) {
  257. case "UP_TO_DATE":
  258. notify(manual, "Blocking rules are already up to date.");
  259. break;
  260. case "INVALID":
  261. notify(manual, "Please renew your subscription.");
  262. break;
  263. case "EXPIRED":
  264. notify(
  265. manual,
  266. "Your subscription has expired. To subscribe again, please follow the 'Subscribe' link in the extension menu.",
  267. );
  268. break;
  269. default:
  270. GM_config.set(
  271. "version",
  272. JSON.parse(response.responseText).info.version,
  273. );
  274. GM_config.set(
  275. "rules",
  276. JSON.stringify(JSON.parse(response.responseText).rules),
  277. );
  278. GM_config.write();
  279. notify(
  280. manual,
  281. `Blocking rules have just been updated to version ${GM_config.get("version")}.`,
  282. );
  283. }
  284. },
  285. });
  286. }
  287.  
  288. function notify(manual, message) {
  289. if (manual) {
  290. if (
  291. GM_config.get("notify") === "Always" ||
  292. GM_config.get("notify") === "Only manual updates"
  293. )
  294. alert(message);
  295. } else {
  296. if (GM_config.get("notify") === "Always") alert(message);
  297. }
  298. }
  299. })();