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

init

parents
No related branches found
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 to comment