diff --git a/src/app/api/wikidata/labels/route.ts b/src/app/api/wikidata/labels/route.ts new file mode 100644 index 0000000..aa92b27 --- /dev/null +++ b/src/app/api/wikidata/labels/route.ts @@ -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 = {}; + + 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({}); + } +} \ No newline at end of file diff --git a/src/app/api/wikidata/properties/route.ts b/src/app/api/wikidata/properties/route.ts new file mode 100644 index 0000000..ecc52d8 --- /dev/null +++ b/src/app/api/wikidata/properties/route.ts @@ -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 = {}; + + 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({}); + } +} \ No newline at end of file diff --git a/src/app/api/wikidata/suggestions/route.ts b/src/app/api/wikidata/suggestions/route.ts new file mode 100644 index 0000000..592cb12 --- /dev/null +++ b/src/app/api/wikidata/suggestions/route.ts @@ -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 }); + } +} \ No newline at end of file