const debug = require('debug')('soundbirder:api'); const debugResponses = require('debug')('soundbirder:api:responses'); require('dotenv').config(); const axios = require('axios'); 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 OPENCAGE_API_KEY = process.env.OPENCAGE_API_KEY; const OPENCAGE_API_URL = 'https://api.opencagedata.com/geocode/v1/json?q=+&key='; const QUIZZ_SIZE = process.env.QUIZZ_SIZE ? process.env.QUIZZ_SIZE : 5; function check(req, res) { } function quizz(req, res) { debug('Generating quizz'); const { lat, lng } = req.body; generateQuizz({ lat, lng }, req.locale) .then(({ species, correct, audio }) => { req.session.correct = correct; res.json({ species, audio }); debug("Quizz sent"); }) .catch(error => { debug("Faced error while generating quizz"); res.json({ error }); throw error; }); } async function generateQuizz(coordinates, locale) { const quizz = {} try { const speciesSelection = await getSpeciesSelection(coordinates); const speciesSelectionLocalized = await getLocalizedNames(speciesSelection, locale); quizz.species = await speciesSelectionLocalized; debug("Got species selection", quizz.species); const answer = await choice(speciesSelectionLocalized); debug("Got answer", answer); quizz.correct = answer.code; quizz.audio = await getAudio(answer.sciName); } catch (error) { debug("Error raised while generating quizz"); console.error(error); } return quizz; } async function getSpeciesSelection(coordinates) { const { lat, lng } = coordinates; const region = await getRegion(lat, lng); region.country_code = region.country_code.toUpperCase(); // const regionCode = await getRegionCode(region); const regionCode = region.country_code; const speciesList = await getSpeciesList(regionCode); const speciesSelection = choices(speciesList, QUIZZ_SIZE); debug("Species proposals:", speciesSelection) return speciesSelection; } function getHome(req, res) { res.render('api', { title: "SoundBirder api", version: 0 } ); } function getRegion(lat, lon) { const url = OPENCAGE_API_URL .replace('', lat) .replace('', lon) .replace('', OPENCAGE_API_KEY); return axios.get(url).then(response => { const { results } = response.data; const { country_code, country, state, county } = results[0].components; return { country_code, country, state, county }; }).catch(error => { throw error; }); } function getRegionCode({ country_code, country, state, county }) { return eBird.ref.region.list('subnational1', country_code)() .then(states => { console.log(states); const regionCode = states.find(region => region.name === state).code; return regionCode; }).catch(error => { throw error; }); } async function getLocalizedNames(speciesCodes, locale) { let names = []; for (let i = 0; i < speciesCodes.length; i++) { const code = speciesCodes[i]; const { sciName, comName } = await getLocalizedName(code, locale); names.push({ code, sciName, comName }); } return names; } 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; }); } function getSpeciesList(regionCode) { return eBird.product.spplist.in(regionCode)() .then(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; }); } const game = { check, quizz } module.exports = { getHome, game }