Skip to content

Commit

Permalink
Merge pull request #655 from RobinNagpal/hassaan/sitemap
Browse files Browse the repository at this point in the history
Hassaan/sitemap
  • Loading branch information
RobinNagpal authored Feb 5, 2025
2 parents 5746827 + b5ee36a commit 9682084
Showing 1 changed file with 168 additions and 58 deletions.
226 changes: 168 additions & 58 deletions academy-ui/src/app/sitemap.xml/route.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { CourseDetailsFragment, CourseTopicFragment, GuideFragment } from '@/graphql/generated/generated-types';
import { SpaceWithIntegrationsDto } from '@/types/space/SpaceDto';
import {
CourseDetailsFragment,
CourseFragment,
CourseTopicFragment,
GuideFragment,
GuideSummaryFragment,
ClickableDemo,
} from '@/graphql/generated/generated-types';
import { SpaceWithIntegrationsDto, SpaceTypes } from '@/types/space/SpaceDto';
import { getSpaceBasedOnHostHeader } from '@/utils/space/getSpaceServerSide';
import { PredefinedSpaces } from '@dodao/web-core/src/utils/constants/constants';
import axios from 'axios';
import { NextRequest, NextResponse } from 'next/server';
import { SitemapStream, streamToPromise } from 'sitemap';
import { ByteCollectionItemType } from '@/app/api/helpers/byteCollection/byteCollectionItemType';
import getBaseUrl from '@dodao/web-core/utils/api/getBaseURL';

interface SiteMapUrl {
url: string;
Expand All @@ -13,114 +22,215 @@ interface SiteMapUrl {
}

async function getAllGuidesWithSteps(spaceId: string) {
const guidesUrl = process.env.V2_API_SERVER_URL?.replace('/graphql', '') + `/${spaceId}/guides`;
const baseUrl = getBaseUrl();

const response = await axios.get(guidesUrl);
const response = await axios.get(`${baseUrl}/api/guide/guides`, {
params: {
spaceId,
},
});

return response?.data as GuideFragment[];
return response.data.guides as GuideSummaryFragment[];
}

async function getAllCourses(spaceId: string) {
const coursesUrl = process.env.V2_API_SERVER_URL?.replace('/graphql', '') + `/${spaceId}/courses`;
async function getClickableDemos(spaceId: string): Promise<ClickableDemo[]> {
const baseUrl = getBaseUrl();

const response = await axios.get(`${baseUrl}/api/clickable-demos`, {
params: { spaceId },
});

const response = await axios.get(coursesUrl);
return response?.data as CourseDetailsFragment[];
return response.data.clickableDemos as ClickableDemo[];
}

async function getClickableDemoUrls(spaceId: string): Promise<SiteMapUrl[]> {
const demos = await getClickableDemos(spaceId);
const urls: SiteMapUrl[] = [];

for (const demo of demos) {
urls.push({
url: `/clickable-demos/view/${demo.id}`,
changefreq: 'weekly',
priority: 0.8,
});
}

return urls;
}

async function getGuideUrlsForAcademy(spaceId: string): Promise<SiteMapUrl[]> {
const allGuides: GuideFragment[] = await getAllGuidesWithSteps(spaceId);
const allGuides: GuideSummaryFragment[] = await getAllGuidesWithSteps(spaceId);
const urls: SiteMapUrl[] = [];
for (const guide of allGuides) {
guide.steps.forEach((s, index) => {
if (s.content.length > 50) {
const sitemapUrl = {
url: `/guides/view/${guide.uuid}/${index}`,
changefreq: 'weekly',
};
urls.push(sitemapUrl);
}
urls.push({
url: `/guides/view/${guide.id}/0`,
changefreq: 'monthly',
priority: 0.8,
});
}
return urls;
}

async function getCourseUrlsForAcademy(space: SpaceWithIntegrationsDto): Promise<SiteMapUrl[]> {
const gitCourses: CourseDetailsFragment[] = await getAllCourses(space.id);
async function getAllCourseKeys(spaceId: string) {
const baseUrl = getBaseUrl();
const response = await axios.get(`${baseUrl}/api/courses`, {
params: { spaceId },
});

return response.data.courses as CourseFragment[];
}

async function getCourseDetails(spaceId: string, courseKey: string) {
const baseUrl = getBaseUrl();
const response = await axios.get(`${baseUrl}/api/courses/${courseKey}`, {
params: { spaceId },
});
return response.data.course as CourseDetailsFragment;
}

async function getCourseUrlsForAcademy(spaceId: string): Promise<SiteMapUrl[]> {
const courses = await getAllCourseKeys(spaceId);
const urls: SiteMapUrl[] = [];
(gitCourses || []).forEach((course: CourseDetailsFragment) => {
urls.push({ url: `/courses/view/${course.key}`, changefreq: 'weekly' });

course.topics.forEach((topic: CourseTopicFragment) => {
urls.push({ url: `/courses/view/${course.key}/${topic.key}`, changefreq: 'weekly' });
for (const course of courses) {
urls.push({
url: `/courses/view/${course.key}`,
changefreq: 'weekly',
priority: 0.8,
});

const detailedCourse = await getCourseDetails(spaceId, course.key);

(topic.explanations || []).forEach((explanation) => {
for (const topic of detailedCourse.topics || []) {
urls.push({
url: `/courses/view/${detailedCourse.key}/${topic.key}`,
changefreq: 'weekly',
priority: 0.7,
});

for (const explanation of topic.explanations || []) {
urls.push({
url: `/courses/view/${course.key}/${topic.key}/explanation/${explanation.key}`,
url: `/courses/view/${detailedCourse.key}/${topic.key}/explanations/${explanation.key}`,
changefreq: 'weekly',
priority: 0.6,
});
});
});
});
}
}
}

return urls;
}

async function getDoDAOSiteMapUrls(): Promise<SiteMapUrl[]> {
const urls: SiteMapUrl[] = [
{ url: '/', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/products/tidbitshub', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/products/academysites', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/products/ai-crowdfunding-agent', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/services/smart-contract', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/services/blockchain-tooling', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/services/defi-analytics', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/services/custom-ai-agent-dev', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/home-section/dodao-io/services/maintenance-support', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/education/blockchain-bootcamp', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/education/educational-content', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/research/real-world-assets', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/research/decen-sol-reviews', changefreq: 'weekly' },
{ url: '/home-section/dodao-io/research/credit-union', changefreq: 'weekly' },
// New URL added here
{ url: 'https://publications.dodao.io/dodao-engaging-gen-z-website', changefreq: 'weekly' },
{ url: '/', changefreq: 'daily', priority: 1.0 },
{ url: '/home-section/dodao-io/products/tidbitshub', changefreq: 'weekly', priority: 0.8 },
{ url: '/home-section/dodao-io/products/academysites', changefreq: 'weekly', priority: 0.8 },
{ url: '/home-section/dodao-io/products/ai-crowdfunding-agent', changefreq: 'weekly', priority: 0.8 },
{ url: '/home-section/dodao-io/services/smart-contract', changefreq: 'monthly', priority: 0.7 },
{ url: '/home-section/dodao-io/services/blockchain-tooling', changefreq: 'monthly', priority: 0.7 },
{ url: '/home-section/dodao-io/services/defi-analytics', changefreq: 'monthly', priority: 0.7 },
{ url: '/home-section/dodao-io/services/custom-ai-agent-dev', changefreq: 'monthly', priority: 0.7 },
{ url: '/home-section/dodao-io/services/maintenance-support', changefreq: 'monthly', priority: 0.7 },
{ url: '/home-section/dodao-io/education/blockchain-bootcamp', changefreq: 'monthly', priority: 0.7 },
{ url: '/home-section/dodao-io/education/educational-content', changefreq: 'monthly', priority: 0.7 },
{ url: '/home-section/dodao-io/research/real-world-assets', changefreq: 'monthly', priority: 0.8 },
{ url: '/home-section/dodao-io/research/decen-sol-reviews', changefreq: 'monthly', priority: 0.6 },
{ url: '/home-section/dodao-io/research/credit-union', changefreq: 'monthly', priority: 0.6 },
{ url: 'https://publications.dodao.io/dodao-engaging-gen-z-website', changefreq: 'yearly', priority: 0.5 },
];

return urls;
}

async function writeDoDAOSiteMapToStream(space: SpaceWithIntegrationsDto, host: string, smStream: SitemapStream) {
if (space.id === PredefinedSpaces.DODAO_HOME) {
const dodaoUrls = await getDoDAOSiteMapUrls();
for (const url of dodaoUrls) {
smStream.write(url);
async function writeDoDAOSiteMapToStream(smStream: SitemapStream) {
const dodaoUrls = await getDoDAOSiteMapUrls();
for (const url of dodaoUrls) {
smStream.write(url);
}
}

async function getTidbitsHubSiteMapUrls(): Promise<SiteMapUrl[]> {
const urls: SiteMapUrl[] = [{ url: '/', changefreq: 'daily', priority: 1.0 }];

return urls;
}

async function writeTidbitsHubSiteMapToStream(smStream: SitemapStream) {
const dodaoUrls = await getTidbitsHubSiteMapUrls();
for (const url of dodaoUrls) {
smStream.write(url);
}
}

async function getTidbitCollections(spaceId: string) {
const baseUrl = getBaseUrl();
const response = await axios.get(`${baseUrl}/api/${spaceId}/byte-collections`);
return response.data;
}

async function getTidbitCollectionUrlsForAcademy(spaceId: string): Promise<SiteMapUrl[]> {
const collections = await getTidbitCollections(spaceId);
const urls: SiteMapUrl[] = [];

for (const collection of collections) {
for (const item of collection.items || []) {
switch (item.type) {
case ByteCollectionItemType.Byte:
urls.push({
url: `/tidbit-collections/view/${collection.id}/${item.byte.byteId}`,
changefreq: 'weekly',
priority: 0.7,
});
break;
}
}
} else {
return [];
}

return urls;
}

async function writeUrlsToStream(space: SpaceWithIntegrationsDto, host: string, smStream: SitemapStream) {
const guideUrls = await getGuideUrlsForAcademy(space.id);

for (const guideUrl of guideUrls) {
smStream.write(guideUrl);
}

const courseUrls = await getCourseUrlsForAcademy(space);

const courseUrls = await getCourseUrlsForAcademy(space.id);
for (const courseUrl of courseUrls) {
smStream.write(courseUrl);
}

const demoUrls = await getClickableDemoUrls(space.id);
for (const demoUrl of demoUrls) {
smStream.write(demoUrl);
}

const tidbitUrls = await getTidbitCollectionUrlsForAcademy(space.id);
for (const tidbitUrl of tidbitUrls) {
smStream.write(tidbitUrl);
}
}

async function GET(req: NextRequest): Promise<NextResponse<Buffer>> {
const host = req.headers.get('host') as string;
const space = (await getSpaceBasedOnHostHeader(req.headers))!;

const smStream = new SitemapStream({ hostname: 'https://' + host });

// pipe your entries or directly write them.
// await writeUrlsToStream(space!, host, smStream);
await writeDoDAOSiteMapToStream(space, host, smStream);
if (space.id === PredefinedSpaces.DODAO_HOME) {
await writeDoDAOSiteMapToStream(smStream);
}
if (space.id === PredefinedSpaces.TIDBITS_HUB) {
await writeTidbitsHubSiteMapToStream(smStream);
}
if (space.type === SpaceTypes.AcademySite) {
smStream.write({ url: '/', changefreq: 'daily', priority: 1.0 }), smStream.write({ url: '/guides', changefreq: 'weekly', priority: 0.9 });
smStream.write({ url: '/tidbit-collections', changefreq: 'weekly', priority: 0.9 });
smStream.write({ url: '/clickable-demos', changefreq: 'weekly', priority: 0.9 });
smStream.write({ url: '/courses', changefreq: 'weekly', priority: 0.9 });
await writeUrlsToStream(space, host, smStream);
}

smStream.end();
// cache the response
Expand Down

0 comments on commit 9682084

Please sign in to comment.