120 lines
3.8 KiB
JavaScript
120 lines
3.8 KiB
JavaScript
require('dotenv').config();
|
|
const debug = require('debug')('soundbirder:api:quizz');
|
|
const debugResponses = require('debug')('soundbirder:api:responses');
|
|
const cache = require('./cache');
|
|
const eBird = require('@unclesamulus/ebird-api')(process.env.EBIRD_API_KEY);
|
|
const XenoCanto = require('@unclesamulus/xeno-canto-api');
|
|
const { choices, choice } = require('../utils/choices');
|
|
const { getRegion } = require('./region');
|
|
|
|
async function generateQuizz(coordinates, locale, size) {
|
|
const quizz = {}
|
|
try {
|
|
const speciesSelection = await getSpeciesSelection(coordinates, size);
|
|
debugResponses(`Species selection: ${speciesSelection}`);
|
|
const speciesSelectionLocalized = await getLocalizedNames(speciesSelection, locale);
|
|
debugResponses('Localized species selection:', speciesSelectionLocalized);
|
|
quizz.species = speciesSelectionLocalized;
|
|
debug("Got species selection", quizz.species);
|
|
const answer = await choice(speciesSelectionLocalized);
|
|
debug("Got answer", answer);
|
|
quizz.correct = answer.speciesCode;
|
|
quizz.audio = await getAudio(answer.sciName);
|
|
debug("Got audio", quizz.audio);
|
|
} catch (error) {
|
|
debug("Error raised while generating quizz");
|
|
console.error(error);
|
|
}
|
|
return quizz;
|
|
}
|
|
|
|
async function getSpeciesSelection(coordinates, number) {
|
|
const { lat, lng } = coordinates;
|
|
const region = await getRegion(lat, lng);
|
|
// const regionCode = await getRegionCode(region);
|
|
const regionCode = region.country_code;
|
|
const speciesList = await getSpeciesList(regionCode);
|
|
const speciesSelection = choices(speciesList, number);
|
|
debug("Species proposals:", speciesSelection)
|
|
return speciesSelection;
|
|
}
|
|
|
|
|
|
async function getLocalizedNames(speciesCodes, locale) {
|
|
let allNames = [];
|
|
for (let i = 0; i < speciesCodes.length; i++) {
|
|
const code = speciesCodes[i];
|
|
let flag = false;
|
|
try {
|
|
names = await cache.getCached(`${code}-${locale}`);
|
|
if (names) {
|
|
allNames.push(names);
|
|
flag = true;
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
if (!flag) {
|
|
try {
|
|
const names = { speciesCode, sciName, comName } = await getLocalizedName(code, locale);
|
|
cache.cacheResponse(`${code}-${locale}`, names);
|
|
allNames.push(names);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
}
|
|
return allNames;
|
|
}
|
|
|
|
function getLocalizedName(speciesCode, locale) {
|
|
return eBird.ref.taxonomy.ebird({
|
|
fmt: 'json',
|
|
locale: locale,
|
|
species: speciesCode
|
|
}).then(
|
|
response => {
|
|
const names = response[0];
|
|
debug("Got localized species names");
|
|
debugResponses(names);
|
|
return names;
|
|
}
|
|
).catch(error => {
|
|
throw error;
|
|
});
|
|
}
|
|
|
|
async function getSpeciesList(regionCode) {
|
|
const cached = await cache.getCached(`spplist-${regionCode}`);
|
|
if (cached) {
|
|
return cached;
|
|
} else {
|
|
return eBird.product.spplist.in(regionCode)()
|
|
.then(species => {
|
|
cache.cacheResponse(`spplist-${regionCode}`, species);
|
|
return species;
|
|
})
|
|
.catch(error => {
|
|
throw error;
|
|
});
|
|
}
|
|
}
|
|
|
|
function getAudio(speciesScientificName) {
|
|
return XenoCanto.search({
|
|
name: speciesScientificName,
|
|
quality: 'A'
|
|
}).then(response => {
|
|
debugResponses(response);
|
|
const { recordings } = response;
|
|
const randomRecord = choice(recordings);
|
|
const audio = randomRecord.file;
|
|
return audio;
|
|
}).catch(error => {
|
|
throw error;
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
generateQuizz
|
|
} |