Skip to content
Snippets Groups Projects
Unverified Commit 8262eb5a authored by Andreas Hubel's avatar Andreas Hubel
Browse files

init

parents
Branches
No related tags found
No related merge requests found
/node_modules
{
"name": "activity-pub-audiothek",
"version": "0.1.0",
"main": "mapping1.ts",
"license": "MIT",
"dependencies": {
"@urql/core": "^5.1.1",
"express": "^4.21.2",
"typescript": "^5.8.2"
},
"devDependencies": {
"@types/express": "^5.0.0"
}
}
import { Client, cacheExchange, fetchExchange, gql } from '@urql/core';
import { Response } from './types';
const audiothekApi = new Client({
url: 'https://api.ardaudiothek.de/graphql',
exchanges: [cacheExchange, fetchExchange],
});
const query = gql`
query Item {
item(id: "14278953") {
show {
coreId
externalId
title
url
publisher: publicationService {
coreId
dvbServiceId
title
url
organizationName
organization {
name
url
}
}
coreDocument
}
assetId
url: sharingUrl
title
published: publishDate
updated: core(key: "modified")
imagesList {
url
title
}
coreDocument
audioList {
title
audioCodec
href
}
}
}
`;
async function fetchData() {
const result = await audiothekApi.query<Response>(query, {}).toPromise();
if (result.error) {
throw result.error;
}
// console.log(JSON.stringify(result.data, null, 2));
return result.data;
}
function transformToActivityPub(response: Response) {
const item = response.item;
return {
"@context": "https://www.w3.org/ns/activitystreams",
"id": item.assetId,
"type": "PodcastEpisode",
"published": item.published,
"updated": item.updated,
"attributedTo": item.show.coreId,
"externalId": item.url,
"title": item.title,
"description": {
"type": "Note",
"mediaType": "text/markdown",
"content": item.coreDocument
},
"image": item.imagesList.length > 0 ? {
"type": "Image",
"url": item.imagesList[0].url
} : undefined,
"audio": item.audioList.map(audio => ({
"type": "Audio",
"name": audio.title,
"mediaType": "audio/mpeg",
"url": audio.href
})),
"partOf": {
"type": "PodcastSeries",
"id": item.show.coreId,
"externalId": item.show.externalId,
"name": item.show.title,
"attributedTo": item.show.publisher.coreId,
"publisher": {
"type": "BroadcastService",
"name": item.show.publisher.title,
"url": item.show.publisher.url,
"organization": {
"type": "Organization",
"name": item.show.publisher.organization.name,
"url": item.show.publisher.organization.url
}
}
}
};
}
async function main() {
const response = await fetchData();
if (response) {
const activityPubEpisode = transformToActivityPub(response);
console.log(JSON.stringify(activityPubEpisode, null, 2));
}
}
main();
import express from 'express';
import { Client, cacheExchange, fetchExchange, gql } from '@urql/core';
import { Response } from './types';
const app = express();
const PORT = 3000;
const audiothekApi = new Client({
url: 'https://api.ardaudiothek.de/graphql',
exchanges: [cacheExchange, fetchExchange],
});
const query = gql`
query Item {
item(id: "14278953") {
show {
coreId
externalId
title
url
publisher: publicationService {
coreId
dvbServiceId
title
url
organizationName
organization {
name
url
}
}
coreDocument
}
assetId
url: sharingUrl
title
description
published: publishDate
updated: core(key: "modified")
imagesList {
url
title
}
coreDocument
audioList {
title
audioCodec
href
}
}
}
`;
async function fetchData(query: any, variables: any) {
const result = await audiothekApi.query<Response>(query, variables).toPromise();
if (result.error) {
throw result.error;
}
// console.log(JSON.stringify(result.data, null, 2));
return result.data;
}
function transformEpisodeToActivityPub(response: Response) {
const item = response.item;
return {
"@context": "https://www.w3.org/ns/activitystreams",
"id": item.assetId,
"type": "PodcastEpisode",
"published": item.published,
"updated": item.updated,
"attributedTo": item.show.coreId,
"externalId": item.url,
"title": item.title,
"description": {
"type": "Note",
"mediaType": "text/markdown",
"content": item.description
},
"image": item.imagesList.length > 0 ? {
"type": "Image",
"url": item.imagesList[0].url
} : undefined,
"audio": item.audioList.map(audio => ({
"type": "Audio",
"name": audio.title,
"mediaType": "audio/mpeg",
"url": audio.href
})),
"partOf": {
"type": "PodcastSeries",
"id": item.show.coreId,
"externalId": item.show.externalId,
"name": item.show.title,
"attributedTo": item.show.publisher.coreId,
"publisher": {
"type": "BroadcastService",
"name": item.show.publisher.title,
"url": item.show.publisher.url,
"organization": {
"type": "Organization",
"name": item.show.publisher.organization.name,
"url": item.show.publisher.organization.url
}
}
}
};
}
async function main() {
const response = await fetchData(query, { id: '14278953' });
if (response) {
const activityPubEpisode = transformEpisodeToActivityPub(response);
console.log(JSON.stringify(activityPubEpisode, null, 2));
}
}
// main();
app.get('/:actor/episodes/:id', async (req, res) => {
try {
const data = await fetchData(query, { id: req.params.id });
if (!data) {
res.status(404).json({ error: 'Episode not found' });
return;
}
// TODO: verifiy that the actor is the same as the attributedTo field
const activityPubDocument = transformEpisodeToActivityPub(data);
res.json(activityPubDocument);
} catch (error) {
res.status(500).json({ error: 'Failed to fetch episode data' });
}
});
app.get('/@blaue-couch', async (req, res) => {
res.json({
"@context": "https://www.w3.org/ns/activitystreams",
"id": "urn:ard:show:a42d1ea0b4a07053",
"type": "Service",
"name": "Blaue Couch",
"externalId": "https://feeds.br.de/blaue-couch/feed.xml",
"attributedTo": "urn:ard:publisher:c4a9cee041835529",
"publisher": {
"type": "BroadcastService",
"name": "BAYERN 1",
"url": "https://www.ardaudiothek.de/radio/br/bayern-1/",
"organization": {
"type": "Organization",
"name": "BR",
"url": "https://www.ardaudiothek.de/radio/br/"
}
}
});
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
export type Show = {
coreId: string;
externalId: string;
title: string;
url: string;
publisher: {
coreId: string;
dvbServiceId: number;
title: string;
url: string;
organizationName: string;
organization: {
name: string;
url: string;
};
};
coreDocument: string;
};
export type Item = {
assetId: string;
url: string;
title: string;
description: string;
published: string;
updated: string;
imagesList: { url: string; title: string }[];
coreDocument: string;
audioList: { title: string; audioCodec: string; href: string }[];
show: Show;
};
export type Response = {
item: Item;
};
\ No newline at end of file
{
"compilerOptions": {
"target": "ES2017",
"lib": ["ES2017", "DOM"],
"strict": true,
"outDir": "./dist",
"rootDir": "./src",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment