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,34 @@
1
+ import { composeHint } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/pleroma.ts
3
+ const profileRegex = /^\/users\/([^/]+)/;
4
+ const pleromaApiRegex = /\/api\/pleroma\//i;
5
+ const isPleromaHtml = (content) => {
6
+ return pleromaApiRegex.test(content);
7
+ };
8
+ const pleromaHandler = {
9
+ match: (url, content) => {
10
+ try {
11
+ if (!content || !isPleromaHtml(content)) return false;
12
+ const { pathname } = new URL(url);
13
+ return profileRegex.test(pathname);
14
+ } catch {}
15
+ return false;
16
+ },
17
+ resolve: (url) => {
18
+ try {
19
+ const { origin, pathname } = new URL(url);
20
+ const match = pathname.match(profileRegex);
21
+ if (!match?.[1]) return [];
22
+ return [{
23
+ uri: `${origin}/users/${match[1]}/feed.atom`,
24
+ hint: composeHint("pleroma:posts")
25
+ }, {
26
+ uri: `${origin}/users/${match[1]}/feed.rss`,
27
+ hint: composeHint("pleroma:posts-rss")
28
+ }];
29
+ } catch {}
30
+ return [];
31
+ }
32
+ };
33
+ //#endregion
34
+ export { pleromaHandler };
@@ -0,0 +1,29 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/podbean.ts
3
+ const domainSuffix = /\.podbean\.com$/i;
4
+ const reservedSlugs = new Set([
5
+ "www",
6
+ "feed",
7
+ "pbcdn1",
8
+ "sponsorship",
9
+ "podads",
10
+ "help",
11
+ "blog",
12
+ "support"
13
+ ]);
14
+ const podbeanHandler = {
15
+ match: (url) => {
16
+ if (!require_utils.isSubdomainOf(url, "podbean.com")) return false;
17
+ const slug = new URL(url).hostname.toLowerCase().replace(domainSuffix, "");
18
+ return !reservedSlugs.has(slug);
19
+ },
20
+ resolve: (url) => {
21
+ const { hostname } = new URL(url);
22
+ return [{
23
+ uri: `https://feed.podbean.com/${hostname.replace(domainSuffix, "")}/feed.xml`,
24
+ hint: require_utils.composeHint("podbean:podcast")
25
+ }];
26
+ }
27
+ };
28
+ //#endregion
29
+ exports.podbeanHandler = podbeanHandler;
@@ -0,0 +1,29 @@
1
+ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/podbean.ts
3
+ const domainSuffix = /\.podbean\.com$/i;
4
+ const reservedSlugs = new Set([
5
+ "www",
6
+ "feed",
7
+ "pbcdn1",
8
+ "sponsorship",
9
+ "podads",
10
+ "help",
11
+ "blog",
12
+ "support"
13
+ ]);
14
+ const podbeanHandler = {
15
+ match: (url) => {
16
+ if (!isSubdomainOf(url, "podbean.com")) return false;
17
+ const slug = new URL(url).hostname.toLowerCase().replace(domainSuffix, "");
18
+ return !reservedSlugs.has(slug);
19
+ },
20
+ resolve: (url) => {
21
+ const { hostname } = new URL(url);
22
+ return [{
23
+ uri: `https://feed.podbean.com/${hostname.replace(domainSuffix, "")}/feed.xml`,
24
+ hint: composeHint("podbean:podcast")
25
+ }];
26
+ }
27
+ };
28
+ //#endregion
29
+ export { podbeanHandler };
@@ -0,0 +1,29 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/podigee.ts
3
+ const domainSuffix = /\.podigee\.io$/i;
4
+ const reservedSlugs = new Set([
5
+ "www",
6
+ "app",
7
+ "help",
8
+ "hilfe",
9
+ "blog",
10
+ "status",
11
+ "player",
12
+ "cdn"
13
+ ]);
14
+ const podigeeHandler = {
15
+ match: (url) => {
16
+ if (!require_utils.isSubdomainOf(url, "podigee.io")) return false;
17
+ const slug = new URL(url).hostname.toLowerCase().replace(domainSuffix, "");
18
+ return !reservedSlugs.has(slug);
19
+ },
20
+ resolve: (url) => {
21
+ const { origin } = new URL(url);
22
+ return [{
23
+ uri: `${origin}/feed/mp3`,
24
+ hint: require_utils.composeHint("podigee:podcast")
25
+ }];
26
+ }
27
+ };
28
+ //#endregion
29
+ exports.podigeeHandler = podigeeHandler;
@@ -0,0 +1,29 @@
1
+ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/podigee.ts
3
+ const domainSuffix = /\.podigee\.io$/i;
4
+ const reservedSlugs = new Set([
5
+ "www",
6
+ "app",
7
+ "help",
8
+ "hilfe",
9
+ "blog",
10
+ "status",
11
+ "player",
12
+ "cdn"
13
+ ]);
14
+ const podigeeHandler = {
15
+ match: (url) => {
16
+ if (!isSubdomainOf(url, "podigee.io")) return false;
17
+ const slug = new URL(url).hostname.toLowerCase().replace(domainSuffix, "");
18
+ return !reservedSlugs.has(slug);
19
+ },
20
+ resolve: (url) => {
21
+ const { origin } = new URL(url);
22
+ return [{
23
+ uri: `${origin}/feed/mp3`,
24
+ hint: composeHint("podigee:podcast")
25
+ }];
26
+ }
27
+ };
28
+ //#endregion
29
+ export { podigeeHandler };
@@ -0,0 +1,24 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/posthaven.ts
3
+ const tagRegex = /^\/tag\/([^/]+)/;
4
+ const posthavenHandler = {
5
+ match: (url) => {
6
+ return require_utils.isSubdomainOf(url, "posthaven.com");
7
+ },
8
+ resolve: (url) => {
9
+ const { origin, pathname } = new URL(url);
10
+ const uris = [];
11
+ const tagMatch = pathname.match(tagRegex);
12
+ if (tagMatch?.[1]) uris.push({
13
+ uri: `${origin}/tag/${tagMatch[1]}.atom`,
14
+ hint: require_utils.composeHint("posthaven:tag")
15
+ });
16
+ uris.push({
17
+ uri: `${origin}/posts.atom`,
18
+ hint: require_utils.composeHint("posthaven:posts")
19
+ });
20
+ return uris;
21
+ }
22
+ };
23
+ //#endregion
24
+ exports.posthavenHandler = posthavenHandler;
@@ -0,0 +1,24 @@
1
+ import { composeHint, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/posthaven.ts
3
+ const tagRegex = /^\/tag\/([^/]+)/;
4
+ const posthavenHandler = {
5
+ match: (url) => {
6
+ return isSubdomainOf(url, "posthaven.com");
7
+ },
8
+ resolve: (url) => {
9
+ const { origin, pathname } = new URL(url);
10
+ const uris = [];
11
+ const tagMatch = pathname.match(tagRegex);
12
+ if (tagMatch?.[1]) uris.push({
13
+ uri: `${origin}/tag/${tagMatch[1]}.atom`,
14
+ hint: composeHint("posthaven:tag")
15
+ });
16
+ uris.push({
17
+ uri: `${origin}/posts.atom`,
18
+ hint: composeHint("posthaven:posts")
19
+ });
20
+ return uris;
21
+ }
22
+ };
23
+ //#endregion
24
+ export { posthavenHandler };
@@ -0,0 +1,26 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/prose.ts
3
+ const apexHosts = ["prose.sh", "www.prose.sh"];
4
+ const proseHandler = {
5
+ match: (url) => {
6
+ return require_utils.isSubdomainOf(url, "prose.sh") || require_utils.isHostOf(url, apexHosts);
7
+ },
8
+ resolve: (url) => {
9
+ const { origin, searchParams } = new URL(url);
10
+ if (require_utils.isHostOf(url, apexHosts)) return [{
11
+ uri: "https://prose.sh/rss",
12
+ hint: require_utils.composeHint("prose:discovery")
13
+ }];
14
+ const tag = searchParams.get("tag");
15
+ if (tag) return [{
16
+ uri: `${origin}/rss?tag=${encodeURIComponent(tag)}`,
17
+ hint: require_utils.composeHint("prose:tag")
18
+ }];
19
+ return [{
20
+ uri: `${origin}/rss`,
21
+ hint: require_utils.composeHint("prose:blog")
22
+ }];
23
+ }
24
+ };
25
+ //#endregion
26
+ exports.proseHandler = proseHandler;
@@ -0,0 +1,26 @@
1
+ import { composeHint, isHostOf, isSubdomainOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/prose.ts
3
+ const apexHosts = ["prose.sh", "www.prose.sh"];
4
+ const proseHandler = {
5
+ match: (url) => {
6
+ return isSubdomainOf(url, "prose.sh") || isHostOf(url, apexHosts);
7
+ },
8
+ resolve: (url) => {
9
+ const { origin, searchParams } = new URL(url);
10
+ if (isHostOf(url, apexHosts)) return [{
11
+ uri: "https://prose.sh/rss",
12
+ hint: composeHint("prose:discovery")
13
+ }];
14
+ const tag = searchParams.get("tag");
15
+ if (tag) return [{
16
+ uri: `${origin}/rss?tag=${encodeURIComponent(tag)}`,
17
+ hint: composeHint("prose:tag")
18
+ }];
19
+ return [{
20
+ uri: `${origin}/rss`,
21
+ hint: composeHint("prose:blog")
22
+ }];
23
+ }
24
+ };
25
+ //#endregion
26
+ export { proseHandler };
@@ -0,0 +1,58 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/qiita.ts
3
+ const hosts = ["qiita.com", "www.qiita.com"];
4
+ const excludedPaths = [
5
+ "about",
6
+ "api",
7
+ "login",
8
+ "official-columns",
9
+ "organizations",
10
+ "popular-items",
11
+ "privacy",
12
+ "search",
13
+ "settings",
14
+ "signup",
15
+ "tags",
16
+ "terms",
17
+ "trend"
18
+ ];
19
+ const tagRegex = /^\/tags\/([^/]+)/;
20
+ const organizationRegex = /^\/organizations\/([^/]+)/;
21
+ const popularItemsRegex = /^\/popular-items(\/|$)/;
22
+ const officialColumnsRegex = /^\/official-columns(\/|$)/;
23
+ const qiitaHandler = {
24
+ match: (url) => {
25
+ return require_utils.isHostOf(url, hosts);
26
+ },
27
+ resolve: (url) => {
28
+ const { pathname } = new URL(url);
29
+ const tagMatch = pathname.match(tagRegex);
30
+ if (tagMatch?.[1]) return [{
31
+ uri: `https://qiita.com/tags/${tagMatch[1]}/feed.atom`,
32
+ hint: require_utils.composeHint("qiita:tag")
33
+ }];
34
+ const orgMatch = pathname.match(organizationRegex);
35
+ if (orgMatch?.[1]) return [{
36
+ uri: `https://qiita.com/organizations/${orgMatch[1]}/activities.atom`,
37
+ hint: require_utils.composeHint("qiita:organization")
38
+ }];
39
+ if (popularItemsRegex.test(pathname)) return [{
40
+ uri: "https://qiita.com/popular-items/feed.atom",
41
+ hint: require_utils.composeHint("qiita:popular")
42
+ }];
43
+ if (officialColumnsRegex.test(pathname)) return [{
44
+ uri: "https://qiita.com/official-columns/feed/",
45
+ hint: require_utils.composeHint("qiita:zine")
46
+ }];
47
+ const pathSegments = pathname.split("/").filter(Boolean);
48
+ if (pathSegments.length === 0) return [];
49
+ const username = pathSegments[0];
50
+ if (require_utils.isAnyOf(username, excludedPaths)) return [];
51
+ return [{
52
+ uri: `https://qiita.com/${username}/feed.atom`,
53
+ hint: require_utils.composeHint("qiita:posts")
54
+ }];
55
+ }
56
+ };
57
+ //#endregion
58
+ exports.qiitaHandler = qiitaHandler;
@@ -0,0 +1,58 @@
1
+ import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
+ //#region src/feeds/platform/handlers/qiita.ts
3
+ const hosts = ["qiita.com", "www.qiita.com"];
4
+ const excludedPaths = [
5
+ "about",
6
+ "api",
7
+ "login",
8
+ "official-columns",
9
+ "organizations",
10
+ "popular-items",
11
+ "privacy",
12
+ "search",
13
+ "settings",
14
+ "signup",
15
+ "tags",
16
+ "terms",
17
+ "trend"
18
+ ];
19
+ const tagRegex = /^\/tags\/([^/]+)/;
20
+ const organizationRegex = /^\/organizations\/([^/]+)/;
21
+ const popularItemsRegex = /^\/popular-items(\/|$)/;
22
+ const officialColumnsRegex = /^\/official-columns(\/|$)/;
23
+ const qiitaHandler = {
24
+ match: (url) => {
25
+ return isHostOf(url, hosts);
26
+ },
27
+ resolve: (url) => {
28
+ const { pathname } = new URL(url);
29
+ const tagMatch = pathname.match(tagRegex);
30
+ if (tagMatch?.[1]) return [{
31
+ uri: `https://qiita.com/tags/${tagMatch[1]}/feed.atom`,
32
+ hint: composeHint("qiita:tag")
33
+ }];
34
+ const orgMatch = pathname.match(organizationRegex);
35
+ if (orgMatch?.[1]) return [{
36
+ uri: `https://qiita.com/organizations/${orgMatch[1]}/activities.atom`,
37
+ hint: composeHint("qiita:organization")
38
+ }];
39
+ if (popularItemsRegex.test(pathname)) return [{
40
+ uri: "https://qiita.com/popular-items/feed.atom",
41
+ hint: composeHint("qiita:popular")
42
+ }];
43
+ if (officialColumnsRegex.test(pathname)) return [{
44
+ uri: "https://qiita.com/official-columns/feed/",
45
+ hint: composeHint("qiita:zine")
46
+ }];
47
+ const pathSegments = pathname.split("/").filter(Boolean);
48
+ if (pathSegments.length === 0) return [];
49
+ const username = pathSegments[0];
50
+ if (isAnyOf(username, excludedPaths)) return [];
51
+ return [{
52
+ uri: `https://qiita.com/${username}/feed.atom`,
53
+ hint: composeHint("qiita:posts")
54
+ }];
55
+ }
56
+ };
57
+ //#endregion
58
+ export { qiitaHandler };
@@ -1,10 +1,13 @@
1
1
  const require_utils = require("../../../common/utils.cjs");
2
2
  //#region src/feeds/platform/handlers/reddit.ts
3
3
  const commentsRegex = /^\/r\/([^/]+)\/comments\/([^/]+)/;
4
+ const subredditWikiRegex = /^\/r\/([^/]+)\/wiki/;
5
+ const subredditSearchRegex = /^\/r\/([^/]+)\/search/;
4
6
  const subredditRegex = /^\/r\/([^/]+)(?:\/([^/]+))?/;
5
7
  const multiredditRegex = /^\/user\/([^/]+)\/m\/([^/]+)/;
6
- const userRegex = /^\/(u|user)\/([^/]+)/;
8
+ const userRegex = /^\/(?:u|user)\/([^/]+)(?:\/(submitted|comments))?/;
7
9
  const domainRegex = /^\/domain\/([^/]+)/;
10
+ const subredditsRegex = /^\/(?:subreddits|reddits)(?:\/(new|popular))?/;
8
11
  const hosts = [
9
12
  "reddit.com",
10
13
  "www.reddit.com",
@@ -16,18 +19,71 @@ const sortOptions = [
16
19
  "new",
17
20
  "rising",
18
21
  "controversial",
19
- "top"
22
+ "top",
23
+ "best"
20
24
  ];
25
+ const timeOptions = new Set([
26
+ "hour",
27
+ "day",
28
+ "week",
29
+ "month",
30
+ "year",
31
+ "all"
32
+ ]);
33
+ const timeFilteredSorts = new Set(["top", "controversial"]);
34
+ const getTimeframeSuffix = (sort, searchParams) => {
35
+ if (!timeFilteredSorts.has(sort)) return "";
36
+ const timeframe = searchParams.get("t");
37
+ if (timeframe && timeOptions.has(timeframe)) return `?t=${timeframe}`;
38
+ return "";
39
+ };
21
40
  const redditHandler = {
22
41
  match: (url) => {
23
42
  return require_utils.isHostOf(url, hosts);
24
43
  },
25
44
  resolve: (url) => {
26
- const { pathname } = new URL(url);
27
- if (pathname.split("/").filter(Boolean).length === 0) return [{
45
+ const { pathname, searchParams } = new URL(url);
46
+ const pathSegments = pathname.split("/").filter(Boolean);
47
+ if (pathSegments.length === 0) return [{
28
48
  uri: "https://www.reddit.com/.rss",
29
49
  hint: require_utils.composeHint("reddit:posts")
30
50
  }];
51
+ if (pathSegments.length === 1 && require_utils.isAnyOf(pathSegments[0], sortOptions)) {
52
+ const sort = pathSegments[0];
53
+ return [{
54
+ uri: `https://www.reddit.com/${sort}/.rss${getTimeframeSuffix(sort, searchParams)}`,
55
+ hint: require_utils.composeHint("reddit:posts")
56
+ }];
57
+ }
58
+ if (pathSegments[0] === "search") {
59
+ const query = searchParams.get("q");
60
+ if (query) return [{
61
+ uri: `https://www.reddit.com/search.rss?q=${encodeURIComponent(query)}`,
62
+ hint: require_utils.composeHint("reddit:search")
63
+ }];
64
+ }
65
+ const subredditsMatch = pathname.match(subredditsRegex);
66
+ if (subredditsMatch) {
67
+ const sort = subredditsMatch[1];
68
+ return [{
69
+ uri: `https://www.reddit.com/${sort ? `subreddits/${sort}` : "subreddits"}/.rss`,
70
+ hint: require_utils.composeHint("reddit:subreddits")
71
+ }];
72
+ }
73
+ const subredditSearchMatch = pathname.match(subredditSearchRegex);
74
+ if (subredditSearchMatch?.[1]) {
75
+ const subreddit = subredditSearchMatch[1];
76
+ const query = searchParams.get("q");
77
+ if (query) return [{
78
+ uri: `https://www.reddit.com/r/${subreddit}/search.rss?q=${encodeURIComponent(query)}&restrict_sr=on`,
79
+ hint: require_utils.composeHint("reddit:search")
80
+ }];
81
+ }
82
+ const subredditWikiMatch = pathname.match(subredditWikiRegex);
83
+ if (subredditWikiMatch?.[1]) return [{
84
+ uri: `https://www.reddit.com/r/${subredditWikiMatch[1]}/wiki/index.rss`,
85
+ hint: require_utils.composeHint("reddit:wiki")
86
+ }];
31
87
  const commentsMatch = pathname.match(commentsRegex);
32
88
  if (commentsMatch?.[1] && commentsMatch?.[2]) return [{
33
89
  uri: `https://www.reddit.com/r/${commentsMatch[1]}/comments/${commentsMatch[2]}/.rss`,
@@ -39,7 +95,7 @@ const redditHandler = {
39
95
  const sort = subredditMatch[2];
40
96
  const uris = [];
41
97
  if (sort && require_utils.isAnyOf(sort, sortOptions)) uris.push({
42
- uri: `https://www.reddit.com/r/${subreddit}/${sort}/.rss`,
98
+ uri: `https://www.reddit.com/r/${subreddit}/${sort}/.rss${getTimeframeSuffix(sort, searchParams)}`,
43
99
  hint: require_utils.composeHint("reddit:posts")
44
100
  });
45
101
  else uris.push({
@@ -58,10 +114,28 @@ const redditHandler = {
58
114
  hint: require_utils.composeHint("reddit:multireddit")
59
115
  }];
60
116
  const userMatch = pathname.match(userRegex);
61
- if (userMatch?.[2]) return [{
62
- uri: `https://www.reddit.com/user/${userMatch[2]}/.rss`,
63
- hint: require_utils.composeHint("reddit:posts")
64
- }];
117
+ if (userMatch?.[1]) {
118
+ const username = userMatch[1];
119
+ const filter = userMatch[2];
120
+ if (filter === "submitted") return [{
121
+ uri: `https://www.reddit.com/user/${username}/submitted/.rss`,
122
+ hint: require_utils.composeHint("reddit:user-submitted")
123
+ }, {
124
+ uri: `https://www.reddit.com/user/${username}/.rss`,
125
+ hint: require_utils.composeHint("reddit:posts")
126
+ }];
127
+ if (filter === "comments") return [{
128
+ uri: `https://www.reddit.com/user/${username}/comments/.rss`,
129
+ hint: require_utils.composeHint("reddit:user-comments")
130
+ }, {
131
+ uri: `https://www.reddit.com/user/${username}/.rss`,
132
+ hint: require_utils.composeHint("reddit:posts")
133
+ }];
134
+ return [{
135
+ uri: `https://www.reddit.com/user/${username}/.rss`,
136
+ hint: require_utils.composeHint("reddit:posts")
137
+ }];
138
+ }
65
139
  const domainMatch = pathname.match(domainRegex);
66
140
  if (domainMatch?.[1]) return [{
67
141
  uri: `https://www.reddit.com/domain/${domainMatch[1]}/.rss`,
@@ -1,10 +1,13 @@
1
1
  import { composeHint, isAnyOf, isHostOf } from "../../../common/utils.js";
2
2
  //#region src/feeds/platform/handlers/reddit.ts
3
3
  const commentsRegex = /^\/r\/([^/]+)\/comments\/([^/]+)/;
4
+ const subredditWikiRegex = /^\/r\/([^/]+)\/wiki/;
5
+ const subredditSearchRegex = /^\/r\/([^/]+)\/search/;
4
6
  const subredditRegex = /^\/r\/([^/]+)(?:\/([^/]+))?/;
5
7
  const multiredditRegex = /^\/user\/([^/]+)\/m\/([^/]+)/;
6
- const userRegex = /^\/(u|user)\/([^/]+)/;
8
+ const userRegex = /^\/(?:u|user)\/([^/]+)(?:\/(submitted|comments))?/;
7
9
  const domainRegex = /^\/domain\/([^/]+)/;
10
+ const subredditsRegex = /^\/(?:subreddits|reddits)(?:\/(new|popular))?/;
8
11
  const hosts = [
9
12
  "reddit.com",
10
13
  "www.reddit.com",
@@ -16,18 +19,71 @@ const sortOptions = [
16
19
  "new",
17
20
  "rising",
18
21
  "controversial",
19
- "top"
22
+ "top",
23
+ "best"
20
24
  ];
25
+ const timeOptions = new Set([
26
+ "hour",
27
+ "day",
28
+ "week",
29
+ "month",
30
+ "year",
31
+ "all"
32
+ ]);
33
+ const timeFilteredSorts = new Set(["top", "controversial"]);
34
+ const getTimeframeSuffix = (sort, searchParams) => {
35
+ if (!timeFilteredSorts.has(sort)) return "";
36
+ const timeframe = searchParams.get("t");
37
+ if (timeframe && timeOptions.has(timeframe)) return `?t=${timeframe}`;
38
+ return "";
39
+ };
21
40
  const redditHandler = {
22
41
  match: (url) => {
23
42
  return isHostOf(url, hosts);
24
43
  },
25
44
  resolve: (url) => {
26
- const { pathname } = new URL(url);
27
- if (pathname.split("/").filter(Boolean).length === 0) return [{
45
+ const { pathname, searchParams } = new URL(url);
46
+ const pathSegments = pathname.split("/").filter(Boolean);
47
+ if (pathSegments.length === 0) return [{
28
48
  uri: "https://www.reddit.com/.rss",
29
49
  hint: composeHint("reddit:posts")
30
50
  }];
51
+ if (pathSegments.length === 1 && isAnyOf(pathSegments[0], sortOptions)) {
52
+ const sort = pathSegments[0];
53
+ return [{
54
+ uri: `https://www.reddit.com/${sort}/.rss${getTimeframeSuffix(sort, searchParams)}`,
55
+ hint: composeHint("reddit:posts")
56
+ }];
57
+ }
58
+ if (pathSegments[0] === "search") {
59
+ const query = searchParams.get("q");
60
+ if (query) return [{
61
+ uri: `https://www.reddit.com/search.rss?q=${encodeURIComponent(query)}`,
62
+ hint: composeHint("reddit:search")
63
+ }];
64
+ }
65
+ const subredditsMatch = pathname.match(subredditsRegex);
66
+ if (subredditsMatch) {
67
+ const sort = subredditsMatch[1];
68
+ return [{
69
+ uri: `https://www.reddit.com/${sort ? `subreddits/${sort}` : "subreddits"}/.rss`,
70
+ hint: composeHint("reddit:subreddits")
71
+ }];
72
+ }
73
+ const subredditSearchMatch = pathname.match(subredditSearchRegex);
74
+ if (subredditSearchMatch?.[1]) {
75
+ const subreddit = subredditSearchMatch[1];
76
+ const query = searchParams.get("q");
77
+ if (query) return [{
78
+ uri: `https://www.reddit.com/r/${subreddit}/search.rss?q=${encodeURIComponent(query)}&restrict_sr=on`,
79
+ hint: composeHint("reddit:search")
80
+ }];
81
+ }
82
+ const subredditWikiMatch = pathname.match(subredditWikiRegex);
83
+ if (subredditWikiMatch?.[1]) return [{
84
+ uri: `https://www.reddit.com/r/${subredditWikiMatch[1]}/wiki/index.rss`,
85
+ hint: composeHint("reddit:wiki")
86
+ }];
31
87
  const commentsMatch = pathname.match(commentsRegex);
32
88
  if (commentsMatch?.[1] && commentsMatch?.[2]) return [{
33
89
  uri: `https://www.reddit.com/r/${commentsMatch[1]}/comments/${commentsMatch[2]}/.rss`,
@@ -39,7 +95,7 @@ const redditHandler = {
39
95
  const sort = subredditMatch[2];
40
96
  const uris = [];
41
97
  if (sort && isAnyOf(sort, sortOptions)) uris.push({
42
- uri: `https://www.reddit.com/r/${subreddit}/${sort}/.rss`,
98
+ uri: `https://www.reddit.com/r/${subreddit}/${sort}/.rss${getTimeframeSuffix(sort, searchParams)}`,
43
99
  hint: composeHint("reddit:posts")
44
100
  });
45
101
  else uris.push({
@@ -58,10 +114,28 @@ const redditHandler = {
58
114
  hint: composeHint("reddit:multireddit")
59
115
  }];
60
116
  const userMatch = pathname.match(userRegex);
61
- if (userMatch?.[2]) return [{
62
- uri: `https://www.reddit.com/user/${userMatch[2]}/.rss`,
63
- hint: composeHint("reddit:posts")
64
- }];
117
+ if (userMatch?.[1]) {
118
+ const username = userMatch[1];
119
+ const filter = userMatch[2];
120
+ if (filter === "submitted") return [{
121
+ uri: `https://www.reddit.com/user/${username}/submitted/.rss`,
122
+ hint: composeHint("reddit:user-submitted")
123
+ }, {
124
+ uri: `https://www.reddit.com/user/${username}/.rss`,
125
+ hint: composeHint("reddit:posts")
126
+ }];
127
+ if (filter === "comments") return [{
128
+ uri: `https://www.reddit.com/user/${username}/comments/.rss`,
129
+ hint: composeHint("reddit:user-comments")
130
+ }, {
131
+ uri: `https://www.reddit.com/user/${username}/.rss`,
132
+ hint: composeHint("reddit:posts")
133
+ }];
134
+ return [{
135
+ uri: `https://www.reddit.com/user/${username}/.rss`,
136
+ hint: composeHint("reddit:posts")
137
+ }];
138
+ }
65
139
  const domainMatch = pathname.match(domainRegex);
66
140
  if (domainMatch?.[1]) return [{
67
141
  uri: `https://www.reddit.com/domain/${domainMatch[1]}/.rss`,
@@ -0,0 +1,20 @@
1
+ const require_utils = require("../../../common/utils.cjs");
2
+ //#region src/feeds/platform/handlers/rssCom.ts
3
+ const hosts = ["rss.com", "www.rss.com"];
4
+ const podcastRegex = /^\/(?:[a-z]{2}\/)?podcasts\/([^/]+)/;
5
+ const rssComHandler = {
6
+ match: (url) => {
7
+ return require_utils.isHostOf(url, hosts);
8
+ },
9
+ resolve: (url) => {
10
+ const { pathname } = new URL(url);
11
+ const match = pathname.match(podcastRegex);
12
+ if (!match?.[1]) return [];
13
+ return [{
14
+ uri: `https://media.rss.com/${match[1]}/feed.xml`,
15
+ hint: require_utils.composeHint("rss-com:podcast")
16
+ }];
17
+ }
18
+ };
19
+ //#endregion
20
+ exports.rssComHandler = rssComHandler;