feedscout 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/README.md +1 -1
  2. package/dist/blogrolls/defaults.cjs +16 -10
  3. package/dist/blogrolls/defaults.d.cts +1 -2
  4. package/dist/blogrolls/defaults.d.ts +1 -2
  5. package/dist/blogrolls/defaults.js +17 -10
  6. package/dist/blogrolls/extractors.cjs +2 -2
  7. package/dist/blogrolls/extractors.d.cts +2 -2
  8. package/dist/blogrolls/extractors.d.ts +2 -2
  9. package/dist/blogrolls/extractors.js +2 -2
  10. package/dist/blogrolls/index.cjs +9 -10
  11. package/dist/blogrolls/index.js +4 -5
  12. package/dist/blogrolls.cjs +1 -2
  13. package/dist/blogrolls.d.cts +3 -3
  14. package/dist/blogrolls.d.ts +3 -3
  15. package/dist/blogrolls.js +3 -3
  16. package/dist/common/discover/defaults.cjs +46 -0
  17. package/dist/common/discover/defaults.d.cts +6 -0
  18. package/dist/common/discover/defaults.d.ts +6 -0
  19. package/dist/common/discover/defaults.js +44 -0
  20. package/dist/common/discover/index.cjs +7 -7
  21. package/dist/common/discover/index.js +2 -2
  22. package/dist/common/discover/utils.cjs +0 -29
  23. package/dist/common/discover/utils.d.cts +1 -3
  24. package/dist/common/discover/utils.d.ts +1 -3
  25. package/dist/common/discover/utils.js +1 -28
  26. package/dist/common/locales.cjs +214 -10
  27. package/dist/common/locales.js +214 -10
  28. package/dist/common/types.d.cts +3 -2
  29. package/dist/common/types.d.ts +3 -2
  30. package/dist/common/uris/html/handlers.cjs +14 -0
  31. package/dist/common/uris/html/handlers.js +14 -0
  32. package/dist/common/uris/html/index.cjs +17 -1
  33. package/dist/common/uris/html/index.js +17 -1
  34. package/dist/common/uris/html/types.d.cts +5 -4
  35. package/dist/common/uris/html/types.d.ts +5 -4
  36. package/dist/common/utils.cjs +12 -11
  37. package/dist/common/utils.d.cts +6 -4
  38. package/dist/common/utils.d.ts +6 -4
  39. package/dist/common/utils.js +13 -11
  40. package/dist/favicons/extractors.cjs +2 -2
  41. package/dist/favicons/extractors.d.cts +2 -2
  42. package/dist/favicons/extractors.d.ts +2 -2
  43. package/dist/favicons/extractors.js +2 -2
  44. package/dist/favicons/index.cjs +11 -12
  45. package/dist/favicons/index.js +4 -5
  46. package/dist/favicons.cjs +1 -1
  47. package/dist/favicons.d.cts +2 -2
  48. package/dist/favicons.d.ts +2 -2
  49. package/dist/favicons.js +2 -2
  50. package/dist/feeds/defaults.cjs +121 -9
  51. package/dist/feeds/defaults.d.cts +4 -3
  52. package/dist/feeds/defaults.d.ts +4 -3
  53. package/dist/feeds/defaults.js +121 -10
  54. package/dist/feeds/extractors.cjs +6 -6
  55. package/dist/feeds/extractors.d.cts +2 -2
  56. package/dist/feeds/extractors.d.ts +2 -2
  57. package/dist/feeds/extractors.js +4 -4
  58. package/dist/feeds/index.cjs +9 -10
  59. package/dist/feeds/index.js +4 -5
  60. package/dist/feeds/platform/handlers/acast.cjs +26 -0
  61. package/dist/feeds/platform/handlers/acast.js +26 -0
  62. package/dist/feeds/platform/handlers/ameblo.cjs +36 -0
  63. package/dist/feeds/platform/handlers/ameblo.js +36 -0
  64. package/dist/feeds/platform/handlers/applePodcasts.cjs +1 -1
  65. package/dist/feeds/platform/handlers/applePodcasts.js +1 -1
  66. package/dist/feeds/platform/handlers/arena.cjs +42 -0
  67. package/dist/feeds/platform/handlers/arena.js +42 -0
  68. package/dist/feeds/platform/handlers/artstation.cjs +52 -0
  69. package/dist/feeds/platform/handlers/artstation.js +52 -0
  70. package/dist/feeds/platform/handlers/audioboom.cjs +23 -0
  71. package/dist/feeds/platform/handlers/audioboom.js +23 -0
  72. package/dist/feeds/platform/handlers/bearblog.cjs +45 -0
  73. package/dist/feeds/platform/handlers/bearblog.js +45 -0
  74. package/dist/feeds/platform/handlers/behance.cjs +7 -0
  75. package/dist/feeds/platform/handlers/behance.js +7 -0
  76. package/dist/feeds/platform/handlers/blogspot.cjs +38 -2
  77. package/dist/feeds/platform/handlers/blogspot.js +38 -2
  78. package/dist/feeds/platform/handlers/bookwyrm.cjs +48 -0
  79. package/dist/feeds/platform/handlers/bookwyrm.js +48 -0
  80. package/dist/feeds/platform/handlers/buttondown.cjs +43 -0
  81. package/dist/feeds/platform/handlers/buttondown.js +43 -0
  82. package/dist/feeds/platform/handlers/buzzsprout.cjs +22 -0
  83. package/dist/feeds/platform/handlers/buzzsprout.js +22 -0
  84. package/dist/feeds/platform/handlers/codeberg.cjs +5 -5
  85. package/dist/feeds/platform/handlers/codeberg.js +5 -5
  86. package/dist/feeds/platform/handlers/dailymotion.cjs +16 -0
  87. package/dist/feeds/platform/handlers/dailymotion.js +16 -0
  88. package/dist/feeds/platform/handlers/deviantart.cjs +25 -6
  89. package/dist/feeds/platform/handlers/deviantart.js +25 -6
  90. package/dist/feeds/platform/handlers/devto.cjs +8 -0
  91. package/dist/feeds/platform/handlers/devto.js +8 -0
  92. package/dist/feeds/platform/handlers/discourse.cjs +70 -0
  93. package/dist/feeds/platform/handlers/discourse.js +70 -0
  94. package/dist/feeds/platform/handlers/dreamwidth.cjs +48 -0
  95. package/dist/feeds/platform/handlers/dreamwidth.js +48 -0
  96. package/dist/feeds/platform/handlers/exblog.cjs +35 -0
  97. package/dist/feeds/platform/handlers/exblog.js +35 -0
  98. package/dist/feeds/platform/handlers/fireside.cjs +24 -0
  99. package/dist/feeds/platform/handlers/fireside.js +24 -0
  100. package/dist/feeds/platform/handlers/friendica.cjs +44 -0
  101. package/dist/feeds/platform/handlers/friendica.js +44 -0
  102. package/dist/feeds/platform/handlers/ghost.cjs +30 -0
  103. package/dist/feeds/platform/handlers/ghost.js +30 -0
  104. package/dist/feeds/platform/handlers/github.cjs +6 -0
  105. package/dist/feeds/platform/handlers/github.js +6 -0
  106. package/dist/feeds/platform/handlers/githubGist.cjs +16 -5
  107. package/dist/feeds/platform/handlers/githubGist.js +16 -5
  108. package/dist/feeds/platform/handlers/gitlab.cjs +31 -13
  109. package/dist/feeds/platform/handlers/gitlab.js +31 -13
  110. package/dist/feeds/platform/handlers/goodreads.cjs +18 -8
  111. package/dist/feeds/platform/handlers/goodreads.js +18 -8
  112. package/dist/feeds/platform/handlers/hackernews.cjs +21 -0
  113. package/dist/feeds/platform/handlers/hackernews.js +21 -0
  114. package/dist/feeds/platform/handlers/hashnode.cjs +1 -1
  115. package/dist/feeds/platform/handlers/hashnode.js +1 -1
  116. package/dist/feeds/platform/handlers/hatenablog.cjs +4 -1
  117. package/dist/feeds/platform/handlers/hatenablog.js +4 -1
  118. package/dist/feeds/platform/handlers/hearthis.cjs +32 -0
  119. package/dist/feeds/platform/handlers/hearthis.js +32 -0
  120. package/dist/feeds/platform/handlers/heyWorld.cjs +18 -0
  121. package/dist/feeds/platform/handlers/heyWorld.js +18 -0
  122. package/dist/feeds/platform/handlers/insanejournal.cjs +69 -0
  123. package/dist/feeds/platform/handlers/insanejournal.js +69 -0
  124. package/dist/feeds/platform/handlers/itchio.cjs +24 -1
  125. package/dist/feeds/platform/handlers/itchio.js +24 -1
  126. package/dist/feeds/platform/handlers/lemmy.cjs +46 -4
  127. package/dist/feeds/platform/handlers/lemmy.js +46 -4
  128. package/dist/feeds/platform/handlers/letterboxd.cjs +4 -0
  129. package/dist/feeds/platform/handlers/letterboxd.js +4 -0
  130. package/dist/feeds/platform/handlers/libsyn.cjs +25 -0
  131. package/dist/feeds/platform/handlers/libsyn.js +25 -0
  132. package/dist/feeds/platform/handlers/listed.cjs +20 -0
  133. package/dist/feeds/platform/handlers/listed.js +20 -0
  134. package/dist/feeds/platform/handlers/livejournal.cjs +68 -0
  135. package/dist/feeds/platform/handlers/livejournal.js +68 -0
  136. package/dist/feeds/platform/handlers/mastodon.cjs +32 -0
  137. package/dist/feeds/platform/handlers/mastodon.js +32 -0
  138. package/dist/feeds/platform/handlers/mataroa.cjs +16 -0
  139. package/dist/feeds/platform/handlers/mataroa.js +16 -0
  140. package/dist/feeds/platform/handlers/medium.cjs +2 -2
  141. package/dist/feeds/platform/handlers/medium.js +2 -2
  142. package/dist/feeds/platform/handlers/microblog.cjs +55 -0
  143. package/dist/feeds/platform/handlers/microblog.js +55 -0
  144. package/dist/feeds/platform/handlers/misskey.cjs +40 -0
  145. package/dist/feeds/platform/handlers/misskey.js +40 -0
  146. package/dist/feeds/platform/handlers/myanimelist.cjs +43 -0
  147. package/dist/feeds/platform/handlers/myanimelist.js +43 -0
  148. package/dist/feeds/platform/handlers/naverBlog.cjs +21 -0
  149. package/dist/feeds/platform/handlers/naverBlog.js +21 -0
  150. package/dist/feeds/platform/handlers/nebula.cjs +68 -0
  151. package/dist/feeds/platform/handlers/nebula.js +68 -0
  152. package/dist/feeds/platform/handlers/note.cjs +53 -0
  153. package/dist/feeds/platform/handlers/note.js +53 -0
  154. package/dist/feeds/platform/handlers/observable.cjs +34 -0
  155. package/dist/feeds/platform/handlers/observable.js +34 -0
  156. package/dist/feeds/platform/handlers/odysee.cjs +20 -0
  157. package/dist/feeds/platform/handlers/odysee.js +20 -0
  158. package/dist/feeds/platform/handlers/pagecord.cjs +16 -0
  159. package/dist/feeds/platform/handlers/pagecord.js +16 -0
  160. package/dist/feeds/platform/handlers/paragraph.cjs +1 -2
  161. package/dist/feeds/platform/handlers/paragraph.js +1 -2
  162. package/dist/feeds/platform/handlers/pika.cjs +35 -0
  163. package/dist/feeds/platform/handlers/pika.js +35 -0
  164. package/dist/feeds/platform/handlers/pinterest.cjs +13 -0
  165. package/dist/feeds/platform/handlers/pinterest.js +13 -0
  166. package/dist/feeds/platform/handlers/pixelfed.cjs +46 -0
  167. package/dist/feeds/platform/handlers/pixelfed.js +46 -0
  168. package/dist/feeds/platform/handlers/pleroma.cjs +34 -0
  169. package/dist/feeds/platform/handlers/pleroma.js +34 -0
  170. package/dist/feeds/platform/handlers/podbean.cjs +29 -0
  171. package/dist/feeds/platform/handlers/podbean.js +29 -0
  172. package/dist/feeds/platform/handlers/podigee.cjs +29 -0
  173. package/dist/feeds/platform/handlers/podigee.js +29 -0
  174. package/dist/feeds/platform/handlers/posthaven.cjs +24 -0
  175. package/dist/feeds/platform/handlers/posthaven.js +24 -0
  176. package/dist/feeds/platform/handlers/prose.cjs +26 -0
  177. package/dist/feeds/platform/handlers/prose.js +26 -0
  178. package/dist/feeds/platform/handlers/qiita.cjs +58 -0
  179. package/dist/feeds/platform/handlers/qiita.js +58 -0
  180. package/dist/feeds/platform/handlers/reddit.cjs +83 -9
  181. package/dist/feeds/platform/handlers/reddit.js +83 -9
  182. package/dist/feeds/platform/handlers/rssCom.cjs +20 -0
  183. package/dist/feeds/platform/handlers/rssCom.js +20 -0
  184. package/dist/feeds/platform/handlers/seesaa.cjs +22 -0
  185. package/dist/feeds/platform/handlers/seesaa.js +22 -0
  186. package/dist/feeds/platform/handlers/sourceforge.cjs +37 -4
  187. package/dist/feeds/platform/handlers/sourceforge.js +37 -4
  188. package/dist/feeds/platform/handlers/spreaker.cjs +21 -0
  189. package/dist/feeds/platform/handlers/spreaker.js +21 -0
  190. package/dist/feeds/platform/handlers/stackExchange.cjs +26 -2
  191. package/dist/feeds/platform/handlers/stackExchange.js +26 -2
  192. package/dist/feeds/platform/handlers/steam.cjs +7 -0
  193. package/dist/feeds/platform/handlers/steam.js +7 -0
  194. package/dist/feeds/platform/handlers/tildes.cjs +41 -0
  195. package/dist/feeds/platform/handlers/tildes.js +41 -0
  196. package/dist/feeds/platform/handlers/tistory.cjs +16 -0
  197. package/dist/feeds/platform/handlers/tistory.js +16 -0
  198. package/dist/feeds/platform/handlers/transistor.cjs +29 -0
  199. package/dist/feeds/platform/handlers/transistor.js +29 -0
  200. package/dist/feeds/platform/handlers/velog.cjs +24 -0
  201. package/dist/feeds/platform/handlers/velog.js +24 -0
  202. package/dist/feeds/platform/handlers/vimeo.cjs +6 -0
  203. package/dist/feeds/platform/handlers/vimeo.js +6 -0
  204. package/dist/feeds/platform/handlers/weblogLol.cjs +26 -0
  205. package/dist/feeds/platform/handlers/weblogLol.js +26 -0
  206. package/dist/feeds/platform/handlers/weebly.cjs +25 -0
  207. package/dist/feeds/platform/handlers/weebly.js +25 -0
  208. package/dist/feeds/platform/handlers/wordpress.cjs +173 -28
  209. package/dist/feeds/platform/handlers/wordpress.js +173 -28
  210. package/dist/feeds/platform/handlers/writeas.cjs +51 -0
  211. package/dist/feeds/platform/handlers/writeas.js +51 -0
  212. package/dist/feeds/platform/handlers/ximalaya.cjs +1 -1
  213. package/dist/feeds/platform/handlers/ximalaya.js +1 -1
  214. package/dist/feeds/platform/handlers/youtube.cjs +4 -1
  215. package/dist/feeds/platform/handlers/youtube.js +4 -1
  216. package/dist/feeds/platform/handlers/zenn.cjs +54 -0
  217. package/dist/feeds/platform/handlers/zenn.js +54 -0
  218. package/dist/feeds.cjs +2 -1
  219. package/dist/feeds.d.cts +3 -3
  220. package/dist/feeds.d.ts +3 -3
  221. package/dist/feeds.js +3 -3
  222. package/dist/hubs/discover/index.cjs +4 -4
  223. package/dist/hubs/discover/index.js +3 -3
  224. package/dist/hubs/feed/index.cjs +2 -2
  225. package/dist/hubs/feed/index.js +2 -2
  226. package/dist/hubs/headers/index.cjs +2 -2
  227. package/dist/hubs/headers/index.js +2 -2
  228. package/dist/hubs/html/index.cjs +2 -2
  229. package/dist/hubs/html/index.js +2 -2
  230. package/dist/index.cjs +2 -1
  231. package/dist/index.d.cts +2 -1
  232. package/dist/index.d.ts +2 -1
  233. package/dist/index.js +2 -1
  234. package/dist/utils.d.cts +2 -1
  235. package/dist/utils.d.ts +2 -1
  236. package/package.json +6 -7
@@ -0,0 +1,21 @@
1
+ import { composeHint, isHostOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/hackernews.ts
3
+ const hosts = ["news.ycombinator.com"];
4
+ const hackernewsHandler = {
5
+ match: (url) => {
6
+ return isHostOf(url, hosts);
7
+ },
8
+ resolve: (url) => {
9
+ const { pathname } = new URL(url);
10
+ if (pathname === "/show" || pathname === "/shownew") return [{
11
+ uri: "https://news.ycombinator.com/showrss",
12
+ hint: composeHint("hackernews:show")
13
+ }];
14
+ return [{
15
+ uri: "https://news.ycombinator.com/rss",
16
+ hint: composeHint("hackernews:front")
17
+ }];
18
+ }
19
+ };
20
+ //#endregion
21
+ export { hackernewsHandler };
@@ -2,7 +2,7 @@ const require_utils = require("../../../common/utils.cjs");
2
2
  //#region src/feeds/platform/handlers/hashnode.ts
3
3
  const hashnodeHandler = {
4
4
  match: (url) => {
5
- return require_utils.isSubdomainOf(url, "hashnode.dev");
5
+ return require_utils.isSubdomainOf(url, ["hashnode.dev", "hashnode.com"]);
6
6
  },
7
7
  resolve: (url) => {
8
8
  const { origin } = new URL(url);
@@ -2,7 +2,7 @@ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
2
2
  //#region src/feeds/platform/handlers/hashnode.ts
3
3
  const hashnodeHandler = {
4
4
  match: (url) => {
5
- return isSubdomainOf(url, "hashnode.dev");
5
+ return isSubdomainOf(url, ["hashnode.dev", "hashnode.com"]);
6
6
  },
7
7
  resolve: (url) => {
8
8
  const { origin } = new URL(url);
@@ -3,7 +3,10 @@ const require_utils = require("../../../common/utils.cjs");
3
3
  const domains = [
4
4
  "hatenablog.com",
5
5
  "hatenablog.jp",
6
- "hateblo.jp"
6
+ "hateblo.jp",
7
+ "hatenadiary.com",
8
+ "hatenadiary.jp",
9
+ "hatenadiary.org"
7
10
  ];
8
11
  const categoryRegex = /^\/archive\/category\/([^/]+)/;
9
12
  const authorRegex = /^\/archive\/author\/([^/]+)/;
@@ -3,7 +3,10 @@ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
3
3
  const domains = [
4
4
  "hatenablog.com",
5
5
  "hatenablog.jp",
6
- "hateblo.jp"
6
+ "hateblo.jp",
7
+ "hatenadiary.com",
8
+ "hatenadiary.jp",
9
+ "hatenadiary.org"
7
10
  ];
8
11
  const categoryRegex = /^\/archive\/category\/([^/]+)/;
9
12
  const authorRegex = /^\/archive\/author\/([^/]+)/;
@@ -0,0 +1,32 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/hearthis.ts
3
+ const hosts = ["hearthis.at", "www.hearthis.at"];
4
+ const excludedPaths = [
5
+ "about",
6
+ "api",
7
+ "feed",
8
+ "login",
9
+ "privacy",
10
+ "search",
11
+ "set",
12
+ "signup",
13
+ "terms"
14
+ ];
15
+ const hearthisHandler = {
16
+ match: (url) => {
17
+ return require_utils.isHostOf(url, hosts);
18
+ },
19
+ resolve: (url) => {
20
+ const { pathname } = new URL(url);
21
+ const pathSegments = pathname.split("/").filter(Boolean);
22
+ if (pathSegments.length === 0) return [];
23
+ const username = pathSegments[0];
24
+ if (require_utils.isAnyOf(username, excludedPaths)) return [];
25
+ return [{
26
+ uri: `https://hearthis.at/${username}/podcast/`,
27
+ hint: require_utils.composeHint("hearthis:tracks")
28
+ }];
29
+ }
30
+ };
31
+ //#endregion
32
+ exports.hearthisHandler = hearthisHandler;
@@ -0,0 +1,32 @@
1
+ import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/hearthis.ts
3
+ const hosts = ["hearthis.at", "www.hearthis.at"];
4
+ const excludedPaths = [
5
+ "about",
6
+ "api",
7
+ "feed",
8
+ "login",
9
+ "privacy",
10
+ "search",
11
+ "set",
12
+ "signup",
13
+ "terms"
14
+ ];
15
+ const hearthisHandler = {
16
+ match: (url) => {
17
+ return isHostOf(url, hosts);
18
+ },
19
+ resolve: (url) => {
20
+ const { pathname } = new URL(url);
21
+ const pathSegments = pathname.split("/").filter(Boolean);
22
+ if (pathSegments.length === 0) return [];
23
+ const username = pathSegments[0];
24
+ if (isAnyOf(username, excludedPaths)) return [];
25
+ return [{
26
+ uri: `https://hearthis.at/${username}/podcast/`,
27
+ hint: composeHint("hearthis:tracks")
28
+ }];
29
+ }
30
+ };
31
+ //#endregion
32
+ export { hearthisHandler };
@@ -0,0 +1,18 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/heyWorld.ts
3
+ const heyWorldHandler = {
4
+ match: (url) => {
5
+ return require_utils.isHostOf(url, "world.hey.com");
6
+ },
7
+ resolve: (url) => {
8
+ const { pathname } = new URL(url);
9
+ const pathSegments = pathname.split("/").filter(Boolean);
10
+ if (pathSegments.length === 0) return [];
11
+ return [{
12
+ uri: `https://world.hey.com/${pathSegments[0]}/feed.atom`,
13
+ hint: require_utils.composeHint("hey-world:blog")
14
+ }];
15
+ }
16
+ };
17
+ //#endregion
18
+ exports.heyWorldHandler = heyWorldHandler;
@@ -0,0 +1,18 @@
1
+ import { composeHint, isHostOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/heyWorld.ts
3
+ const heyWorldHandler = {
4
+ match: (url) => {
5
+ return isHostOf(url, "world.hey.com");
6
+ },
7
+ resolve: (url) => {
8
+ const { pathname } = new URL(url);
9
+ const pathSegments = pathname.split("/").filter(Boolean);
10
+ if (pathSegments.length === 0) return [];
11
+ return [{
12
+ uri: `https://world.hey.com/${pathSegments[0]}/feed.atom`,
13
+ hint: composeHint("hey-world:blog")
14
+ }];
15
+ }
16
+ };
17
+ //#endregion
18
+ export { heyWorldHandler };
@@ -0,0 +1,69 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/insanejournal.ts
3
+ const wwwUsersPathRegex = /^\/(?:users\/|~)([^/]+)/;
4
+ const wwwAsylumPathRegex = /^\/(?:asylum|community)\/([^/]+)/;
5
+ const firstSegmentRegex = /^\/([^/]+)/;
6
+ const tagRegex = /^\/tag\/([^/]+)/;
7
+ const insanejournalHandler = {
8
+ match: (url) => {
9
+ if (!require_utils.isSubdomainOf(url, "insanejournal.com")) return false;
10
+ const { hostname, pathname } = new URL(url);
11
+ const lower = hostname.toLowerCase();
12
+ if (lower === "www.insanejournal.com" || lower === "insanejournal.com") return wwwUsersPathRegex.test(pathname) || wwwAsylumPathRegex.test(pathname);
13
+ if (lower === "asylums.insanejournal.com" || lower === "feeds.insanejournal.com") return firstSegmentRegex.test(pathname);
14
+ return true;
15
+ },
16
+ resolve: (url) => {
17
+ const { origin, hostname, pathname } = new URL(url);
18
+ const lowerHostname = hostname.toLowerCase();
19
+ const uris = [];
20
+ let feedOrigin = origin;
21
+ let feedPathPrefix = "";
22
+ if (lowerHostname === "www.insanejournal.com" || lowerHostname === "insanejournal.com") {
23
+ const userMatch = pathname.match(wwwUsersPathRegex);
24
+ if (userMatch?.[1]) feedOrigin = `https://${userMatch[1]}.insanejournal.com`;
25
+ else {
26
+ const asylumMatch = pathname.match(wwwAsylumPathRegex);
27
+ if (asylumMatch?.[1]) {
28
+ feedOrigin = "https://asylums.insanejournal.com";
29
+ feedPathPrefix = `/${asylumMatch[1]}`;
30
+ } else return uris;
31
+ }
32
+ } else if (lowerHostname === "asylums.insanejournal.com") {
33
+ const segMatch = pathname.match(firstSegmentRegex);
34
+ if (segMatch?.[1]) feedPathPrefix = `/${segMatch[1]}`;
35
+ else return uris;
36
+ } else if (lowerHostname === "feeds.insanejournal.com") {
37
+ const segMatch = pathname.match(firstSegmentRegex);
38
+ if (segMatch?.[1]) feedPathPrefix = `/${segMatch[1]}`;
39
+ else return uris;
40
+ }
41
+ const tagMatch = pathname.match(tagRegex);
42
+ if (tagMatch?.[1]) {
43
+ const tag = encodeURIComponent(tagMatch[1]);
44
+ uris.push({
45
+ uri: `${feedOrigin}${feedPathPrefix}/data/rss?tag=${tag}`,
46
+ hint: require_utils.composeHint("insanejournal:posts-tag-rss")
47
+ });
48
+ uris.push({
49
+ uri: `${feedOrigin}${feedPathPrefix}/data/atom?tag=${tag}`,
50
+ hint: require_utils.composeHint("insanejournal:posts-tag-atom")
51
+ });
52
+ }
53
+ uris.push({
54
+ uri: `${feedOrigin}${feedPathPrefix}/data/rss`,
55
+ hint: require_utils.composeHint("insanejournal:posts-rss")
56
+ });
57
+ uris.push({
58
+ uri: `${feedOrigin}${feedPathPrefix}/data/atom`,
59
+ hint: require_utils.composeHint("insanejournal:posts-atom")
60
+ });
61
+ uris.push({
62
+ uri: `${feedOrigin}${feedPathPrefix}/data/userpics`,
63
+ hint: require_utils.composeHint("insanejournal:userpics-atom")
64
+ });
65
+ return uris;
66
+ }
67
+ };
68
+ //#endregion
69
+ exports.insanejournalHandler = insanejournalHandler;
@@ -0,0 +1,69 @@
1
+ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/insanejournal.ts
3
+ const wwwUsersPathRegex = /^\/(?:users\/|~)([^/]+)/;
4
+ const wwwAsylumPathRegex = /^\/(?:asylum|community)\/([^/]+)/;
5
+ const firstSegmentRegex = /^\/([^/]+)/;
6
+ const tagRegex = /^\/tag\/([^/]+)/;
7
+ const insanejournalHandler = {
8
+ match: (url) => {
9
+ if (!isSubdomainOf(url, "insanejournal.com")) return false;
10
+ const { hostname, pathname } = new URL(url);
11
+ const lower = hostname.toLowerCase();
12
+ if (lower === "www.insanejournal.com" || lower === "insanejournal.com") return wwwUsersPathRegex.test(pathname) || wwwAsylumPathRegex.test(pathname);
13
+ if (lower === "asylums.insanejournal.com" || lower === "feeds.insanejournal.com") return firstSegmentRegex.test(pathname);
14
+ return true;
15
+ },
16
+ resolve: (url) => {
17
+ const { origin, hostname, pathname } = new URL(url);
18
+ const lowerHostname = hostname.toLowerCase();
19
+ const uris = [];
20
+ let feedOrigin = origin;
21
+ let feedPathPrefix = "";
22
+ if (lowerHostname === "www.insanejournal.com" || lowerHostname === "insanejournal.com") {
23
+ const userMatch = pathname.match(wwwUsersPathRegex);
24
+ if (userMatch?.[1]) feedOrigin = `https://${userMatch[1]}.insanejournal.com`;
25
+ else {
26
+ const asylumMatch = pathname.match(wwwAsylumPathRegex);
27
+ if (asylumMatch?.[1]) {
28
+ feedOrigin = "https://asylums.insanejournal.com";
29
+ feedPathPrefix = `/${asylumMatch[1]}`;
30
+ } else return uris;
31
+ }
32
+ } else if (lowerHostname === "asylums.insanejournal.com") {
33
+ const segMatch = pathname.match(firstSegmentRegex);
34
+ if (segMatch?.[1]) feedPathPrefix = `/${segMatch[1]}`;
35
+ else return uris;
36
+ } else if (lowerHostname === "feeds.insanejournal.com") {
37
+ const segMatch = pathname.match(firstSegmentRegex);
38
+ if (segMatch?.[1]) feedPathPrefix = `/${segMatch[1]}`;
39
+ else return uris;
40
+ }
41
+ const tagMatch = pathname.match(tagRegex);
42
+ if (tagMatch?.[1]) {
43
+ const tag = encodeURIComponent(tagMatch[1]);
44
+ uris.push({
45
+ uri: `${feedOrigin}${feedPathPrefix}/data/rss?tag=${tag}`,
46
+ hint: composeHint("insanejournal:posts-tag-rss")
47
+ });
48
+ uris.push({
49
+ uri: `${feedOrigin}${feedPathPrefix}/data/atom?tag=${tag}`,
50
+ hint: composeHint("insanejournal:posts-tag-atom")
51
+ });
52
+ }
53
+ uris.push({
54
+ uri: `${feedOrigin}${feedPathPrefix}/data/rss`,
55
+ hint: composeHint("insanejournal:posts-rss")
56
+ });
57
+ uris.push({
58
+ uri: `${feedOrigin}${feedPathPrefix}/data/atom`,
59
+ hint: composeHint("insanejournal:posts-atom")
60
+ });
61
+ uris.push({
62
+ uri: `${feedOrigin}${feedPathPrefix}/data/userpics`,
63
+ hint: composeHint("insanejournal:userpics-atom")
64
+ });
65
+ return uris;
66
+ }
67
+ };
68
+ //#endregion
69
+ export { insanejournalHandler };
@@ -14,10 +14,14 @@ const sorts = [
14
14
  "newest",
15
15
  "top-rated",
16
16
  "top-sellers",
17
- "on-sale"
17
+ "on-sale",
18
+ "free"
18
19
  ];
19
20
  const byUserRegex = /^\/games\/by-([^/]+)/;
20
21
  const tagRegex = /^\/games\/tag-([^/]+)/;
22
+ const platformRegex = /^\/games\/platform-([^/.]+)/;
23
+ const genreRegex = /^\/games\/genre-([^/.]+)/;
24
+ const madeWithRegex = /^\/games\/made-with-([^/.]+)/;
21
25
  const sortRegex = /^\/games\/([^/.]+)/;
22
26
  const sectionRegex = /^\/([^/.]+)/;
23
27
  const gameRegex = /^\/([^/]+)/;
@@ -50,6 +54,21 @@ const itchioHandler = {
50
54
  uri: `https://itch.io/games/tag-${tagMatch[1]}.xml`,
51
55
  hint: require_utils.composeHint("itchio:tag")
52
56
  }];
57
+ const platformMatch = pathname.match(platformRegex);
58
+ if (platformMatch?.[1]) return [{
59
+ uri: `https://itch.io/games/platform-${platformMatch[1]}.xml`,
60
+ hint: require_utils.composeHint("itchio:platform")
61
+ }];
62
+ const genreMatch = pathname.match(genreRegex);
63
+ if (genreMatch?.[1]) return [{
64
+ uri: `https://itch.io/games/genre-${genreMatch[1]}.xml`,
65
+ hint: require_utils.composeHint("itchio:genre")
66
+ }];
67
+ const madeWithMatch = pathname.match(madeWithRegex);
68
+ if (madeWithMatch?.[1]) return [{
69
+ uri: `https://itch.io/games/made-with-${madeWithMatch[1]}.xml`,
70
+ hint: require_utils.composeHint("itchio:made-with")
71
+ }];
53
72
  const sortMatch = pathname.match(sortRegex);
54
73
  if (sortMatch?.[1] && require_utils.isAnyOf(sortMatch[1], sorts)) return [{
55
74
  uri: `https://itch.io/games/${sortMatch[1]}.xml`,
@@ -81,6 +100,10 @@ const itchioHandler = {
81
100
  uri: "https://itch.io/feed/sales.xml",
82
101
  hint: require_utils.composeHint("itchio:sales")
83
102
  });
103
+ uris.push({
104
+ uri: "https://itch.io/blog.rss",
105
+ hint: require_utils.composeHint("itchio:blog")
106
+ });
84
107
  return uris;
85
108
  }
86
109
  };
@@ -14,10 +14,14 @@ const sorts = [
14
14
  "newest",
15
15
  "top-rated",
16
16
  "top-sellers",
17
- "on-sale"
17
+ "on-sale",
18
+ "free"
18
19
  ];
19
20
  const byUserRegex = /^\/games\/by-([^/]+)/;
20
21
  const tagRegex = /^\/games\/tag-([^/]+)/;
22
+ const platformRegex = /^\/games\/platform-([^/.]+)/;
23
+ const genreRegex = /^\/games\/genre-([^/.]+)/;
24
+ const madeWithRegex = /^\/games\/made-with-([^/.]+)/;
21
25
  const sortRegex = /^\/games\/([^/.]+)/;
22
26
  const sectionRegex = /^\/([^/.]+)/;
23
27
  const gameRegex = /^\/([^/]+)/;
@@ -50,6 +54,21 @@ const itchioHandler = {
50
54
  uri: `https://itch.io/games/tag-${tagMatch[1]}.xml`,
51
55
  hint: composeHint("itchio:tag")
52
56
  }];
57
+ const platformMatch = pathname.match(platformRegex);
58
+ if (platformMatch?.[1]) return [{
59
+ uri: `https://itch.io/games/platform-${platformMatch[1]}.xml`,
60
+ hint: composeHint("itchio:platform")
61
+ }];
62
+ const genreMatch = pathname.match(genreRegex);
63
+ if (genreMatch?.[1]) return [{
64
+ uri: `https://itch.io/games/genre-${genreMatch[1]}.xml`,
65
+ hint: composeHint("itchio:genre")
66
+ }];
67
+ const madeWithMatch = pathname.match(madeWithRegex);
68
+ if (madeWithMatch?.[1]) return [{
69
+ uri: `https://itch.io/games/made-with-${madeWithMatch[1]}.xml`,
70
+ hint: composeHint("itchio:made-with")
71
+ }];
53
72
  const sortMatch = pathname.match(sortRegex);
54
73
  if (sortMatch?.[1] && isAnyOf(sortMatch[1], sorts)) return [{
55
74
  uri: `https://itch.io/games/${sortMatch[1]}.xml`,
@@ -81,6 +100,10 @@ const itchioHandler = {
81
100
  uri: "https://itch.io/feed/sales.xml",
82
101
  hint: composeHint("itchio:sales")
83
102
  });
103
+ uris.push({
104
+ uri: "https://itch.io/blog.rss",
105
+ hint: composeHint("itchio:blog")
106
+ });
84
107
  return uris;
85
108
  }
86
109
  };
@@ -1,6 +1,37 @@
1
1
  const require_utils = require("../../../common/utils.cjs");
2
2
  //#region src/feeds/platform/handlers/lemmy.ts
3
3
  const lemmyPoweredByRegex = /lemmy/i;
4
+ const validSorts = new Set([
5
+ "Active",
6
+ "Hot",
7
+ "New",
8
+ "Old",
9
+ "TopHour",
10
+ "TopSixHour",
11
+ "TopTwelveHour",
12
+ "TopDay",
13
+ "TopWeek",
14
+ "TopMonth",
15
+ "TopThreeMonths",
16
+ "TopSixMonths",
17
+ "TopNineMonths",
18
+ "TopYear",
19
+ "TopAll",
20
+ "Controversial",
21
+ "Scaled",
22
+ "MostComments",
23
+ "NewComments"
24
+ ]);
25
+ const numericRegex = /^\d+$/;
26
+ const getQuerySuffix = (searchParams) => {
27
+ const params = new URLSearchParams();
28
+ const sort = searchParams.get("sort");
29
+ if (sort && validSorts.has(sort)) params.set("sort", sort);
30
+ const limit = searchParams.get("limit");
31
+ if (limit && numericRegex.test(limit)) params.set("limit", limit);
32
+ const query = params.toString();
33
+ return query ? `?${query}` : "";
34
+ };
4
35
  const isCommunityPath = (pathname) => {
5
36
  const segments = pathname.split("/").filter(Boolean);
6
37
  return segments.length >= 2 && segments[0] === "c";
@@ -9,6 +40,9 @@ const isUserPath = (pathname) => {
9
40
  const segments = pathname.split("/").filter(Boolean);
10
41
  return segments.length >= 2 && segments[0] === "u";
11
42
  };
43
+ const isHomePath = (pathname) => {
44
+ return pathname === "/" || pathname === "" || pathname === "/home";
45
+ };
12
46
  const isLemmyHtml = (content) => {
13
47
  return require_utils.hasMetaContent(content, "generator", "Lemmy");
14
48
  };
@@ -20,7 +54,7 @@ const lemmyHandler = {
20
54
  match: (url, content, headers) => {
21
55
  try {
22
56
  const { pathname } = new URL(url);
23
- if (!isCommunityPath(pathname) && !isUserPath(pathname)) return false;
57
+ if (!isCommunityPath(pathname) && !isUserPath(pathname) && !isHomePath(pathname)) return false;
24
58
  if (content && isLemmyHtml(content)) return true;
25
59
  if (headers && isLemmyHeaders(headers)) return true;
26
60
  } catch {}
@@ -28,16 +62,24 @@ const lemmyHandler = {
28
62
  },
29
63
  resolve: (url) => {
30
64
  try {
31
- const { origin, pathname } = new URL(url);
65
+ const { origin, pathname, searchParams } = new URL(url);
32
66
  const segments = pathname.split("/").filter(Boolean);
67
+ const sortSuffix = getQuerySuffix(searchParams);
33
68
  if (isCommunityPath(pathname) && segments[1]) return [{
34
- uri: `${origin}/feeds/c/${segments[1]}.xml`,
69
+ uri: `${origin}/feeds/c/${segments[1]}.xml${sortSuffix}`,
35
70
  hint: require_utils.composeHint("lemmy:community")
36
71
  }];
37
72
  if (isUserPath(pathname) && segments[1]) return [{
38
- uri: `${origin}/feeds/u/${segments[1]}.xml`,
73
+ uri: `${origin}/feeds/u/${segments[1]}.xml${sortSuffix}`,
39
74
  hint: require_utils.composeHint("lemmy:user")
40
75
  }];
76
+ if (isHomePath(pathname)) return [{
77
+ uri: `${origin}/feeds/all.xml${sortSuffix}`,
78
+ hint: require_utils.composeHint("lemmy:all")
79
+ }, {
80
+ uri: `${origin}/feeds/local.xml${sortSuffix}`,
81
+ hint: require_utils.composeHint("lemmy:local")
82
+ }];
41
83
  } catch {}
42
84
  return [];
43
85
  }
@@ -1,6 +1,37 @@
1
1
  import { composeHint, hasMetaContent } from "../../../common/utils.js";
2
2
  //#region src/feeds/platform/handlers/lemmy.ts
3
3
  const lemmyPoweredByRegex = /lemmy/i;
4
+ const validSorts = new Set([
5
+ "Active",
6
+ "Hot",
7
+ "New",
8
+ "Old",
9
+ "TopHour",
10
+ "TopSixHour",
11
+ "TopTwelveHour",
12
+ "TopDay",
13
+ "TopWeek",
14
+ "TopMonth",
15
+ "TopThreeMonths",
16
+ "TopSixMonths",
17
+ "TopNineMonths",
18
+ "TopYear",
19
+ "TopAll",
20
+ "Controversial",
21
+ "Scaled",
22
+ "MostComments",
23
+ "NewComments"
24
+ ]);
25
+ const numericRegex = /^\d+$/;
26
+ const getQuerySuffix = (searchParams) => {
27
+ const params = new URLSearchParams();
28
+ const sort = searchParams.get("sort");
29
+ if (sort && validSorts.has(sort)) params.set("sort", sort);
30
+ const limit = searchParams.get("limit");
31
+ if (limit && numericRegex.test(limit)) params.set("limit", limit);
32
+ const query = params.toString();
33
+ return query ? `?${query}` : "";
34
+ };
4
35
  const isCommunityPath = (pathname) => {
5
36
  const segments = pathname.split("/").filter(Boolean);
6
37
  return segments.length >= 2 && segments[0] === "c";
@@ -9,6 +40,9 @@ const isUserPath = (pathname) => {
9
40
  const segments = pathname.split("/").filter(Boolean);
10
41
  return segments.length >= 2 && segments[0] === "u";
11
42
  };
43
+ const isHomePath = (pathname) => {
44
+ return pathname === "/" || pathname === "" || pathname === "/home";
45
+ };
12
46
  const isLemmyHtml = (content) => {
13
47
  return hasMetaContent(content, "generator", "Lemmy");
14
48
  };
@@ -20,7 +54,7 @@ const lemmyHandler = {
20
54
  match: (url, content, headers) => {
21
55
  try {
22
56
  const { pathname } = new URL(url);
23
- if (!isCommunityPath(pathname) && !isUserPath(pathname)) return false;
57
+ if (!isCommunityPath(pathname) && !isUserPath(pathname) && !isHomePath(pathname)) return false;
24
58
  if (content && isLemmyHtml(content)) return true;
25
59
  if (headers && isLemmyHeaders(headers)) return true;
26
60
  } catch {}
@@ -28,16 +62,24 @@ const lemmyHandler = {
28
62
  },
29
63
  resolve: (url) => {
30
64
  try {
31
- const { origin, pathname } = new URL(url);
65
+ const { origin, pathname, searchParams } = new URL(url);
32
66
  const segments = pathname.split("/").filter(Boolean);
67
+ const sortSuffix = getQuerySuffix(searchParams);
33
68
  if (isCommunityPath(pathname) && segments[1]) return [{
34
- uri: `${origin}/feeds/c/${segments[1]}.xml`,
69
+ uri: `${origin}/feeds/c/${segments[1]}.xml${sortSuffix}`,
35
70
  hint: composeHint("lemmy:community")
36
71
  }];
37
72
  if (isUserPath(pathname) && segments[1]) return [{
38
- uri: `${origin}/feeds/u/${segments[1]}.xml`,
73
+ uri: `${origin}/feeds/u/${segments[1]}.xml${sortSuffix}`,
39
74
  hint: composeHint("lemmy:user")
40
75
  }];
76
+ if (isHomePath(pathname)) return [{
77
+ uri: `${origin}/feeds/all.xml${sortSuffix}`,
78
+ hint: composeHint("lemmy:all")
79
+ }, {
80
+ uri: `${origin}/feeds/local.xml${sortSuffix}`,
81
+ hint: composeHint("lemmy:local")
82
+ }];
41
83
  } catch {}
42
84
  return [];
43
85
  }
@@ -30,6 +30,10 @@ const letterboxdHandler = {
30
30
  const { pathname } = new URL(url);
31
31
  const pathSegments = pathname.split("/").filter(Boolean);
32
32
  if (pathSegments.length === 0) return [];
33
+ if (pathSegments[0] === "journal") return [{
34
+ uri: "https://letterboxd.com/journal/rss/",
35
+ hint: require_utils.composeHint("letterboxd:journal")
36
+ }];
33
37
  const username = pathSegments[0];
34
38
  if (require_utils.isAnyOf(username, excludedPaths)) return [];
35
39
  return [{
@@ -30,6 +30,10 @@ const letterboxdHandler = {
30
30
  const { pathname } = new URL(url);
31
31
  const pathSegments = pathname.split("/").filter(Boolean);
32
32
  if (pathSegments.length === 0) return [];
33
+ if (pathSegments[0] === "journal") return [{
34
+ uri: "https://letterboxd.com/journal/rss/",
35
+ hint: composeHint("letterboxd:journal")
36
+ }];
33
37
  const username = pathSegments[0];
34
38
  if (isAnyOf(username, excludedPaths)) return [];
35
39
  return [{
@@ -0,0 +1,25 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/libsyn.ts
3
+ const numericRegex = /^\d+$/;
4
+ const libsynHandler = {
5
+ match: (url) => {
6
+ return require_utils.isSubdomainOf(url, "libsyn.com");
7
+ },
8
+ resolve: (url) => {
9
+ const { origin, pathname } = new URL(url);
10
+ if (require_utils.isHostOf(url, "feeds.libsyn.com")) {
11
+ const showId = pathname.split("/").filter(Boolean)[0];
12
+ if (showId && numericRegex.test(showId)) return [{
13
+ uri: `https://feeds.libsyn.com/${showId}/rss`,
14
+ hint: require_utils.composeHint("libsyn:podcast")
15
+ }];
16
+ return [];
17
+ }
18
+ return [{
19
+ uri: `${origin}/rss`,
20
+ hint: require_utils.composeHint("libsyn:podcast")
21
+ }];
22
+ }
23
+ };
24
+ //#endregion
25
+ exports.libsynHandler = libsynHandler;
@@ -0,0 +1,25 @@
1
+ import { composeHint, isHostOf, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/libsyn.ts
3
+ const numericRegex = /^\d+$/;
4
+ const libsynHandler = {
5
+ match: (url) => {
6
+ return isSubdomainOf(url, "libsyn.com");
7
+ },
8
+ resolve: (url) => {
9
+ const { origin, pathname } = new URL(url);
10
+ if (isHostOf(url, "feeds.libsyn.com")) {
11
+ const showId = pathname.split("/").filter(Boolean)[0];
12
+ if (showId && numericRegex.test(showId)) return [{
13
+ uri: `https://feeds.libsyn.com/${showId}/rss`,
14
+ hint: composeHint("libsyn:podcast")
15
+ }];
16
+ return [];
17
+ }
18
+ return [{
19
+ uri: `${origin}/rss`,
20
+ hint: composeHint("libsyn:podcast")
21
+ }];
22
+ }
23
+ };
24
+ //#endregion
25
+ export { libsynHandler };