diff --git a/server/routes.ts b/server/routes.ts index a1371b3..4826c07 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -438,85 +438,74 @@ export async function registerRoutes(app: Express): Promise { }); } - // To avoid 414 errors, we'll limit the name parameter to just the genus and species + // Extract genus and species for v4 API query const nameParts = String(name).split(' '); - const simplifiedName = nameParts.slice(0, 2).join(' '); const [genusName, speciesName] = nameParts; - // Try with v4 API first if we have a token + // Get IUCN token const activeToken = await storage.getActiveToken(); - if (activeToken?.iucnToken) { - try { - // First, we need to find the species taxon ID using scientific name lookup - const taxaResponse = await axios.get(`${IUCN_V4_BASE_URL}/taxa/scientific_name`, { - headers: { - "Authorization": `Bearer ${activeToken.iucnToken}` - }, - params: { - genus_name: genusName, - species_name: speciesName || "" - } - }); - - // Check if we found the species - if (taxaResponse.data && taxaResponse.data.result && taxaResponse.data.result.length > 0) { - const taxonId = taxaResponse.data.result[0].taxonid; - - // Now retrieve the threats using the taxon ID - const threatsResponse = await axios.get(`${IUCN_V4_BASE_URL}/threats/species/id/${taxonId}`, { - headers: { - "Authorization": `Bearer ${activeToken.iucnToken}` - } - }); - - return res.json({ - success: true, - data: threatsResponse.data, - apiVersion: "v4" - }); - } - // If no species found, fall back to v3 - console.log("IUCN V4 API: No species found with the given scientific name, falling back to V3"); - } catch (error: any) { - console.log("IUCN V4 API threats lookup failed, falling back to V3:", error.message); - // Continue to v3 fallback - } - } - - // Fallback to v3 API - const apiKey = process.env.IUCN_API_KEY; - if (!apiKey) { + if (!activeToken?.iucnToken) { return res.status(401).json({ success: false, - connected: false, - message: "IUCN API key is not configured" + message: "IUCN API v4 token is not configured. Please set your token in the API Token panel." }); } try { - const response = await axios.get(`${IUCN_V3_BASE_URL}/threats/species/name/${encodeURIComponent(simplifiedName)}`, { - params: { token: apiKey } + // First, we need to find the species taxon ID using scientific name lookup + const taxaResponse = await axios.get("https://apiv4.iucnredlist.org/api/v4/taxa/scientific_name", { + headers: { + "Authorization": `Bearer ${activeToken.iucnToken}` + }, + params: { + genus_name: genusName, + species_name: speciesName || "" + } }); - res.json({ - success: true, - data: response.data, - apiVersion: "v3" - }); - } catch (error) { - if (axios.isAxiosError(error) && error.response) { - return res.status(error.response.status).json({ - success: false, - message: error.response.data?.message || "Error from IUCN Red List API", - status: error.response.status + // Check if we found the species + if (!taxaResponse.data?.result || taxaResponse.data.result.length === 0) { + return res.status(404).json({ + success: false, + message: `No species found with the name "${name}" in the IUCN Red List database.` }); } - throw error; + + const taxonId = taxaResponse.data.result[0].taxonid; + + // Now retrieve the threats using the taxon ID + const threatsResponse = await axios.get(`https://apiv4.iucnredlist.org/api/v4/threats/species/id/${taxonId}`, { + headers: { + "Authorization": `Bearer ${activeToken.iucnToken}` + } + }); + + return res.json({ + success: true, + data: threatsResponse.data, + apiVersion: "v4" + }); + } catch (error: any) { + console.log("IUCN API threats lookup failed:", error.message); + + if (error.response?.status === 401) { + return res.status(401).json({ + success: false, + message: "IUCN API v4 token is invalid. Please check your token and try again." + }); + } + + return res.status(error.response?.status || 500).json({ + success: false, + message: error.response?.data?.message || "Error from IUCN Red List API: " + error.message, + status: error.response?.status + }); } } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); res.status(500).json({ success: false, - message: "Failed to retrieve IUCN threats data" + message: "Failed to retrieve IUCN threats data: " + errorMessage }); } }); @@ -532,85 +521,74 @@ export async function registerRoutes(app: Express): Promise { }); } - // To avoid 414 errors, we'll limit the name parameter to just the genus and species + // Extract genus and species for v4 API query const nameParts = String(name).split(' '); - const simplifiedName = nameParts.slice(0, 2).join(' '); const [genusName, speciesName] = nameParts; - // Try with v4 API first if we have a token + // Get IUCN token const activeToken = await storage.getActiveToken(); - if (activeToken?.iucnToken) { - try { - // First, we need to find the species taxon ID using scientific name lookup - const taxaResponse = await axios.get(`${IUCN_V4_BASE_URL}/taxa/scientific_name`, { - headers: { - "Authorization": `Bearer ${activeToken.iucnToken}` - }, - params: { - genus_name: genusName, - species_name: speciesName || "" - } - }); - - // Check if we found the species - if (taxaResponse.data && taxaResponse.data.result && taxaResponse.data.result.length > 0) { - const taxonId = taxaResponse.data.result[0].taxonid; - - // Now retrieve the habitats using the taxon ID - const habitatsResponse = await axios.get(`${IUCN_V4_BASE_URL}/habitats/species/id/${taxonId}`, { - headers: { - "Authorization": `Bearer ${activeToken.iucnToken}` - } - }); - - return res.json({ - success: true, - data: habitatsResponse.data, - apiVersion: "v4" - }); - } - // If no species found, fall back to v3 - console.log("IUCN V4 API: No species found with the given scientific name, falling back to V3"); - } catch (error: any) { - console.log("IUCN V4 API habitats lookup failed, falling back to V3:", error.message); - // Continue to v3 fallback - } - } - - // Fallback to v3 API - const apiKey = process.env.IUCN_API_KEY; - if (!apiKey) { + if (!activeToken?.iucnToken) { return res.status(401).json({ success: false, - connected: false, - message: "IUCN API key is not configured" + message: "IUCN API v4 token is not configured. Please set your token in the API Token panel." }); } try { - const response = await axios.get(`${IUCN_V3_BASE_URL}/habitats/species/name/${encodeURIComponent(simplifiedName)}`, { - params: { token: apiKey } + // First, we need to find the species taxon ID using scientific name lookup + const taxaResponse = await axios.get("https://apiv4.iucnredlist.org/api/v4/taxa/scientific_name", { + headers: { + "Authorization": `Bearer ${activeToken.iucnToken}` + }, + params: { + genus_name: genusName, + species_name: speciesName || "" + } }); - res.json({ - success: true, - data: response.data, - apiVersion: "v3" - }); - } catch (error) { - if (axios.isAxiosError(error) && error.response) { - return res.status(error.response.status).json({ - success: false, - message: error.response.data?.message || "Error from IUCN Red List API", - status: error.response.status + // Check if we found the species + if (!taxaResponse.data?.result || taxaResponse.data.result.length === 0) { + return res.status(404).json({ + success: false, + message: `No species found with the name "${name}" in the IUCN Red List database.` }); } - throw error; + + const taxonId = taxaResponse.data.result[0].taxonid; + + // Now retrieve the habitats using the taxon ID + const habitatsResponse = await axios.get(`https://apiv4.iucnredlist.org/api/v4/habitats/species/id/${taxonId}`, { + headers: { + "Authorization": `Bearer ${activeToken.iucnToken}` + } + }); + + return res.json({ + success: true, + data: habitatsResponse.data, + apiVersion: "v4" + }); + } catch (error: any) { + console.log("IUCN API habitats lookup failed:", error.message); + + if (error.response?.status === 401) { + return res.status(401).json({ + success: false, + message: "IUCN API v4 token is invalid. Please check your token and try again." + }); + } + + return res.status(error.response?.status || 500).json({ + success: false, + message: error.response?.data?.message || "Error from IUCN Red List API: " + error.message, + status: error.response?.status + }); } } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); res.status(500).json({ success: false, - message: "Failed to retrieve IUCN habitats data" + message: "Failed to retrieve IUCN habitats data: " + errorMessage }); } }); @@ -626,85 +604,74 @@ export async function registerRoutes(app: Express): Promise { }); } - // To avoid 414 errors, we'll limit the name parameter to just the genus and species + // Extract genus and species for v4 API query const nameParts = String(name).split(' '); - const simplifiedName = nameParts.slice(0, 2).join(' '); const [genusName, speciesName] = nameParts; - // Try with v4 API first if we have a token + // Get IUCN token const activeToken = await storage.getActiveToken(); - if (activeToken?.iucnToken) { - try { - // First, we need to find the species taxon ID using scientific name lookup - const taxaResponse = await axios.get(`${IUCN_V4_BASE_URL}/taxa/scientific_name`, { - headers: { - "Authorization": `Bearer ${activeToken.iucnToken}` - }, - params: { - genus_name: genusName, - species_name: speciesName || "" - } - }); - - // Check if we found the species - if (taxaResponse.data && taxaResponse.data.result && taxaResponse.data.result.length > 0) { - const taxonId = taxaResponse.data.result[0].taxonid; - - // Now retrieve the conservation measures using the taxon ID - const measuresResponse = await axios.get(`${IUCN_V4_BASE_URL}/measures/species/id/${taxonId}`, { - headers: { - "Authorization": `Bearer ${activeToken.iucnToken}` - } - }); - - return res.json({ - success: true, - data: measuresResponse.data, - apiVersion: "v4" - }); - } - // If no species found, fall back to v3 - console.log("IUCN V4 API: No species found with the given scientific name, falling back to V3"); - } catch (error: any) { - console.log("IUCN V4 API conservation measures lookup failed, falling back to V3:", error.message); - // Continue to v3 fallback - } - } - - // Fallback to v3 API - const apiKey = process.env.IUCN_API_KEY; - if (!apiKey) { + if (!activeToken?.iucnToken) { return res.status(401).json({ success: false, - connected: false, - message: "IUCN API key is not configured" + message: "IUCN API v4 token is not configured. Please set your token in the API Token panel." }); } try { - const response = await axios.get(`${IUCN_V3_BASE_URL}/measures/species/name/${encodeURIComponent(simplifiedName)}`, { - params: { token: apiKey } + // First, we need to find the species taxon ID using scientific name lookup + const taxaResponse = await axios.get("https://apiv4.iucnredlist.org/api/v4/taxa/scientific_name", { + headers: { + "Authorization": `Bearer ${activeToken.iucnToken}` + }, + params: { + genus_name: genusName, + species_name: speciesName || "" + } }); - res.json({ - success: true, - data: response.data, - apiVersion: "v3" - }); - } catch (error) { - if (axios.isAxiosError(error) && error.response) { - return res.status(error.response.status).json({ - success: false, - message: error.response.data?.message || "Error from IUCN Red List API", - status: error.response.status + // Check if we found the species + if (!taxaResponse.data?.result || taxaResponse.data.result.length === 0) { + return res.status(404).json({ + success: false, + message: `No species found with the name "${name}" in the IUCN Red List database.` }); } - throw error; + + const taxonId = taxaResponse.data.result[0].taxonid; + + // Now retrieve the conservation measures using the taxon ID + const measuresResponse = await axios.get(`https://apiv4.iucnredlist.org/api/v4/measures/species/id/${taxonId}`, { + headers: { + "Authorization": `Bearer ${activeToken.iucnToken}` + } + }); + + return res.json({ + success: true, + data: measuresResponse.data, + apiVersion: "v4" + }); + } catch (error: any) { + console.log("IUCN API conservation measures lookup failed:", error.message); + + if (error.response?.status === 401) { + return res.status(401).json({ + success: false, + message: "IUCN API v4 token is invalid. Please check your token and try again." + }); + } + + return res.status(error.response?.status || 500).json({ + success: false, + message: error.response?.data?.message || "Error from IUCN Red List API: " + error.message, + status: error.response?.status + }); } } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); res.status(500).json({ success: false, - message: "Failed to retrieve IUCN conservation measures data" + message: "Failed to retrieve IUCN conservation measures data: " + errorMessage }); } });