feedscout 1.1.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 +8 -6
- package/dist/blogrolls/index.cjs +8 -3
- package/dist/blogrolls/index.d.cts +1 -1
- package/dist/blogrolls/index.d.ts +1 -1
- package/dist/blogrolls/index.js +8 -3
- package/dist/common/discover/utils.cjs +14 -0
- package/dist/common/discover/utils.js +14 -1
- package/dist/common/types.d.cts +4 -4
- package/dist/common/types.d.ts +4 -4
- package/dist/common/uris/headers/index.cjs +6 -3
- package/dist/common/uris/headers/index.js +6 -3
- package/dist/common/utils.cjs +1 -0
- package/dist/common/utils.d.cts +9 -0
- package/dist/common/utils.d.ts +9 -0
- package/dist/common/utils.js +1 -1
- package/dist/feeds/defaults.cjs +18 -0
- package/dist/feeds/defaults.js +18 -0
- package/dist/feeds/index.cjs +9 -3
- package/dist/feeds/index.d.cts +1 -1
- package/dist/feeds/index.d.ts +1 -1
- package/dist/feeds/index.js +9 -3
- 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 +13 -4
- package/dist/feeds/platform/handlers/blogspot.js +13 -5
- 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 +9 -3
- package/dist/feeds/platform/handlers/github.js +9 -3
- 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 +36 -2
- package/dist/feeds/platform/handlers/gitlab.js +37 -3
- package/dist/feeds/platform/handlers/kickstarter.cjs +4 -7
- package/dist/feeds/platform/handlers/kickstarter.js +4 -7
- 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 +3 -0
- package/dist/feeds/platform/handlers/reddit.js +3 -0
- package/dist/feeds/platform/handlers/soundcloud.cjs +1 -1
- package/dist/feeds/platform/handlers/soundcloud.js +2 -2
- package/dist/feeds/platform/handlers/tumblr.cjs +4 -1
- package/dist/feeds/platform/handlers/tumblr.js +4 -1
- package/dist/feeds/platform/handlers/wordpress.cjs +17 -6
- package/dist/feeds/platform/handlers/wordpress.js +17 -6
- package/dist/feeds/platform/handlers/youtube.cjs +16 -4
- package/dist/feeds/platform/handlers/youtube.js +16 -4
- 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 +18 -19
- 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,66 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/dailymotion.ts
|
|
4
|
+
const hosts = ["dailymotion.com", "www.dailymotion.com"];
|
|
5
|
+
const userPathRegex = /^\/([a-zA-Z0-9_-]+)$/;
|
|
6
|
+
const playlistPathRegex = /^\/playlist\/([a-zA-Z0-9_-]+)/;
|
|
7
|
+
const excludedPaths = [
|
|
8
|
+
"signin",
|
|
9
|
+
"signout",
|
|
10
|
+
"signup",
|
|
11
|
+
"login",
|
|
12
|
+
"logout",
|
|
13
|
+
"register",
|
|
14
|
+
"search",
|
|
15
|
+
"legal",
|
|
16
|
+
"about",
|
|
17
|
+
"careers",
|
|
18
|
+
"terms",
|
|
19
|
+
"privacy",
|
|
20
|
+
"feedback",
|
|
21
|
+
"help",
|
|
22
|
+
"settings",
|
|
23
|
+
"upload",
|
|
24
|
+
"partner",
|
|
25
|
+
"monetize",
|
|
26
|
+
"studio",
|
|
27
|
+
"video",
|
|
28
|
+
"live",
|
|
29
|
+
"channels",
|
|
30
|
+
"playlist",
|
|
31
|
+
"topics",
|
|
32
|
+
"trending",
|
|
33
|
+
"dm",
|
|
34
|
+
"creator",
|
|
35
|
+
"premium",
|
|
36
|
+
"explore",
|
|
37
|
+
"following",
|
|
38
|
+
"subscriptions",
|
|
39
|
+
"notifications",
|
|
40
|
+
"history",
|
|
41
|
+
"watch",
|
|
42
|
+
"contact",
|
|
43
|
+
"ads",
|
|
44
|
+
"dmca",
|
|
45
|
+
"copyright",
|
|
46
|
+
"community"
|
|
47
|
+
];
|
|
48
|
+
const dailymotionHandler = {
|
|
49
|
+
match: (url) => {
|
|
50
|
+
return isHostOf(url, hosts);
|
|
51
|
+
},
|
|
52
|
+
resolve: (url) => {
|
|
53
|
+
const { pathname } = new URL(url);
|
|
54
|
+
const playlistMatch = pathname.match(playlistPathRegex);
|
|
55
|
+
if (playlistMatch?.[1]) return [`https://www.dailymotion.com/rss/playlist/${playlistMatch[1]}`];
|
|
56
|
+
const userMatch = pathname.match(userPathRegex);
|
|
57
|
+
if (userMatch?.[1]) {
|
|
58
|
+
const username = userMatch[1];
|
|
59
|
+
if (!isAnyOf(username, excludedPaths)) return [`https://www.dailymotion.com/rss/${username}`];
|
|
60
|
+
}
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
export { dailymotionHandler };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/deviantart.ts
|
|
4
|
+
const hosts = ["deviantart.com", "www.deviantart.com"];
|
|
5
|
+
const feedBaseUrl = "https://backend.deviantart.com/rss.xml";
|
|
6
|
+
const excludedPaths = [
|
|
7
|
+
"about",
|
|
8
|
+
"join",
|
|
9
|
+
"search",
|
|
10
|
+
"topic",
|
|
11
|
+
"watch",
|
|
12
|
+
"notifications",
|
|
13
|
+
"settings",
|
|
14
|
+
"submit",
|
|
15
|
+
"shop",
|
|
16
|
+
"core-membership",
|
|
17
|
+
"team",
|
|
18
|
+
"developers"
|
|
19
|
+
];
|
|
20
|
+
const deviantartHandler = {
|
|
21
|
+
match: (url) => {
|
|
22
|
+
return require_utils.isHostOf(url, hosts);
|
|
23
|
+
},
|
|
24
|
+
resolve: (url) => {
|
|
25
|
+
const { pathname } = new URL(url);
|
|
26
|
+
const tagMatch = pathname.match(/^\/tag\/([^/]+)/);
|
|
27
|
+
if (tagMatch?.[1]) {
|
|
28
|
+
const tag = tagMatch[1];
|
|
29
|
+
return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`tag:${tag}`)}`];
|
|
30
|
+
}
|
|
31
|
+
const favMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/favourites\/?$/);
|
|
32
|
+
if (favMatch?.[1]) {
|
|
33
|
+
const username = favMatch[1];
|
|
34
|
+
if (!require_utils.isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`favby:${username}`)}`];
|
|
35
|
+
}
|
|
36
|
+
const folderMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/gallery\/(\d+)(?:\/|$)/);
|
|
37
|
+
if (folderMatch?.[1] && folderMatch?.[2]) {
|
|
38
|
+
const username = folderMatch[1];
|
|
39
|
+
const folderId = folderMatch[2];
|
|
40
|
+
if (!require_utils.isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`gallery:${username}/${folderId}`)}`];
|
|
41
|
+
}
|
|
42
|
+
const username = pathname.match(/^\/([a-zA-Z0-9_-]+)(?:\/gallery(?:\/all)?)?(?:\/|$)/)?.[1];
|
|
43
|
+
if (!username || require_utils.isAnyOf(username, excludedPaths)) return [];
|
|
44
|
+
const query = `by:${username} sort:time meta:all`;
|
|
45
|
+
return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(query)}`];
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
exports.deviantartHandler = deviantartHandler;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/deviantart.ts
|
|
4
|
+
const hosts = ["deviantart.com", "www.deviantart.com"];
|
|
5
|
+
const feedBaseUrl = "https://backend.deviantart.com/rss.xml";
|
|
6
|
+
const excludedPaths = [
|
|
7
|
+
"about",
|
|
8
|
+
"join",
|
|
9
|
+
"search",
|
|
10
|
+
"topic",
|
|
11
|
+
"watch",
|
|
12
|
+
"notifications",
|
|
13
|
+
"settings",
|
|
14
|
+
"submit",
|
|
15
|
+
"shop",
|
|
16
|
+
"core-membership",
|
|
17
|
+
"team",
|
|
18
|
+
"developers"
|
|
19
|
+
];
|
|
20
|
+
const deviantartHandler = {
|
|
21
|
+
match: (url) => {
|
|
22
|
+
return isHostOf(url, hosts);
|
|
23
|
+
},
|
|
24
|
+
resolve: (url) => {
|
|
25
|
+
const { pathname } = new URL(url);
|
|
26
|
+
const tagMatch = pathname.match(/^\/tag\/([^/]+)/);
|
|
27
|
+
if (tagMatch?.[1]) {
|
|
28
|
+
const tag = tagMatch[1];
|
|
29
|
+
return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`tag:${tag}`)}`];
|
|
30
|
+
}
|
|
31
|
+
const favMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/favourites\/?$/);
|
|
32
|
+
if (favMatch?.[1]) {
|
|
33
|
+
const username = favMatch[1];
|
|
34
|
+
if (!isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`favby:${username}`)}`];
|
|
35
|
+
}
|
|
36
|
+
const folderMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)\/gallery\/(\d+)(?:\/|$)/);
|
|
37
|
+
if (folderMatch?.[1] && folderMatch?.[2]) {
|
|
38
|
+
const username = folderMatch[1];
|
|
39
|
+
const folderId = folderMatch[2];
|
|
40
|
+
if (!isAnyOf(username, excludedPaths)) return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(`gallery:${username}/${folderId}`)}`];
|
|
41
|
+
}
|
|
42
|
+
const username = pathname.match(/^\/([a-zA-Z0-9_-]+)(?:\/gallery(?:\/all)?)?(?:\/|$)/)?.[1];
|
|
43
|
+
if (!username || isAnyOf(username, excludedPaths)) return [];
|
|
44
|
+
const query = `by:${username} sort:time meta:all`;
|
|
45
|
+
return [`${feedBaseUrl}?type=deviation&q=${encodeURIComponent(query)}`];
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { deviantartHandler };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const require_utils = require('../../../common/utils.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/devto.ts
|
|
4
|
+
const hosts = ["dev.to", "www.dev.to"];
|
|
5
|
+
const userPathRegex = /^\/([a-zA-Z0-9_]+)\/?$/;
|
|
6
|
+
const tagPathRegex = /^\/t\/([^/]+)/;
|
|
7
|
+
const excludedPaths = [
|
|
8
|
+
"tag",
|
|
9
|
+
"tags",
|
|
10
|
+
"search",
|
|
11
|
+
"top",
|
|
12
|
+
"latest",
|
|
13
|
+
"about",
|
|
14
|
+
"contact",
|
|
15
|
+
"privacy",
|
|
16
|
+
"terms",
|
|
17
|
+
"code-of-conduct",
|
|
18
|
+
"faq",
|
|
19
|
+
"enter",
|
|
20
|
+
"settings",
|
|
21
|
+
"signout-confirm",
|
|
22
|
+
"notifications",
|
|
23
|
+
"reading-list",
|
|
24
|
+
"dashboard"
|
|
25
|
+
];
|
|
26
|
+
const devtoHandler = {
|
|
27
|
+
match: (url) => {
|
|
28
|
+
return require_utils.isHostOf(url, hosts);
|
|
29
|
+
},
|
|
30
|
+
resolve: (url) => {
|
|
31
|
+
const { pathname } = new URL(url);
|
|
32
|
+
const userMatch = pathname.match(userPathRegex);
|
|
33
|
+
if (userMatch?.[1]) {
|
|
34
|
+
const username = userMatch[1];
|
|
35
|
+
if (!require_utils.isAnyOf(username, excludedPaths)) return [`https://dev.to/feed/${username}`];
|
|
36
|
+
}
|
|
37
|
+
const tagMatch = pathname.match(tagPathRegex);
|
|
38
|
+
if (tagMatch?.[1]) return [`https://dev.to/feed/tag/${tagMatch[1]}`];
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
exports.devtoHandler = devtoHandler;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
|
+
|
|
3
|
+
//#region src/feeds/platform/handlers/devto.ts
|
|
4
|
+
const hosts = ["dev.to", "www.dev.to"];
|
|
5
|
+
const userPathRegex = /^\/([a-zA-Z0-9_]+)\/?$/;
|
|
6
|
+
const tagPathRegex = /^\/t\/([^/]+)/;
|
|
7
|
+
const excludedPaths = [
|
|
8
|
+
"tag",
|
|
9
|
+
"tags",
|
|
10
|
+
"search",
|
|
11
|
+
"top",
|
|
12
|
+
"latest",
|
|
13
|
+
"about",
|
|
14
|
+
"contact",
|
|
15
|
+
"privacy",
|
|
16
|
+
"terms",
|
|
17
|
+
"code-of-conduct",
|
|
18
|
+
"faq",
|
|
19
|
+
"enter",
|
|
20
|
+
"settings",
|
|
21
|
+
"signout-confirm",
|
|
22
|
+
"notifications",
|
|
23
|
+
"reading-list",
|
|
24
|
+
"dashboard"
|
|
25
|
+
];
|
|
26
|
+
const devtoHandler = {
|
|
27
|
+
match: (url) => {
|
|
28
|
+
return isHostOf(url, hosts);
|
|
29
|
+
},
|
|
30
|
+
resolve: (url) => {
|
|
31
|
+
const { pathname } = new URL(url);
|
|
32
|
+
const userMatch = pathname.match(userPathRegex);
|
|
33
|
+
if (userMatch?.[1]) {
|
|
34
|
+
const username = userMatch[1];
|
|
35
|
+
if (!isAnyOf(username, excludedPaths)) return [`https://dev.to/feed/${username}`];
|
|
36
|
+
}
|
|
37
|
+
const tagMatch = pathname.match(tagPathRegex);
|
|
38
|
+
if (tagMatch?.[1]) return [`https://dev.to/feed/tag/${tagMatch[1]}`];
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { devtoHandler };
|
|
@@ -68,13 +68,19 @@ const githubHandler = {
|
|
|
68
68
|
uris.push(`https://github.com/${owner}/${repo}/releases.atom`);
|
|
69
69
|
uris.push(`https://github.com/${owner}/${repo}/commits.atom`);
|
|
70
70
|
uris.push(`https://github.com/${owner}/${repo}/tags.atom`);
|
|
71
|
-
if (
|
|
72
|
-
if (
|
|
73
|
-
const branchMatch = pathname.match(/^\/[^/]+\/[^/]+\/tree\/([^/]+)
|
|
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
74
|
if (branchMatch?.[1]) {
|
|
75
75
|
const branch = branchMatch[1];
|
|
76
76
|
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}.atom`);
|
|
77
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
|
+
}
|
|
78
84
|
return uris;
|
|
79
85
|
}
|
|
80
86
|
};
|
|
@@ -68,13 +68,19 @@ const githubHandler = {
|
|
|
68
68
|
uris.push(`https://github.com/${owner}/${repo}/releases.atom`);
|
|
69
69
|
uris.push(`https://github.com/${owner}/${repo}/commits.atom`);
|
|
70
70
|
uris.push(`https://github.com/${owner}/${repo}/tags.atom`);
|
|
71
|
-
if (
|
|
72
|
-
if (
|
|
73
|
-
const branchMatch = pathname.match(/^\/[^/]+\/[^/]+\/tree\/([^/]+)
|
|
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
74
|
if (branchMatch?.[1]) {
|
|
75
75
|
const branch = branchMatch[1];
|
|
76
76
|
uris.push(`https://github.com/${owner}/${repo}/commits/${branch}.atom`);
|
|
77
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
|
+
}
|
|
78
84
|
return uris;
|
|
79
85
|
}
|
|
80
86
|
};
|
|
@@ -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 };
|
|
@@ -2,6 +2,29 @@ const require_utils = require('../../../common/utils.cjs');
|
|
|
2
2
|
|
|
3
3
|
//#region src/feeds/platform/handlers/gitlab.ts
|
|
4
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
|
+
];
|
|
5
28
|
const gitlabHandler = {
|
|
6
29
|
match: (url) => {
|
|
7
30
|
return require_utils.isHostOf(url, hosts);
|
|
@@ -9,8 +32,19 @@ const gitlabHandler = {
|
|
|
9
32
|
resolve: (url) => {
|
|
10
33
|
const { origin, pathname } = new URL(url);
|
|
11
34
|
const pathSegments = pathname.split("/").filter(Boolean);
|
|
12
|
-
if (pathSegments.length === 1)
|
|
13
|
-
|
|
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
|
+
}
|
|
14
48
|
return [];
|
|
15
49
|
}
|
|
16
50
|
};
|
|
@@ -1,7 +1,30 @@
|
|
|
1
|
-
import { isHostOf } from "../../../common/utils.js";
|
|
1
|
+
import { isAnyOf, isHostOf } from "../../../common/utils.js";
|
|
2
2
|
|
|
3
3
|
//#region src/feeds/platform/handlers/gitlab.ts
|
|
4
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
|
+
];
|
|
5
28
|
const gitlabHandler = {
|
|
6
29
|
match: (url) => {
|
|
7
30
|
return isHostOf(url, hosts);
|
|
@@ -9,8 +32,19 @@ const gitlabHandler = {
|
|
|
9
32
|
resolve: (url) => {
|
|
10
33
|
const { origin, pathname } = new URL(url);
|
|
11
34
|
const pathSegments = pathname.split("/").filter(Boolean);
|
|
12
|
-
if (pathSegments.length === 1)
|
|
13
|
-
|
|
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
|
+
}
|
|
14
48
|
return [];
|
|
15
49
|
}
|
|
16
50
|
};
|
|
@@ -4,16 +4,13 @@ const require_utils = require('../../../common/utils.cjs');
|
|
|
4
4
|
const hosts = ["kickstarter.com", "www.kickstarter.com"];
|
|
5
5
|
const kickstarterHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
|
-
|
|
8
|
-
const { pathname } = new URL(url);
|
|
9
|
-
const pathSegments = pathname.split("/").filter(Boolean);
|
|
10
|
-
return pathSegments.length >= 3 && pathSegments[0] === "projects";
|
|
7
|
+
return require_utils.isHostOf(url, hosts);
|
|
11
8
|
},
|
|
12
9
|
resolve: (url) => {
|
|
13
|
-
const {
|
|
10
|
+
const { pathname } = new URL(url);
|
|
14
11
|
const pathSegments = pathname.split("/").filter(Boolean);
|
|
15
|
-
if (pathSegments.length >= 3 && pathSegments[0] === "projects") return [
|
|
16
|
-
return [];
|
|
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"];
|
|
17
14
|
}
|
|
18
15
|
};
|
|
19
16
|
|
|
@@ -4,16 +4,13 @@ import { isHostOf } from "../../../common/utils.js";
|
|
|
4
4
|
const hosts = ["kickstarter.com", "www.kickstarter.com"];
|
|
5
5
|
const kickstarterHandler = {
|
|
6
6
|
match: (url) => {
|
|
7
|
-
|
|
8
|
-
const { pathname } = new URL(url);
|
|
9
|
-
const pathSegments = pathname.split("/").filter(Boolean);
|
|
10
|
-
return pathSegments.length >= 3 && pathSegments[0] === "projects";
|
|
7
|
+
return isHostOf(url, hosts);
|
|
11
8
|
},
|
|
12
9
|
resolve: (url) => {
|
|
13
|
-
const {
|
|
10
|
+
const { pathname } = new URL(url);
|
|
14
11
|
const pathSegments = pathname.split("/").filter(Boolean);
|
|
15
|
-
if (pathSegments.length >= 3 && pathSegments[0] === "projects") return [
|
|
16
|
-
return [];
|
|
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"];
|
|
17
14
|
}
|
|
18
15
|
};
|
|
19
16
|
|
|
@@ -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;
|