Hacker News Anti-Paywall

A userscript for HackerNews that points out paywalled articles and provides anti-paywall urls.

  1. // ==UserScript==
  2. // @name Hacker News Anti-Paywall
  3. // @namespace https://github.com/MostlyEmre/hn-anti-paywall
  4. // @version 0.8
  5. // @description A userscript for HackerNews that points out paywalled articles and provides anti-paywall urls.
  6. // @author MostlyEmre
  7. // @match https://news.ycombinator.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=ycombinator.com
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. /* jshint esversion:6 */
  14.  
  15. (function() {
  16. 'use strict';
  17. const projects = [
  18. {
  19. name: "Archive.is",
  20. url: "https://archive.is/",
  21. },
  22. {
  23. name: "12ft.io",
  24. url: "https://12ft.io/",
  25. },
  26. {
  27. name: "Archive.org",
  28. url: "https://web.archive.org/web/",
  29. },
  30. ];
  31. const paywalls = [
  32. "adweek.com",
  33. "ad.nl",
  34. "ambito.com",
  35. "americanbanker.com",
  36. "baltimoresun.com",
  37. "barrons.com",
  38. "bloomberg.com",
  39. "bloombergquint.com",
  40. "bndestem.nl",
  41. "bostonglobe.com",
  42. "bd.nl",
  43. "brisbanetimes.com.au",
  44. "businessinsider.com",
  45. "caixinglobal.com",
  46. "centralwesterndaily.com.au",
  47. "cen.acs.org",
  48. "chicagotribune.com",
  49. "corriere.it",
  50. "chicagobusiness.com",
  51. "dailypress.com",
  52. "gelderlander.nl",
  53. "groene.nl",
  54. "demorgen.be",
  55. "denverpost.com",
  56. "speld.nl",
  57. "destentor.nl",
  58. "tijd.be",
  59. "volkskrant.nl",
  60. "df.cl",
  61. "editorialedomani.it",
  62. "dynamed.com",
  63. "ed.nl",
  64. "elmercurio.com",
  65. "elmundo.es",
  66. "elpais.com",
  67. "elperiodico.com",
  68. "elu24.ee",
  69. "britannica.com",
  70. "estadao.com.br",
  71. "examiner.com.au",
  72. "expansion.com",
  73. "fnlondon.com",
  74. "financialpost.com",
  75. "ft.com",
  76. "firstthings.com",
  77. "foreignpolicy.com",
  78. "fortune.com",
  79. "genomeweb.com",
  80. "glassdoor.com",
  81. "globes.co.il",
  82. "grubstreet.com",
  83. "haaretz.com",
  84. "haaretz.co.il",
  85. "harpers.org",
  86. "courant.com",
  87. "hbr.org",
  88. "hbrchina.org",
  89. "heraldsun.com.au",
  90. "fd.nl",
  91. "historyextra.com",
  92. "humo.be",
  93. "ilmanifesto.it",
  94. "inc.com",
  95. "interest.co.nz",
  96. "investorschronicle.co.uk",
  97. "lanacion.com.ar",
  98. "repubblica.it",
  99. "lastampa.it",
  100. "latercera.com",
  101. "lavoixdunord.fr",
  102. "lecho.be",
  103. "ledevoir.com",
  104. "leparisien.fr",
  105. "lesechos.fr",
  106. "loebclassics.com",
  107. "lrb.co.uk",
  108. "labusinessjournal.com",
  109. "latimes.com",
  110. "medium.com",
  111. "medscape.com",
  112. "mexiconewsdaily.com",
  113. "sloanreview.mit.edu",
  114. "technologyreview.com",
  115. "mv-voice.com",
  116. "nationalgeographic.com",
  117. "nationalpost.com",
  118. "nzz.ch",
  119. "newstatesman.com",
  120. "nydailynews.com",
  121. "nymag.com",
  122. "nzherald.co.nz",
  123. "nrc.nl",
  124. "ntnews.com.au",
  125. "ocregister.com",
  126. "orlandosentinel.com",
  127. "paloaltoonline.com",
  128. "parool.nl",
  129. "postimees.ee",
  130. "pzc.nl",
  131. "qz.com",
  132. "quora.com",
  133. "gelocal.it",
  134. "republic.ru",
  135. "reuters.com",
  136. "sandiegouniontribune.com",
  137. "sfchronicle.com",
  138. "scientificamerican.com",
  139. "seekingalpha.com",
  140. "slate.com",
  141. "sofrep.com",
  142. "startribune.com",
  143. "statista.com",
  144. "stuff.co.nz",
  145. '"sueddeutsche.de"',
  146. "sun-sentinel.com",
  147. "techinasia.com",
  148. "telegraaf.nl",
  149. "time.com",
  150. "adelaidenow.com.au",
  151. "theadvocate.com.au",
  152. "theage.com.au",
  153. "the-american-interest.com",
  154. "theathletic.com",
  155. "theathletic.co.uk",
  156. "theatlantic.com",
  157. "afr.com",
  158. "theaustralian.com.au",
  159. "bizjournals.com",
  160. "canberratimes.com.au",
  161. "thecourier.com.au",
  162. "couriermail.com.au",
  163. "thecut.com",
  164. "dailytelegraph.com.au",
  165. "thediplomat.com",
  166. "economist.com",
  167. "theglobeandmail.com",
  168. "theherald.com.au",
  169. "thehindu.com",
  170. "irishtimes.com",
  171. "japantimes.co.jp",
  172. "kansascity.com",
  173. "themarker.com",
  174. "mercurynews.com",
  175. "themercury.com.au",
  176. "mcall.com",
  177. "thenation.com",
  178. "thenational.scot",
  179. "news-gazette.com",
  180. "newyorker.com",
  181. "nytimes.com",
  182. "theolivepress.es",
  183. "inquirer.com",
  184. "thesaturdaypaper.com.au",
  185. "seattletimes.com",
  186. "spectator.com.au",
  187. "spectator.co.uk",
  188. "spectator.us",
  189. "smh.com.au",
  190. "telegraph.co.uk",
  191. "thestar.com",
  192. "wsj.com",
  193. "washingtonpost.com",
  194. "thewrap.com",
  195. "the-tls.co.uk",
  196. "towardsdatascience.com",
  197. "trouw.nl",
  198. "tubantia.nl",
  199. "vanityfair.com",
  200. "vn.nl",
  201. "vulture.com",
  202. "journalnow.com",
  203. "wired.com",
  204. "zeit.de",
  205. ];
  206.  
  207. let titles = document.querySelectorAll("table tr.athing");
  208. let postTitle = document.querySelector("tbody table.fatitem tr.athing");
  209.  
  210. // The main function that updates the UI with the links.
  211. const passTheButter = (node) => {
  212. let meta = node.nextSibling.querySelector(".subtext");
  213. let link = node.querySelector(".titleline a").href;
  214. let domain = node.querySelector("span.sitestr") ? node.querySelector("span.sitestr").innerText : "";
  215. let paywall = paywalls.find((paywall) => domain.includes(paywall));
  216.  
  217. if (paywall) {
  218. let paywallSpan = document.createElement("span");
  219. paywallSpan.appendChild(document.createTextNode(" | 💰"));
  220.  
  221. projects.forEach((project) => {
  222. const anchor = document.createElement("a");
  223. const line = document.createElement("span");
  224. line.textContent = " | ";
  225. anchor.setAttribute("href", `${project.url}${link}`);
  226. anchor.setAttribute("target", "_blank");
  227. anchor.setAttribute("rel", "noopener noreferrer");
  228. anchor.textContent = project.name;
  229. paywallSpan.appendChild(line);
  230. paywallSpan.appendChild(anchor);
  231. });
  232. paywallSpan.appendChild(document.createTextNode(" | "));
  233. paywallSpan.appendChild(
  234. Object.assign(document.createElement("a"), {
  235. href: `https://github.com/MostlyEmre/hn-anti-paywall`,
  236. target: "_blank",
  237. rel: "noopener noreferrer",
  238. textContent: "ℹ",
  239. })
  240. );
  241.  
  242. meta.appendChild(paywallSpan);
  243. }
  244. };
  245.  
  246. postTitle
  247. ? passTheButter(postTitle)
  248. : titles.forEach((title) => {
  249. passTheButter(title);
  250. });
  251.  
  252. })();