Refactor: Update IUCN API integration to use v4 API and handle token authentication.
Replit-Commit-Author: Agent Replit-Commit-Session-Id: e931b5ab-041b-42e7-baf1-50017869cef6 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/e19c6a51-7e4c-4bb8-a6a6-46dc00f0ec99/7e887f15-a417-4702-b9ec-027ae572bb88.jpg
This commit is contained in:
327
server/routes.ts
327
server/routes.ts
@ -438,85 +438,74 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
});
|
||||
}
|
||||
|
||||
// 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({
|
||||
// Check if we found the species
|
||||
if (!taxaResponse.data?.result || taxaResponse.data.result.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: error.response.data?.message || "Error from IUCN Red List API",
|
||||
status: error.response.status
|
||||
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<Server> {
|
||||
});
|
||||
}
|
||||
|
||||
// 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({
|
||||
// Check if we found the species
|
||||
if (!taxaResponse.data?.result || taxaResponse.data.result.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: error.response.data?.message || "Error from IUCN Red List API",
|
||||
status: error.response.status
|
||||
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<Server> {
|
||||
});
|
||||
}
|
||||
|
||||
// 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({
|
||||
// Check if we found the species
|
||||
if (!taxaResponse.data?.result || taxaResponse.data.result.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: error.response.data?.message || "Error from IUCN Red List API",
|
||||
status: error.response.status
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user