feedscout 1.0.0 → 1.2.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.
- package/README.md +10 -7
- package/dist/blogrolls/index.cjs +9 -3
- package/dist/blogrolls/index.d.cts +1 -1
- package/dist/blogrolls/index.d.ts +1 -1
- package/dist/blogrolls/index.js +9 -3
- package/dist/common/discover/utils.cjs +26 -0
- package/dist/common/discover/utils.js +26 -1
- package/dist/common/locales.cjs +1 -0
- package/dist/common/locales.js +1 -0
- package/dist/common/types.d.cts +7 -5
- package/dist/common/types.d.ts +7 -5
- package/dist/common/uris/headers/index.cjs +6 -3
- package/dist/common/uris/headers/index.js +6 -3
- package/dist/common/uris/index.cjs +2 -0
- package/dist/common/uris/index.js +2 -0
- package/dist/common/uris/platform/index.cjs +12 -0
- package/dist/common/uris/platform/index.js +11 -0
- package/dist/common/uris/platform/types.d.cts +11 -0
- package/dist/common/uris/platform/types.d.ts +11 -0
- package/dist/common/utils.cjs +10 -0
- package/dist/common/utils.d.cts +9 -0
- package/dist/common/utils.d.ts +9 -0
- package/dist/common/utils.js +7 -1
- package/dist/feeds/defaults.cjs +43 -0
- package/dist/feeds/defaults.d.cts +3 -1
- package/dist/feeds/defaults.d.ts +3 -1
- package/dist/feeds/defaults.js +44 -1
- package/dist/feeds/index.cjs +10 -3
- package/dist/feeds/index.d.cts +1 -1
- package/dist/feeds/index.d.ts +1 -1
- package/dist/feeds/index.js +11 -4
- package/dist/feeds/platform/handlers/behance.cjs +45 -0
- package/dist/feeds/platform/handlers/behance.js +45 -0
- package/dist/feeds/platform/handlers/blogspot.cjs +24 -0
- package/dist/feeds/platform/handlers/blogspot.js +23 -0
- package/dist/feeds/platform/handlers/bluesky.cjs +18 -0
- package/dist/feeds/platform/handlers/bluesky.js +18 -0
- package/dist/feeds/platform/handlers/dailymotion.cjs +66 -0
- package/dist/feeds/platform/handlers/dailymotion.js +66 -0
- package/dist/feeds/platform/handlers/deviantart.cjs +50 -0
- package/dist/feeds/platform/handlers/deviantart.js +50 -0
- package/dist/feeds/platform/handlers/devto.cjs +44 -0
- package/dist/feeds/platform/handlers/devto.js +44 -0
- package/dist/feeds/platform/handlers/github.cjs +89 -0
- package/dist/feeds/platform/handlers/github.js +89 -0
- package/dist/feeds/platform/handlers/githubGist.cjs +42 -0
- package/dist/feeds/platform/handlers/githubGist.js +42 -0
- package/dist/feeds/platform/handlers/gitlab.cjs +53 -0
- package/dist/feeds/platform/handlers/gitlab.js +53 -0
- package/dist/feeds/platform/handlers/kickstarter.cjs +18 -0
- package/dist/feeds/platform/handlers/kickstarter.js +18 -0
- package/dist/feeds/platform/handlers/lobsters.cjs +34 -0
- package/dist/feeds/platform/handlers/lobsters.js +34 -0
- package/dist/feeds/platform/handlers/medium.cjs +47 -0
- package/dist/feeds/platform/handlers/medium.js +47 -0
- package/dist/feeds/platform/handlers/pinterest.cjs +48 -0
- package/dist/feeds/platform/handlers/pinterest.js +48 -0
- package/dist/feeds/platform/handlers/producthunt.cjs +22 -0
- package/dist/feeds/platform/handlers/producthunt.js +22 -0
- package/dist/feeds/platform/handlers/reddit.cjs +47 -0
- package/dist/feeds/platform/handlers/reddit.js +47 -0
- package/dist/feeds/platform/handlers/soundcloud.cjs +37 -0
- package/dist/feeds/platform/handlers/soundcloud.js +37 -0
- package/dist/feeds/platform/handlers/substack.cjs +15 -0
- package/dist/feeds/platform/handlers/substack.js +15 -0
- package/dist/feeds/platform/handlers/tumblr.cjs +18 -0
- package/dist/feeds/platform/handlers/tumblr.js +18 -0
- package/dist/feeds/platform/handlers/wordpress.cjs +30 -0
- package/dist/feeds/platform/handlers/wordpress.js +30 -0
- package/dist/feeds/platform/handlers/youtube.cjs +56 -0
- package/dist/feeds/platform/handlers/youtube.js +56 -0
- package/dist/feeds.cjs +1 -0
- package/dist/feeds.d.cts +2 -2
- package/dist/feeds.d.ts +2 -2
- package/dist/feeds.js +2 -2
- package/dist/hubs/discover/index.cjs +7 -6
- package/dist/hubs/discover/index.js +5 -4
- package/dist/hubs/discover/types.d.cts +2 -1
- package/dist/hubs/discover/types.d.ts +2 -1
- package/dist/hubs/headers/index.cjs +3 -3
- package/dist/hubs/headers/index.js +3 -3
- package/dist/hubs/html/index.cjs +3 -3
- package/dist/hubs/html/index.js +3 -3
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/utils.cjs +8 -0
- package/dist/utils.d.cts +2 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +3 -0
- package/package.json +32 -32
- package/dist/adapters.cjs +0 -6
- package/dist/adapters.d.cts +0 -2
- package/dist/adapters.d.ts +0 -2
- package/dist/adapters.js +0 -3
- package/dist/common/discover/adapters.cjs +0 -76
- package/dist/common/discover/adapters.d.cts +0 -10
- package/dist/common/discover/adapters.d.ts +0 -10
- package/dist/common/discover/adapters.js +0 -72
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/github.ts
|
|
4
|
+
const hosts = ["github.com", "www.github.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"about",
|
|
7
|
+
"account",
|
|
8
|
+
"apps",
|
|
9
|
+
"blog",
|
|
10
|
+
"careers",
|
|
11
|
+
"codespaces",
|
|
12
|
+
"collections",
|
|
13
|
+
"contact",
|
|
14
|
+
"copilot",
|
|
15
|
+
"customer-stories",
|
|
16
|
+
"dashboard",
|
|
17
|
+
"education",
|
|
18
|
+
"enterprise",
|
|
19
|
+
"events",
|
|
20
|
+
"explore",
|
|
21
|
+
"features",
|
|
22
|
+
"feed",
|
|
23
|
+
"home",
|
|
24
|
+
"issues",
|
|
25
|
+
"join",
|
|
26
|
+
"login",
|
|
27
|
+
"marketplace",
|
|
28
|
+
"new",
|
|
29
|
+
"nonprofit",
|
|
30
|
+
"notifications",
|
|
31
|
+
"organizations",
|
|
32
|
+
"orgs",
|
|
33
|
+
"password_reset",
|
|
34
|
+
"premium-support",
|
|
35
|
+
"pricing",
|
|
36
|
+
"pulls",
|
|
37
|
+
"readme",
|
|
38
|
+
"resources",
|
|
39
|
+
"search",
|
|
40
|
+
"security",
|
|
41
|
+
"sessions",
|
|
42
|
+
"settings",
|
|
43
|
+
"site",
|
|
44
|
+
"sponsors",
|
|
45
|
+
"stars",
|
|
46
|
+
"team",
|
|
47
|
+
"topics",
|
|
48
|
+
"trending",
|
|
49
|
+
"watching"
|
|
50
|
+
];
|
|
51
|
+
const githubHandler = {
|
|
52
|
+
match: (url) => {
|
|
53
|
+
return require_utils.isHostOf(url, hosts);
|
|
54
|
+
},
|
|
55
|
+
resolve: (url) => {
|
|
56
|
+
const { pathname } = new URL(url);
|
|
57
|
+
const uris = [];
|
|
58
|
+
const userMatch = pathname.match(/^\/([^/]+)\/?$/);
|
|
59
|
+
if (userMatch?.[1] && !require_utils.isAnyOf(userMatch[1], excludedPaths)) {
|
|
60
|
+
const user = userMatch[1];
|
|
61
|
+
uris.push(`https://github.com/${user}.atom`);
|
|
62
|
+
return uris;
|
|
63
|
+
}
|
|
64
|
+
const repoMatch = pathname.match(/^\/([^/]+)\/([^/]+)/);
|
|
65
|
+
const owner = repoMatch?.[1];
|
|
66
|
+
const repo = repoMatch?.[2];
|
|
67
|
+
if (!owner || !repo || require_utils.isAnyOf(owner, excludedPaths)) return [];
|
|
68
|
+
uris.push(`https://github.com/${owner}/${repo}/releases.atom`);
|
|
69
|
+
uris.push(`https://github.com/${owner}/${repo}/commits.atom`);
|
|
70
|
+
uris.push(`https://github.com/${owner}/${repo}/tags.atom`);
|
|
71
|
+
if (/\/wiki(\/|$)/.test(pathname)) uris.push(`https://github.com/${owner}/${repo}/wiki.atom`);
|
|
72
|
+
if (/\/discussions(\/|$)/.test(pathname)) uris.push(`https://github.com/${owner}/${repo}/discussions.atom`);
|
|
73
|
+
const branchMatch = pathname.match(/^\/[^/]+\/[^/]+\/tree\/([^/]+)\/?$/);
|
|
74
|
+
if (branchMatch?.[1]) {
|
|
75
|
+
const branch = branchMatch[1];
|
|
76
|
+
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}.atom`);
|
|
77
|
+
}
|
|
78
|
+
const fileMatch = pathname.match(/^\/[^/]+\/[^/]+\/(?:blob|commits)\/([^/]+)\/(.+)/);
|
|
79
|
+
if (fileMatch?.[1] && fileMatch?.[2]) {
|
|
80
|
+
const branch = fileMatch[1];
|
|
81
|
+
const filePath = fileMatch[2];
|
|
82
|
+
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}/${filePath}.atom`);
|
|
83
|
+
}
|
|
84
|
+
return uris;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
exports.githubHandler = githubHandler;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/github.ts
|
|
4
|
+
const hosts = ["github.com", "www.github.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"about",
|
|
7
|
+
"account",
|
|
8
|
+
"apps",
|
|
9
|
+
"blog",
|
|
10
|
+
"careers",
|
|
11
|
+
"codespaces",
|
|
12
|
+
"collections",
|
|
13
|
+
"contact",
|
|
14
|
+
"copilot",
|
|
15
|
+
"customer-stories",
|
|
16
|
+
"dashboard",
|
|
17
|
+
"education",
|
|
18
|
+
"enterprise",
|
|
19
|
+
"events",
|
|
20
|
+
"explore",
|
|
21
|
+
"features",
|
|
22
|
+
"feed",
|
|
23
|
+
"home",
|
|
24
|
+
"issues",
|
|
25
|
+
"join",
|
|
26
|
+
"login",
|
|
27
|
+
"marketplace",
|
|
28
|
+
"new",
|
|
29
|
+
"nonprofit",
|
|
30
|
+
"notifications",
|
|
31
|
+
"organizations",
|
|
32
|
+
"orgs",
|
|
33
|
+
"password_reset",
|
|
34
|
+
"premium-support",
|
|
35
|
+
"pricing",
|
|
36
|
+
"pulls",
|
|
37
|
+
"readme",
|
|
38
|
+
"resources",
|
|
39
|
+
"search",
|
|
40
|
+
"security",
|
|
41
|
+
"sessions",
|
|
42
|
+
"settings",
|
|
43
|
+
"site",
|
|
44
|
+
"sponsors",
|
|
45
|
+
"stars",
|
|
46
|
+
"team",
|
|
47
|
+
"topics",
|
|
48
|
+
"trending",
|
|
49
|
+
"watching"
|
|
50
|
+
];
|
|
51
|
+
const githubHandler = {
|
|
52
|
+
match: (url) => {
|
|
53
|
+
return isHostOf(url, hosts);
|
|
54
|
+
},
|
|
55
|
+
resolve: (url) => {
|
|
56
|
+
const { pathname } = new URL(url);
|
|
57
|
+
const uris = [];
|
|
58
|
+
const userMatch = pathname.match(/^\/([^/]+)\/?$/);
|
|
59
|
+
if (userMatch?.[1] && !isAnyOf(userMatch[1], excludedPaths)) {
|
|
60
|
+
const user = userMatch[1];
|
|
61
|
+
uris.push(`https://github.com/${user}.atom`);
|
|
62
|
+
return uris;
|
|
63
|
+
}
|
|
64
|
+
const repoMatch = pathname.match(/^\/([^/]+)\/([^/]+)/);
|
|
65
|
+
const owner = repoMatch?.[1];
|
|
66
|
+
const repo = repoMatch?.[2];
|
|
67
|
+
if (!owner || !repo || isAnyOf(owner, excludedPaths)) return [];
|
|
68
|
+
uris.push(`https://github.com/${owner}/${repo}/releases.atom`);
|
|
69
|
+
uris.push(`https://github.com/${owner}/${repo}/commits.atom`);
|
|
70
|
+
uris.push(`https://github.com/${owner}/${repo}/tags.atom`);
|
|
71
|
+
if (/\/wiki(\/|$)/.test(pathname)) uris.push(`https://github.com/${owner}/${repo}/wiki.atom`);
|
|
72
|
+
if (/\/discussions(\/|$)/.test(pathname)) uris.push(`https://github.com/${owner}/${repo}/discussions.atom`);
|
|
73
|
+
const branchMatch = pathname.match(/^\/[^/]+\/[^/]+\/tree\/([^/]+)\/?$/);
|
|
74
|
+
if (branchMatch?.[1]) {
|
|
75
|
+
const branch = branchMatch[1];
|
|
76
|
+
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}.atom`);
|
|
77
|
+
}
|
|
78
|
+
const fileMatch = pathname.match(/^\/[^/]+\/[^/]+\/(?:blob|commits)\/([^/]+)\/(.+)/);
|
|
79
|
+
if (fileMatch?.[1] && fileMatch?.[2]) {
|
|
80
|
+
const branch = fileMatch[1];
|
|
81
|
+
const filePath = fileMatch[2];
|
|
82
|
+
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}/${filePath}.atom`);
|
|
83
|
+
}
|
|
84
|
+
return uris;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
//#endregion
|
|
89
|
+
export { githubHandler };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/githubGist.ts
|
|
4
|
+
const hosts = ["gist.github.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"discover",
|
|
7
|
+
"search",
|
|
8
|
+
"login",
|
|
9
|
+
"join",
|
|
10
|
+
"settings"
|
|
11
|
+
];
|
|
12
|
+
const githubGistHandler = {
|
|
13
|
+
match: (url) => {
|
|
14
|
+
return require_utils.isHostOf(url, hosts);
|
|
15
|
+
},
|
|
16
|
+
resolve: (url) => {
|
|
17
|
+
const { pathname } = new URL(url);
|
|
18
|
+
const uris = [];
|
|
19
|
+
const gistMatch = pathname.match(/^\/([^/]+)\/([a-f0-9]+)/);
|
|
20
|
+
if (gistMatch?.[1] && gistMatch?.[2]) {
|
|
21
|
+
const username = gistMatch[1];
|
|
22
|
+
if (!require_utils.isAnyOf(username, excludedPaths)) uris.push(`https://gist.github.com/${username}.atom`);
|
|
23
|
+
return uris;
|
|
24
|
+
}
|
|
25
|
+
const starredMatch = pathname.match(/^\/([^/]+)\/starred\/?$/);
|
|
26
|
+
if (starredMatch?.[1] && !require_utils.isAnyOf(starredMatch[1], excludedPaths)) {
|
|
27
|
+
const username = starredMatch[1];
|
|
28
|
+
uris.push(`https://gist.github.com/${username}/starred.atom`);
|
|
29
|
+
return uris;
|
|
30
|
+
}
|
|
31
|
+
const userMatch = pathname.match(/^\/([^/]+)\/?$/);
|
|
32
|
+
if (userMatch?.[1] && !require_utils.isAnyOf(userMatch[1], excludedPaths)) {
|
|
33
|
+
const username = userMatch[1];
|
|
34
|
+
uris.push(`https://gist.github.com/${username}.atom`);
|
|
35
|
+
return uris;
|
|
36
|
+
}
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
exports.githubGistHandler = githubGistHandler;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/githubGist.ts
|
|
4
|
+
const hosts = ["gist.github.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"discover",
|
|
7
|
+
"search",
|
|
8
|
+
"login",
|
|
9
|
+
"join",
|
|
10
|
+
"settings"
|
|
11
|
+
];
|
|
12
|
+
const githubGistHandler = {
|
|
13
|
+
match: (url) => {
|
|
14
|
+
return isHostOf(url, hosts);
|
|
15
|
+
},
|
|
16
|
+
resolve: (url) => {
|
|
17
|
+
const { pathname } = new URL(url);
|
|
18
|
+
const uris = [];
|
|
19
|
+
const gistMatch = pathname.match(/^\/([^/]+)\/([a-f0-9]+)/);
|
|
20
|
+
if (gistMatch?.[1] && gistMatch?.[2]) {
|
|
21
|
+
const username = gistMatch[1];
|
|
22
|
+
if (!isAnyOf(username, excludedPaths)) uris.push(`https://gist.github.com/${username}.atom`);
|
|
23
|
+
return uris;
|
|
24
|
+
}
|
|
25
|
+
const starredMatch = pathname.match(/^\/([^/]+)\/starred\/?$/);
|
|
26
|
+
if (starredMatch?.[1] && !isAnyOf(starredMatch[1], excludedPaths)) {
|
|
27
|
+
const username = starredMatch[1];
|
|
28
|
+
uris.push(`https://gist.github.com/${username}/starred.atom`);
|
|
29
|
+
return uris;
|
|
30
|
+
}
|
|
31
|
+
const userMatch = pathname.match(/^\/([^/]+)\/?$/);
|
|
32
|
+
if (userMatch?.[1] && !isAnyOf(userMatch[1], excludedPaths)) {
|
|
33
|
+
const username = userMatch[1];
|
|
34
|
+
uris.push(`https://gist.github.com/${username}.atom`);
|
|
35
|
+
return uris;
|
|
36
|
+
}
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
export { githubGistHandler };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/gitlab.ts
|
|
4
|
+
const hosts = ["gitlab.com", "www.gitlab.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"explore",
|
|
7
|
+
"dashboard",
|
|
8
|
+
"projects",
|
|
9
|
+
"groups",
|
|
10
|
+
"search",
|
|
11
|
+
"admin",
|
|
12
|
+
"help",
|
|
13
|
+
"assets",
|
|
14
|
+
"users",
|
|
15
|
+
"api",
|
|
16
|
+
"jwt",
|
|
17
|
+
"oauth",
|
|
18
|
+
"profile",
|
|
19
|
+
"snippets",
|
|
20
|
+
"abuse_reports",
|
|
21
|
+
"invites",
|
|
22
|
+
"import",
|
|
23
|
+
"uploads",
|
|
24
|
+
"robots.txt",
|
|
25
|
+
"sitemap",
|
|
26
|
+
"-"
|
|
27
|
+
];
|
|
28
|
+
const gitlabHandler = {
|
|
29
|
+
match: (url) => {
|
|
30
|
+
return require_utils.isHostOf(url, hosts);
|
|
31
|
+
},
|
|
32
|
+
resolve: (url) => {
|
|
33
|
+
const { origin, pathname } = new URL(url);
|
|
34
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
35
|
+
if (pathSegments.length === 1) {
|
|
36
|
+
const user = pathSegments[0];
|
|
37
|
+
if (!require_utils.isAnyOf(user, excludedPaths)) return [`${origin}/${user}.atom`];
|
|
38
|
+
}
|
|
39
|
+
if (pathSegments.length >= 2) {
|
|
40
|
+
const user = pathSegments[0];
|
|
41
|
+
const repo = pathSegments[1];
|
|
42
|
+
if (!require_utils.isAnyOf(user, excludedPaths)) return [
|
|
43
|
+
`${origin}/${user}/${repo}/-/releases.atom`,
|
|
44
|
+
`${origin}/${user}/${repo}/-/tags?format=atom`,
|
|
45
|
+
`${origin}/${user}/${repo}.atom`
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
exports.gitlabHandler = gitlabHandler;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/gitlab.ts
|
|
4
|
+
const hosts = ["gitlab.com", "www.gitlab.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"explore",
|
|
7
|
+
"dashboard",
|
|
8
|
+
"projects",
|
|
9
|
+
"groups",
|
|
10
|
+
"search",
|
|
11
|
+
"admin",
|
|
12
|
+
"help",
|
|
13
|
+
"assets",
|
|
14
|
+
"users",
|
|
15
|
+
"api",
|
|
16
|
+
"jwt",
|
|
17
|
+
"oauth",
|
|
18
|
+
"profile",
|
|
19
|
+
"snippets",
|
|
20
|
+
"abuse_reports",
|
|
21
|
+
"invites",
|
|
22
|
+
"import",
|
|
23
|
+
"uploads",
|
|
24
|
+
"robots.txt",
|
|
25
|
+
"sitemap",
|
|
26
|
+
"-"
|
|
27
|
+
];
|
|
28
|
+
const gitlabHandler = {
|
|
29
|
+
match: (url) => {
|
|
30
|
+
return isHostOf(url, hosts);
|
|
31
|
+
},
|
|
32
|
+
resolve: (url) => {
|
|
33
|
+
const { origin, pathname } = new URL(url);
|
|
34
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
35
|
+
if (pathSegments.length === 1) {
|
|
36
|
+
const user = pathSegments[0];
|
|
37
|
+
if (!isAnyOf(user, excludedPaths)) return [`${origin}/${user}.atom`];
|
|
38
|
+
}
|
|
39
|
+
if (pathSegments.length >= 2) {
|
|
40
|
+
const user = pathSegments[0];
|
|
41
|
+
const repo = pathSegments[1];
|
|
42
|
+
if (!isAnyOf(user, excludedPaths)) return [
|
|
43
|
+
`${origin}/${user}/${repo}/-/releases.atom`,
|
|
44
|
+
`${origin}/${user}/${repo}/-/tags?format=atom`,
|
|
45
|
+
`${origin}/${user}/${repo}.atom`
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { gitlabHandler };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/kickstarter.ts
|
|
4
|
+
const hosts = ["kickstarter.com", "www.kickstarter.com"];
|
|
5
|
+
const kickstarterHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
return require_utils.isHostOf(url, hosts);
|
|
8
|
+
},
|
|
9
|
+
resolve: (url) => {
|
|
10
|
+
const { pathname } = new URL(url);
|
|
11
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
12
|
+
if (pathSegments.length >= 3 && pathSegments[0] === "projects") return [`https://www.kickstarter.com/projects/${pathSegments[1]}/${pathSegments[2]}/posts.atom`];
|
|
13
|
+
return ["https://www.kickstarter.com/projects/feed.atom"];
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
exports.kickstarterHandler = kickstarterHandler;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/kickstarter.ts
|
|
4
|
+
const hosts = ["kickstarter.com", "www.kickstarter.com"];
|
|
5
|
+
const kickstarterHandler = {
|
|
6
|
+
match: (url) => {
|
|
7
|
+
return isHostOf(url, hosts);
|
|
8
|
+
},
|
|
9
|
+
resolve: (url) => {
|
|
10
|
+
const { pathname } = new URL(url);
|
|
11
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
12
|
+
if (pathSegments.length >= 3 && pathSegments[0] === "projects") return [`https://www.kickstarter.com/projects/${pathSegments[1]}/${pathSegments[2]}/posts.atom`];
|
|
13
|
+
return ["https://www.kickstarter.com/projects/feed.atom"];
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { kickstarterHandler };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/lobsters.ts
|
|
4
|
+
const hosts = ["lobste.rs"];
|
|
5
|
+
const tagPathRegex = /^\/t\/([a-zA-Z0-9,_-]+)/;
|
|
6
|
+
const domainPathRegex = /^\/domains\/([^/]+)/;
|
|
7
|
+
const userPathRegex = /^\/~([a-zA-Z0-9_-]+)/;
|
|
8
|
+
const topPathRegex = /^\/top(?:\/(1d|3d|1w|1m|1y))?\/?$/;
|
|
9
|
+
const lobstersHandler = {
|
|
10
|
+
match: (url) => {
|
|
11
|
+
return require_utils.isHostOf(url, hosts);
|
|
12
|
+
},
|
|
13
|
+
resolve: (url) => {
|
|
14
|
+
const { pathname } = new URL(url);
|
|
15
|
+
const tagMatch = pathname.match(tagPathRegex);
|
|
16
|
+
if (tagMatch?.[1]) return [`https://lobste.rs/t/${tagMatch[1]}.rss`];
|
|
17
|
+
const domainMatch = pathname.match(domainPathRegex);
|
|
18
|
+
if (domainMatch?.[1]) return [`https://lobste.rs/domains/${domainMatch[1]}.rss`];
|
|
19
|
+
const userMatch = pathname.match(userPathRegex);
|
|
20
|
+
if (userMatch?.[1]) return [`https://lobste.rs/~${userMatch[1]}/stories.rss`];
|
|
21
|
+
const topMatch = pathname.match(topPathRegex);
|
|
22
|
+
if (topMatch) {
|
|
23
|
+
const period = topMatch[1];
|
|
24
|
+
if (period) return [`https://lobste.rs/top/${period}/rss`];
|
|
25
|
+
return ["https://lobste.rs/top/rss"];
|
|
26
|
+
}
|
|
27
|
+
if (pathname === "/newest" || pathname === "/newest/") return ["https://lobste.rs/newest.rss"];
|
|
28
|
+
if (pathname === "/comments" || pathname === "/comments/") return ["https://lobste.rs/comments.rss"];
|
|
29
|
+
return ["https://lobste.rs/rss"];
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
exports.lobstersHandler = lobstersHandler;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/lobsters.ts
|
|
4
|
+
const hosts = ["lobste.rs"];
|
|
5
|
+
const tagPathRegex = /^\/t\/([a-zA-Z0-9,_-]+)/;
|
|
6
|
+
const domainPathRegex = /^\/domains\/([^/]+)/;
|
|
7
|
+
const userPathRegex = /^\/~([a-zA-Z0-9_-]+)/;
|
|
8
|
+
const topPathRegex = /^\/top(?:\/(1d|3d|1w|1m|1y))?\/?$/;
|
|
9
|
+
const lobstersHandler = {
|
|
10
|
+
match: (url) => {
|
|
11
|
+
return isHostOf(url, hosts);
|
|
12
|
+
},
|
|
13
|
+
resolve: (url) => {
|
|
14
|
+
const { pathname } = new URL(url);
|
|
15
|
+
const tagMatch = pathname.match(tagPathRegex);
|
|
16
|
+
if (tagMatch?.[1]) return [`https://lobste.rs/t/${tagMatch[1]}.rss`];
|
|
17
|
+
const domainMatch = pathname.match(domainPathRegex);
|
|
18
|
+
if (domainMatch?.[1]) return [`https://lobste.rs/domains/${domainMatch[1]}.rss`];
|
|
19
|
+
const userMatch = pathname.match(userPathRegex);
|
|
20
|
+
if (userMatch?.[1]) return [`https://lobste.rs/~${userMatch[1]}/stories.rss`];
|
|
21
|
+
const topMatch = pathname.match(topPathRegex);
|
|
22
|
+
if (topMatch) {
|
|
23
|
+
const period = topMatch[1];
|
|
24
|
+
if (period) return [`https://lobste.rs/top/${period}/rss`];
|
|
25
|
+
return ["https://lobste.rs/top/rss"];
|
|
26
|
+
}
|
|
27
|
+
if (pathname === "/newest" || pathname === "/newest/") return ["https://lobste.rs/newest.rss"];
|
|
28
|
+
if (pathname === "/comments" || pathname === "/comments/") return ["https://lobste.rs/comments.rss"];
|
|
29
|
+
return ["https://lobste.rs/rss"];
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { lobstersHandler };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/medium.ts
|
|
4
|
+
const hosts = ["medium.com", "www.medium.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"search",
|
|
7
|
+
"me",
|
|
8
|
+
"new-story",
|
|
9
|
+
"plans",
|
|
10
|
+
"membership"
|
|
11
|
+
];
|
|
12
|
+
const mediumHandler = {
|
|
13
|
+
match: (url) => {
|
|
14
|
+
return require_utils.isHostOf(url, hosts) || require_utils.isSubdomainOf(url, "medium.com");
|
|
15
|
+
},
|
|
16
|
+
resolve: (url) => {
|
|
17
|
+
const { hostname, pathname } = new URL(url);
|
|
18
|
+
const lowerHostname = hostname.toLowerCase();
|
|
19
|
+
if (hosts.includes(lowerHostname)) {
|
|
20
|
+
const userMatch = pathname.match(/^\/@([^/]+)/);
|
|
21
|
+
if (userMatch?.[1]) return [`https://medium.com/feed/@${userMatch[1]}`];
|
|
22
|
+
const tagMatch = pathname.match(/^\/tag\/([^/]+)/);
|
|
23
|
+
if (tagMatch?.[1]) return [`https://medium.com/feed/tag/${tagMatch[1]}`];
|
|
24
|
+
const pubTagMatch = pathname.match(/^\/([^/@][^/]+)\/tagged\/([^/]+)/);
|
|
25
|
+
if (pubTagMatch?.[1] && pubTagMatch?.[2]) {
|
|
26
|
+
const publication = pubTagMatch[1];
|
|
27
|
+
const tag = pubTagMatch[2];
|
|
28
|
+
if (!require_utils.isAnyOf(publication, excludedPaths)) return [`https://medium.com/feed/${publication}/tagged/${tag}`];
|
|
29
|
+
}
|
|
30
|
+
const pubMatch = pathname.match(/^\/([^/@][^/]+)/);
|
|
31
|
+
if (pubMatch?.[1]) {
|
|
32
|
+
const publication = pubMatch[1];
|
|
33
|
+
if (!require_utils.isAnyOf(publication, excludedPaths)) return [`https://medium.com/feed/${publication}`];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (lowerHostname.endsWith(".medium.com") && lowerHostname !== "medium.com" && lowerHostname !== "www.medium.com") {
|
|
37
|
+
const subdomain = lowerHostname.replace(".medium.com", "");
|
|
38
|
+
const tagMatch = pathname.match(/^\/tagged\/([^/]+)/);
|
|
39
|
+
if (tagMatch?.[1]) return [`https://medium.com/feed/${subdomain}/tagged/${tagMatch[1]}`];
|
|
40
|
+
return [`https://medium.com/feed/${subdomain}`];
|
|
41
|
+
}
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
exports.mediumHandler = mediumHandler;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf, isSubdomainOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/medium.ts
|
|
4
|
+
const hosts = ["medium.com", "www.medium.com"];
|
|
5
|
+
const excludedPaths = [
|
|
6
|
+
"search",
|
|
7
|
+
"me",
|
|
8
|
+
"new-story",
|
|
9
|
+
"plans",
|
|
10
|
+
"membership"
|
|
11
|
+
];
|
|
12
|
+
const mediumHandler = {
|
|
13
|
+
match: (url) => {
|
|
14
|
+
return isHostOf(url, hosts) || isSubdomainOf(url, "medium.com");
|
|
15
|
+
},
|
|
16
|
+
resolve: (url) => {
|
|
17
|
+
const { hostname, pathname } = new URL(url);
|
|
18
|
+
const lowerHostname = hostname.toLowerCase();
|
|
19
|
+
if (hosts.includes(lowerHostname)) {
|
|
20
|
+
const userMatch = pathname.match(/^\/@([^/]+)/);
|
|
21
|
+
if (userMatch?.[1]) return [`https://medium.com/feed/@${userMatch[1]}`];
|
|
22
|
+
const tagMatch = pathname.match(/^\/tag\/([^/]+)/);
|
|
23
|
+
if (tagMatch?.[1]) return [`https://medium.com/feed/tag/${tagMatch[1]}`];
|
|
24
|
+
const pubTagMatch = pathname.match(/^\/([^/@][^/]+)\/tagged\/([^/]+)/);
|
|
25
|
+
if (pubTagMatch?.[1] && pubTagMatch?.[2]) {
|
|
26
|
+
const publication = pubTagMatch[1];
|
|
27
|
+
const tag = pubTagMatch[2];
|
|
28
|
+
if (!isAnyOf(publication, excludedPaths)) return [`https://medium.com/feed/${publication}/tagged/${tag}`];
|
|
29
|
+
}
|
|
30
|
+
const pubMatch = pathname.match(/^\/([^/@][^/]+)/);
|
|
31
|
+
if (pubMatch?.[1]) {
|
|
32
|
+
const publication = pubMatch[1];
|
|
33
|
+
if (!isAnyOf(publication, excludedPaths)) return [`https://medium.com/feed/${publication}`];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (lowerHostname.endsWith(".medium.com") && lowerHostname !== "medium.com" && lowerHostname !== "www.medium.com") {
|
|
37
|
+
const subdomain = lowerHostname.replace(".medium.com", "");
|
|
38
|
+
const tagMatch = pathname.match(/^\/tagged\/([^/]+)/);
|
|
39
|
+
if (tagMatch?.[1]) return [`https://medium.com/feed/${subdomain}/tagged/${tagMatch[1]}`];
|
|
40
|
+
return [`https://medium.com/feed/${subdomain}`];
|
|
41
|
+
}
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
export { mediumHandler };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/pinterest.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"pinterest.com",
|
|
6
|
+
"www.pinterest.com",
|
|
7
|
+
"pin.it"
|
|
8
|
+
];
|
|
9
|
+
const excludedPaths = [
|
|
10
|
+
"_",
|
|
11
|
+
"about",
|
|
12
|
+
"business",
|
|
13
|
+
"convert",
|
|
14
|
+
"explore",
|
|
15
|
+
"ideas",
|
|
16
|
+
"login",
|
|
17
|
+
"news_hub",
|
|
18
|
+
"password",
|
|
19
|
+
"pin",
|
|
20
|
+
"privacy",
|
|
21
|
+
"resource",
|
|
22
|
+
"search",
|
|
23
|
+
"settings",
|
|
24
|
+
"terms",
|
|
25
|
+
"today",
|
|
26
|
+
"topics"
|
|
27
|
+
];
|
|
28
|
+
const pinterestHandler = {
|
|
29
|
+
match: (url) => {
|
|
30
|
+
return require_utils.isHostOf(url, hosts);
|
|
31
|
+
},
|
|
32
|
+
resolve: (url) => {
|
|
33
|
+
const { pathname } = new URL(url);
|
|
34
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
35
|
+
if (pathSegments.length === 0) return [];
|
|
36
|
+
const username = pathSegments[0];
|
|
37
|
+
if (require_utils.isAnyOf(username, excludedPaths)) return [];
|
|
38
|
+
if (pathSegments.length >= 2) {
|
|
39
|
+
const boardname = pathSegments[1];
|
|
40
|
+
if (boardname.startsWith("_") || boardname === "pins" || boardname === "boards") return [`https://www.pinterest.com/${username}/feed.rss`];
|
|
41
|
+
return [`https://www.pinterest.com/${username}/${boardname}.rss`];
|
|
42
|
+
}
|
|
43
|
+
return [`https://www.pinterest.com/${username}/feed.rss`];
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
exports.pinterestHandler = pinterestHandler;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/pinterest.ts
|
|
4
|
+
const hosts = [
|
|
5
|
+
"pinterest.com",
|
|
6
|
+
"www.pinterest.com",
|
|
7
|
+
"pin.it"
|
|
8
|
+
];
|
|
9
|
+
const excludedPaths = [
|
|
10
|
+
"_",
|
|
11
|
+
"about",
|
|
12
|
+
"business",
|
|
13
|
+
"convert",
|
|
14
|
+
"explore",
|
|
15
|
+
"ideas",
|
|
16
|
+
"login",
|
|
17
|
+
"news_hub",
|
|
18
|
+
"password",
|
|
19
|
+
"pin",
|
|
20
|
+
"privacy",
|
|
21
|
+
"resource",
|
|
22
|
+
"search",
|
|
23
|
+
"settings",
|
|
24
|
+
"terms",
|
|
25
|
+
"today",
|
|
26
|
+
"topics"
|
|
27
|
+
];
|
|
28
|
+
const pinterestHandler = {
|
|
29
|
+
match: (url) => {
|
|
30
|
+
return isHostOf(url, hosts);
|
|
31
|
+
},
|
|
32
|
+
resolve: (url) => {
|
|
33
|
+
const { pathname } = new URL(url);
|
|
34
|
+
const pathSegments = pathname.split("/").filter(Boolean);
|
|
35
|
+
if (pathSegments.length === 0) return [];
|
|
36
|
+
const username = pathSegments[0];
|
|
37
|
+
if (isAnyOf(username, excludedPaths)) return [];
|
|
38
|
+
if (pathSegments.length >= 2) {
|
|
39
|
+
const boardname = pathSegments[1];
|
|
40
|
+
if (boardname.startsWith("_") || boardname === "pins" || boardname === "boards") return [`https://www.pinterest.com/${username}/feed.rss`];
|
|
41
|
+
return [`https://www.pinterest.com/${username}/${boardname}.rss`];
|
|
42
|
+
}
|
|
43
|
+
return [`https://www.pinterest.com/${username}/feed.rss`];
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
export { pinterestHandler };
|