feat(Wikidata API): implement endpoints for fetching property labels, properties, and suggestions
This commit is contained in:
parent
c5380c0661
commit
d480495715
3 changed files with 169 additions and 0 deletions
54
src/app/api/wikidata/labels/route.ts
Normal file
54
src/app/api/wikidata/labels/route.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { propertyIds } = await request.json();
|
||||
|
||||
if (!propertyIds || !Array.isArray(propertyIds)) {
|
||||
return NextResponse.json({ error: 'propertyIds array is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
const cleanIds = propertyIds.map(id => id.replace('http://www.wikidata.org/prop/', ''));
|
||||
const propertyIdsStr = cleanIds.join(' wd:');
|
||||
|
||||
const sparqlQuery = `
|
||||
SELECT ?prop ?propLabel WHERE {
|
||||
VALUES ?prop { wd:${propertyIdsStr} }
|
||||
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
|
||||
}
|
||||
`;
|
||||
|
||||
const url = `https://query.wikidata.org/sparql?query=${encodeURIComponent(sparqlQuery)}&format=json`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': 'WikidataApp/1.0 (https://example.com/contact)'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Wikidata SPARQL error: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const result: Record<string, string> = {};
|
||||
|
||||
if (data.results?.bindings) {
|
||||
for (const binding of data.results.bindings) {
|
||||
const propUri = binding.prop?.value;
|
||||
const label = binding.propLabel?.value || '';
|
||||
|
||||
if (propUri) {
|
||||
const propId = propUri.split('/').pop() || '';
|
||||
result[propId] = label;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(result);
|
||||
} catch (error) {
|
||||
console.error('Error fetching property labels:', error);
|
||||
return NextResponse.json({});
|
||||
}
|
||||
}
|
59
src/app/api/wikidata/properties/route.ts
Normal file
59
src/app/api/wikidata/properties/route.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const wikidataId = searchParams.get('wikidataId');
|
||||
|
||||
if (!wikidataId || typeof wikidataId !== 'string') {
|
||||
return NextResponse.json({ error: 'wikidataId parameter is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const sparqlQuery = `
|
||||
SELECT ?prop ?propLabel ?value ?valueLabel WHERE {
|
||||
wd:${wikidataId} ?prop ?statement.
|
||||
?statement ?ps ?value.
|
||||
?property wikibase:claim ?prop.
|
||||
?property wikibase:statementProperty ?ps.
|
||||
SERVICE wikibase:label {
|
||||
bd:serviceParam wikibase:language "en".
|
||||
?prop rdfs:label ?propLabel.
|
||||
?value rdfs:label ?valueLabel.
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const url = `https://query.wikidata.org/sparql?query=${encodeURIComponent(sparqlQuery)}&format=json`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'User-Agent': 'WikidataApp/1.0 (https://example.com/contact)'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Wikidata SPARQL error: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const result: Record<string, string> = {};
|
||||
|
||||
if (data.results?.bindings) {
|
||||
for (const binding of data.results.bindings) {
|
||||
const propUri = binding.prop?.value;
|
||||
const value = binding.valueLabel?.value || binding.value?.value || '';
|
||||
|
||||
if (propUri) {
|
||||
const propId = propUri.split('/').pop() || '';
|
||||
result[propId] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json(result);
|
||||
} catch (error) {
|
||||
console.error('Error fetching Wikidata properties:', error);
|
||||
return NextResponse.json({});
|
||||
}
|
||||
}
|
56
src/app/api/wikidata/suggestions/route.ts
Normal file
56
src/app/api/wikidata/suggestions/route.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
// Define interfaces for Wikidata API response
|
||||
interface WikidataSearchItem {
|
||||
id: string;
|
||||
label?: string;
|
||||
description?: string;
|
||||
concepturi?: string;
|
||||
url?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
interface WikidataSearchResponse {
|
||||
search?: WikidataSearchItem[];
|
||||
searchinfo?: {
|
||||
search: string;
|
||||
};
|
||||
success?: number;
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const query = searchParams.get('query');
|
||||
|
||||
if (!query || typeof query !== 'string') {
|
||||
return NextResponse.json({ error: 'Query parameter is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const wikidataUrl = `https://www.wikidata.org/w/api.php?action=wbsearchentities&search=${encodeURIComponent(query)}&language=en&limit=5&format=json&origin=*`;
|
||||
|
||||
const response = await fetch(wikidataUrl, {
|
||||
headers: {
|
||||
'User-Agent': 'WikidataApp/1.0 (https://example.com/contact)'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Wikidata API error: ${response.status}`);
|
||||
}
|
||||
|
||||
const data: WikidataSearchResponse = await response.json();
|
||||
|
||||
// Transform the response to match our WikidataSuggestion interface
|
||||
const suggestions = (data.search || []).map((item: WikidataSearchItem) => ({
|
||||
id: item.id,
|
||||
label: item.label || '',
|
||||
description: item.description || ''
|
||||
}));
|
||||
|
||||
return NextResponse.json(suggestions);
|
||||
} catch (error) {
|
||||
console.error('Error fetching Wikidata suggestions:', error);
|
||||
return NextResponse.json({ error: 'Failed to fetch suggestions' }, { status: 500 });
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue