diff --git a/lib/routes/buaa/lib/space/newbook.ts b/lib/routes/buaa/lib/space/newbook.ts
index 3ef8cde73..810b8ef3c 100644
--- a/lib/routes/buaa/lib/space/newbook.ts
+++ b/lib/routes/buaa/lib/space/newbook.ts
@@ -5,7 +5,7 @@ import { parseDate } from '@/utils/parse-date';
import timezone from '@/utils/timezone';
import cache from '@/utils/cache';
import { art } from '@/utils/render';
-import path from 'path';
+import path from 'node:path';
import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);
diff --git a/lib/routes/daily/discussed.ts b/lib/routes/daily/discussed.ts
index 54a595727..23f80e4b5 100644
--- a/lib/routes/daily/discussed.ts
+++ b/lib/routes/daily/discussed.ts
@@ -1,9 +1,5 @@
import { Route } from '@/types';
-import { getData, getList, getRedirectedLink } from './utils.js';
-
-const variables = {
- first: 15,
-};
+import { baseUrl, getData, getList } from './utils.js';
const query = `
query MostDiscussedFeed(
@@ -19,6 +15,7 @@ const query = `
edges {
node {
...FeedPost
+ contentHtml
}
}
}
@@ -33,6 +30,7 @@ const query = `
image
readTime
permalink
+ commentsPermalink
summary
createdAt
numUpvotes
@@ -52,37 +50,40 @@ const query = `
bio
}
`;
-const graphqlQuery = {
- query,
- variables,
-};
export const route: Route = {
path: '/discussed',
example: '/daily/discussed',
radar: [
{
- source: ['daily.dev/popular'],
+ source: ['app.daily.dev/discussed'],
},
],
name: 'Most Discussed',
maintainers: ['Rjnishant530'],
handler,
- url: 'daily.dev/popular',
+ url: 'app.daily.dev/discussed',
};
-async function handler() {
- const baseUrl = 'https://app.daily.dev/discussed';
- const data = await getData(graphqlQuery);
- const list = getList(data);
- const items = await getRedirectedLink(list);
+async function handler(ctx) {
+ const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 20;
+ const link = `${baseUrl}/discussed`;
+
+ const data = await getData({
+ query,
+ variables: {
+ first: limit,
+ },
+ });
+ const items = getList(data);
+
return {
- title: 'Most Discussed',
- link: baseUrl,
+ title: 'Real-time discussions in the developer community | daily.dev',
+ link,
item: items,
- description: 'Most Discussed Posts on Daily.dev',
- logo: 'https://app.daily.dev/favicon-32x32.png',
- icon: 'https://app.daily.dev/favicon-32x32.png',
+ description: 'Stay on top of real-time developer discussions on daily.dev. Join conversations happening now and engage with the most active community members.',
+ logo: `${baseUrl}/favicon-32x32.png`,
+ icon: `${baseUrl}/favicon-32x32.png`,
language: 'en-us',
};
}
diff --git a/lib/routes/daily/index.ts b/lib/routes/daily/index.ts
index 031f47c0a..40f0fdfbe 100644
--- a/lib/routes/daily/index.ts
+++ b/lib/routes/daily/index.ts
@@ -1,5 +1,5 @@
import { Route } from '@/types';
-import { getData, getList, getRedirectedLink } from './utils.js';
+import { baseUrl, getData, getList } from './utils.js';
const variables = {
version: 11,
@@ -28,6 +28,7 @@ const query = `
edges {
node {
...FeedPost
+ contentHtml
}
}
}
@@ -42,6 +43,7 @@ const query = `
image
readTime
permalink
+ commentsPermalink
summary
createdAt
numUpvotes
@@ -72,27 +74,28 @@ export const route: Route = {
example: '/daily',
radar: [
{
- source: ['daily.dev/popular'],
+ source: ['app.daily.dev/popular'],
},
],
name: 'Popular',
maintainers: ['Rjnishant530'],
handler,
- url: 'daily.dev/popular',
+ url: 'app.daily.dev/popular',
};
async function handler() {
- const baseUrl = 'https://app.daily.dev/popular';
+ const link = `${baseUrl}/popular`;
+
const data = await getData(graphqlQuery);
- const list = getList(data);
- const items = await getRedirectedLink(list);
+ const items = getList(data);
+
return {
- title: 'Popular',
- link: baseUrl,
+ title: 'Popular posts on daily.dev',
+ link,
item: items,
- description: 'Popular Posts on Daily.dev',
- logo: 'https://app.daily.dev/favicon-32x32.png',
- icon: 'https://app.daily.dev/favicon-32x32.png',
+ description: 'daily.dev is the easiest way to stay updated on the latest programming news. Get the best content from the top tech publications on any topic you want.',
+ logo: `${baseUrl}/favicon-32x32.png`,
+ icon: `${baseUrl}/favicon-32x32.png`,
language: 'en-us',
};
}
diff --git a/lib/routes/daily/namespace.ts b/lib/routes/daily/namespace.ts
index f40a96813..1b57d03d5 100644
--- a/lib/routes/daily/namespace.ts
+++ b/lib/routes/daily/namespace.ts
@@ -2,7 +2,7 @@ import type { Namespace } from '@/types';
export const namespace: Namespace = {
name: 'Daily.dev',
- url: 'daily.dev',
+ url: 'app.daily.dev',
categories: ['social-media'],
lang: 'en',
};
diff --git a/lib/routes/daily/source.ts b/lib/routes/daily/source.ts
new file mode 100644
index 000000000..4594daa6d
--- /dev/null
+++ b/lib/routes/daily/source.ts
@@ -0,0 +1,186 @@
+import { Route } from '@/types';
+import { baseUrl, getBuildId, getData, getList } from './utils';
+import ofetch from '@/utils/ofetch';
+import cache from '@/utils/cache';
+import { config } from '@/config';
+
+interface Source {
+ id: string;
+ name: string;
+ handle: string;
+ image: string;
+ permalink: string;
+ description: string;
+ type: string;
+}
+
+const sourceFeedQuery = `
+query SourceFeed($source: ID!, $loggedIn: Boolean! = false, $first: Int, $after: String, $ranking: Ranking, $supportedTypes: [String!]) {
+ page: sourceFeed(
+ source: $source
+ first: $first
+ after: $after
+ ranking: $ranking
+ supportedTypes: $supportedTypes
+ ) {
+ ...FeedPostConnection
+ }
+}
+
+fragment FeedPostConnection on PostConnection {
+ pageInfo {
+ hasNextPage
+ endCursor
+ }
+ edges {
+ node {
+ ...FeedPost
+ pinnedAt
+ contentHtml
+ ...UserPost @include(if: $loggedIn)
+ }
+ }
+}
+
+fragment FeedPost on Post {
+ ...FeedPostInfo
+ sharedPost {
+ id
+ title
+ image
+ readTime
+ permalink
+ commentsPermalink
+ createdAt
+ type
+ tags
+ source {
+ id
+ handle
+ permalink
+ image
+ }
+ slug
+ }
+ trending
+ feedMeta
+ collectionSources {
+ handle
+ image
+ }
+ numCollectionSources
+ updatedAt
+ slug
+}
+
+fragment FeedPostInfo on Post {
+ id
+ title
+ image
+ readTime
+ permalink
+ commentsPermalink
+ createdAt
+ commented
+ bookmarked
+ views
+ numUpvotes
+ numComments
+ summary
+ bookmark {
+ remindAt
+ }
+ author {
+ id
+ name
+ image
+ username
+ permalink
+ }
+ type
+ tags
+ source {
+ id
+ handle
+ name
+ permalink
+ image
+ type
+ }
+ userState {
+ vote
+ flags {
+ feedbackDismiss
+ }
+ }
+ slug
+}
+
+fragment UserPost on Post {
+ read
+ upvoted
+ commented
+ bookmarked
+ downvoted
+}`;
+
+export const route: Route = {
+ path: '/source/:sourceId',
+ example: '/daily/source/hn',
+ parameters: {
+ sourceId: 'The source id',
+ },
+ radar: [
+ {
+ source: ['app.daily.dev/sources/:sourceId'],
+ },
+ ],
+ name: 'Source Posts',
+ maintainers: ['TonyRL'],
+ handler,
+ url: 'app.daily.dev',
+};
+
+async function handler(ctx) {
+ const sourceId = ctx.req.param('sourceId');
+ const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 10;
+ const link = `${baseUrl}/sources/${sourceId}`;
+
+ const buildId = await getBuildId();
+
+ const userData = (await cache.tryGet(`daily:source:${sourceId}`, async () => {
+ const response = await ofetch(`${baseUrl}/_next/data/${buildId}/en/sources/${sourceId}.json`);
+ return response.pageProps.source;
+ })) as Source;
+
+ const items = await cache.tryGet(
+ `daily:source:${sourceId}:posts`,
+ async () => {
+ const edges = await getData({
+ query: sourceFeedQuery,
+ variables: {
+ source: sourceId,
+ supportedTypes: ['article', 'video:youtube', 'collection'],
+ period: 30,
+ first: limit,
+ after: '',
+ loggedIn: false,
+ },
+ });
+ return getList(edges);
+ },
+ config.cache.routeExpire,
+ false
+ );
+
+ return {
+ title: `${userData.name} posts on daily.dev`,
+ description: userData.description,
+ link,
+ item: items,
+ image: userData.image,
+ logo: userData.image,
+ icon: userData.image,
+ language: 'en-us',
+ };
+}
diff --git a/lib/routes/daily/upvoted.ts b/lib/routes/daily/upvoted.ts
index 68a2a19d6..8326d0618 100644
--- a/lib/routes/daily/upvoted.ts
+++ b/lib/routes/daily/upvoted.ts
@@ -1,5 +1,5 @@
import { Route } from '@/types';
-import { getData, getList, getRedirectedLink } from './utils.js';
+import { baseUrl, getData, getList } from './utils.js';
const variables = {
period: 7,
@@ -21,6 +21,7 @@ const query = `
edges {
node {
...FeedPost
+ contentHtml
}
}
}
@@ -35,6 +36,7 @@ const query = `
image
readTime
permalink
+ commentsPermalink
summary
createdAt
numUpvotes
@@ -56,37 +58,35 @@ const query = `
`;
-const graphqlQuery = {
- query,
- variables,
-};
-
export const route: Route = {
path: '/upvoted',
example: '/daily/upvoted',
radar: [
{
- source: ['daily.dev/popular'],
+ source: ['app.daily.dev/upvoted'],
},
],
name: 'Most upvoted',
maintainers: ['Rjnishant530'],
handler,
- url: 'daily.dev/popular',
+ url: 'app.daily.dev/upvoted',
};
async function handler() {
- const baseUrl = 'https://app.daily.dev/upvoted';
- const data = await getData(graphqlQuery);
- const list = getList(data);
- const items = await getRedirectedLink(list);
+ const link = `${baseUrl}/upvoted`;
+ const data = await getData({
+ query,
+ variables,
+ });
+ const items = getList(data);
+
return {
- title: 'Most Upvoted',
- link: baseUrl,
+ title: 'Most upvoted posts for developers | daily.dev',
+ link,
item: items,
- description: 'Most Upvoted Posts on Daily.dev',
- logo: 'https://app.daily.dev/favicon-32x32.png',
- icon: 'https://app.daily.dev/favicon-32x32.png',
+ description: 'Find the most upvoted developer posts on daily.dev. Explore top-rated content in coding, tutorials, and tech news from the largest developer network in the world.',
+ logo: `${baseUrl}/favicon-32x32.png`,
+ icon: `${baseUrl}/favicon-32x32.png`,
language: 'en-us',
};
}
diff --git a/lib/routes/daily/user.ts b/lib/routes/daily/user.ts
index 7abaf15a0..cdf738368 100644
--- a/lib/routes/daily/user.ts
+++ b/lib/routes/daily/user.ts
@@ -1,13 +1,8 @@
import { Route } from '@/types';
-import { baseUrl, getBuildId, getData } from './utils';
+import { baseUrl, getBuildId, getData, getList } from './utils';
import ofetch from '@/utils/ofetch';
import cache from '@/utils/cache';
import { config } from '@/config';
-import { parseDate } from '@/utils/parse-date';
-import { art } from '@/utils/render';
-import path from 'path';
-import { getCurrentPath } from '@/utils/helpers';
-const __dirname = getCurrentPath(import.meta.url);
const userPostQuery = `
query AuthorFeed(
@@ -155,20 +150,18 @@ const userPostQuery = `
downvoted
}`;
-const render = (data) => art(path.join(__dirname, 'templates/posts.art'), data);
-
export const route: Route = {
path: '/user/:userId',
example: '/daily/user/kramer',
radar: [
{
- source: ['daily.dev/:userId/posts', 'daily.dev/:userId'],
+ source: ['app.daily.dev/:userId/posts', 'app.daily.dev/:userId'],
},
],
name: 'User Posts',
maintainers: ['TonyRL'],
handler,
- url: 'daily.dev',
+ url: 'app.daily.dev',
};
async function handler(ctx) {
@@ -178,12 +171,12 @@ async function handler(ctx) {
const buildId = await getBuildId();
const userData = await cache.tryGet(`daily:user:${userId}`, async () => {
- const resposne = await ofetch(`${baseUrl}/_next/data/${buildId}/en/${userId}.json`, {
+ const response = await ofetch(`${baseUrl}/_next/data/${buildId}/en/${userId}.json`, {
query: {
userId,
},
});
- return resposne.pageProps;
+ return response.pageProps;
});
const user = (userData as any).user;
@@ -198,17 +191,7 @@ async function handler(ctx) {
loggedIn: false,
},
});
- return edges.map(({ node }) => ({
- title: node.title,
- description: render({
- image: node.image,
- content: node.contentHtml?.replaceAll('\n', '
') ?? node.summary,
- }),
- link: node.permalink,
- author: node.author?.name,
- category: node.tags,
- pubDate: parseDate(node.createdAt),
- }));
+ return getList(edges);
},
config.cache.routeExpire,
false
diff --git a/lib/routes/daily/utils.ts b/lib/routes/daily/utils.ts
index 8f203c744..4576a8695 100644
--- a/lib/routes/daily/utils.ts
+++ b/lib/routes/daily/utils.ts
@@ -2,10 +2,15 @@ import { parseDate } from '@/utils/parse-date';
import ofetch from '@/utils/ofetch';
import cache from '@/utils/cache';
import { config } from '@/config';
+import { art } from '@/utils/render';
+import path from 'node:path';
+import { getCurrentPath } from '@/utils/helpers';
+const __dirname = getCurrentPath(import.meta.url);
-const baseUrl = 'https://app.daily.dev';
+export const baseUrl = 'https://app.daily.dev';
+const gqlUrl = `https://api.daily.dev/graphql`;
-const getBuildId = () =>
+export const getBuildId = () =>
cache.tryGet(
'daily:buildId',
async () => {
@@ -17,40 +22,30 @@ const getBuildId = () =>
false
);
-const getData = async (graphqlQuery) => {
- const response = await ofetch(`${baseUrl}/api/graphql`, {
+export const getData = async (graphqlQuery) => {
+ const response = await ofetch(gqlUrl, {
method: 'POST',
body: graphqlQuery,
});
return response.data.page.edges;
};
-const getList = (data) =>
- data.map((value) => {
- const { id, title, image, permalink, summary, createdAt, numUpvotes, author, tags, numComments } = value.node;
- const pubDate = parseDate(createdAt);
- return {
- id,
- title,
- link: permalink,
- description: summary,
- author: author?.name,
- itunes_item_image: image,
- pubDate,
- upvotes: numUpvotes,
- comments: numComments,
- category: tags,
- };
- });
+const render = (data) => art(path.join(__dirname, 'templates/posts.art'), data);
-const getRedirectedLink = (data) =>
- Promise.all(
- data.map((v) =>
- cache.tryGet(v.link, async () => {
- const resp = await ofetch.raw(v.link);
- return { ...v, link: resp.headers.get('location') };
- })
- )
- );
-
-export { baseUrl, getBuildId, getData, getList, getRedirectedLink };
+export const getList = (edges) =>
+ edges.map(({ node }) => ({
+ id: node.id,
+ title: node.title,
+ link: node.commentsPermalink ?? node.permalink,
+ guid: node.permalink,
+ description: render({
+ image: node.image,
+ content: node.contentHtml?.replaceAll('\n', '
') ?? node.summary,
+ }),
+ author: node.author?.name,
+ itunes_item_image: node.image,
+ pubDate: parseDate(node.createdAt),
+ upvotes: node.numUpvotes,
+ comments: node.numComments,
+ category: node.tags,
+ }));
diff --git a/lib/routes/espn/news.ts b/lib/routes/espn/news.ts
index 154cb72cd..0187cd06c 100644
--- a/lib/routes/espn/news.ts
+++ b/lib/routes/espn/news.ts
@@ -2,7 +2,7 @@ import { Route } from '@/types';
import cache from '@/utils/cache';
import ofetch from '@/utils/ofetch';
import * as cheerio from 'cheerio';
-import path from 'path';
+import path from 'node:path';
import { getCurrentPath } from '@/utils/helpers';
import { art } from '@/utils/render';
diff --git a/lib/routes/imdb/chart.ts b/lib/routes/imdb/chart.ts
index 4d1611280..117454065 100644
--- a/lib/routes/imdb/chart.ts
+++ b/lib/routes/imdb/chart.ts
@@ -3,7 +3,7 @@ import ofetch from '@/utils/ofetch';
import * as cheerio from 'cheerio';
import type { Context } from 'hono';
import { ChartTitleSearchConnection } from './types';
-import path from 'path';
+import path from 'node:path';
import { getCurrentPath } from '@/utils/helpers';
import { art } from '@/utils/render';
diff --git a/lib/routes/jiuyangongshe/community.ts b/lib/routes/jiuyangongshe/community.ts
index 05138854f..d739cd583 100644
--- a/lib/routes/jiuyangongshe/community.ts
+++ b/lib/routes/jiuyangongshe/community.ts
@@ -4,7 +4,7 @@ import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';
import timezone from '@/utils/timezone';
import md5 from '@/utils/md5';
-import path from 'path';
+import path from 'node:path';
import { getCurrentPath } from '@/utils/helpers';
import { art } from '@/utils/render';
diff --git a/lib/routes/mi/utils.ts b/lib/routes/mi/utils.ts
index a0839f489..2fc2c90d2 100644
--- a/lib/routes/mi/utils.ts
+++ b/lib/routes/mi/utils.ts
@@ -9,7 +9,7 @@ import 'dayjs/locale/zh-cn';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';
-import path from 'path';
+import path from 'node:path';
import { CrowdfundingData, CrowdfundingDetailData, CrowdfundingDetailInfo, CrowdfundingItem, CrowdfundingList, DataResponse } from './types';
dayjs.extend(localizedFormat);
diff --git a/lib/routes/theblockbeats/index.ts b/lib/routes/theblockbeats/index.ts
index 4fc1112c7..a61a6fc9f 100644
--- a/lib/routes/theblockbeats/index.ts
+++ b/lib/routes/theblockbeats/index.ts
@@ -3,7 +3,7 @@ import cache from '@/utils/cache';
import ofetch from '@/utils/ofetch';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
-import path from 'path';
+import path from 'node:path';
import { art } from '@/utils/render';
import { getCurrentPath } from '@/utils/helpers';
diff --git a/lib/routes/vice/topic.ts b/lib/routes/vice/topic.ts
index 339655ad8..51b0f977f 100644
--- a/lib/routes/vice/topic.ts
+++ b/lib/routes/vice/topic.ts
@@ -3,7 +3,7 @@ import ofetch from '@/utils/ofetch';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
import cache from '@/utils/cache';
-import path from 'path';
+import path from 'node:path';
import { getCurrentPath } from '@/utils/helpers';
import { art } from '@/utils/render';
diff --git a/lib/routes/wellcee/rent.ts b/lib/routes/wellcee/rent.ts
index dc67f30c9..9c092b40d 100644
--- a/lib/routes/wellcee/rent.ts
+++ b/lib/routes/wellcee/rent.ts
@@ -7,7 +7,7 @@ import { parseDate } from '@/utils/parse-date';
import { baseUrl, getCitys, getDistricts } from './utils';
import InvalidParameterError from '@/errors/types/invalid-parameter';
import { art } from '@/utils/render';
-import path from 'path';
+import path from 'node:path';
import { getCurrentPath } from '@/utils/helpers';
const __dirname = getCurrentPath(import.meta.url);