
Compartilhar:
Ex-representante de desenvolvedores da Vonage, onde sua função era apoiar a comunidade tecnológica local em Londres. Ele é um experiente organizador de eventos, jogador de jogos de tabuleiro e pai de um cachorrinho fofo chamado Moo. Ele também é o principal organizador do You Got This — uma rede de eventos sobre as habilidades essenciais necessárias para uma vida profissional feliz e saudável.
Crie um sistema de votação sem servidor para o Eurovision com Node.js e Vonage
Tempo de leitura: 10 minutos
O Eurovision é um dos meus eventos favoritos do ano. Para quem não sabe, o Eurovision é um concurso de canto que é estranho, maravilhoso e excêntrico em partes iguais. Cada país participante indica um artista para apresentar uma música original — que muitas vezes são ridículas e geniais. Vamos lá, então — dê uma mais links links.
Os países que chegam à final se apresentam ao vivo, e o público dos países participantes vota em sua apresentação favorita (excluindo a do próprio país). Os votos de cada país são contados e, como resultado, cada um atribui 58 pontos: 12 para o primeiro colocado, depois 10 e, finalmente, de 8 a 1. Nos últimos anos, júris profissionais representam metade dos votos de cada país, mas vamos ignorar a existência deles para fins deste projeto.
2019 Eurovision Leaderboard
Sou um grande fã do Eurovision e achei que seria um projeto divertido criar um sistema de votação totalmente funcional usando a Number Insight API da Vonage para validar a origem de um número.
Primeiramente, vamos criar um banco de dados com todos os países participantes. Esse conjunto de dados também indicará quem são os finalistas (com base nos participantes de 2019). Em seguida, vamos processar os votos recebidos por SMS, armazenar os votos válidos e responder usando a Messages API da Vonage. Por fim, criaremos um front-end que nos permitirá obter os resultados por país com um quadro de classificação atualizado. Todo o projeto será hospedado no Netlify, utilizando o Vue.js para nosso front-end minimalista.
Se você quiser apenas ver o código finalizado, pode encontrá-lo em https://github.com/nexmo-community/eurovision-voting-system-js.
Pronto? Vamos lá!
Pré-requisitos
Vamos precisar de algumas contas para que isso funcione. Se ainda não tiver feito isso, crie um Account:
Abra o terminal, crie um novo diretório vazio para este projeto e inicialize um novo projeto digitando npm init -y. Quando terminar, instale as dependências necessárias executando npm install dotenv encoding mongodb netlify-lambda nexmo@beta.
Você também precisará da CLI do Nexmo. Para npm install -g nexmo-cli@beta para instalá-la, acesse seu Account online para obter sua chave e segredo de API e, em seguida, execute nexmo setup <api_key> <api_secret>.
Configurar um banco de dados MongoDB
Usaremos uma instância hospedada do MongoDB no MongoDB Atlas. Faça login na sua conta do MongoDB Atlas e crie um novo projeto com o nome que desejar. Crie um novo cluster (o plano gratuito já é suficiente) — vou chamar o meu de Eurovision— e aguarde até que as alterações sejam implantadas.
Clique no botão “Conectar” no seu novo cluster, adicione seu endereço IP atual e crie um novo usuário do MongoDB com permissão para acessar esse banco de dados (anote a senha).
No painel seguinte, são apresentadas várias opções para se conectar ao seu banco de dados. Escolha Conectar seu aplicativo e copie a URI para a área de transferência.
Criar arquivo .env
Antes de continuarmos, precisamos criar um novo .env arquivo no diretório do projeto para conter todas as nossas strings confidenciais que não queremos que outras pessoas vejam. O conteúdo do arquivo deve ser:
DB_URL=<Mongo DB URI>Substitua <password> pela senha do seu usuário do MongoDB e <dbname> por eurovision.
Criar coleções
Clique nas botão “Coleções” no seu cluster e, em seguida, Adicionar meus próprios dados para criar uma nova coleção. Devemos criar duas:
Nome do banco de dados:
eurovision, nome da coleção:countriesNome do banco de dados:
eurovision, nome da coleção:votes
Permitir acesso de qualquer lugar
Adicionamos nosso próprio endereço IP à lista, o que permite o acesso a esse banco de dados a partir do nosso aplicativo local. No entanto, quando, posteriormente, implantarmos esse projeto, não teremos acesso a endereços IP estáticos. Clique em Acesso à Rede na barra lateral e, em seguida, Adicionar endereço IPe, por fim, Permitir acesso de qualquer lugar. Confirme as alterações para que as restrições sejam removidas.
Preencher com países
Em 2019, houve 42 inscrições no Eurovision, das quais 26 passaram para a final. Como precisamos inserir esses dados apenas uma vez, criei um script para automatizar essa inserção. Crie uma pasta chamada boilerplate, e dentro dela um arquivo chamado addCountries.js. Coloque o seguinte código no arquivo:
// Load environment variables
require('dotenv').config()
// Initialize MongoClient
const { MongoClient } = require('mongodb')
const mongo = new MongoClient(process.env.DB_URL, { useUnifiedTopology: true })
const countriesList = [
{ "iso": "ALB", "name": "Albania", "final": true },
{ "iso": "ARM", "name": "Armenia", "final": false },
{ "iso": "AUS", "name": "Australia", "final": true },
{ "iso": "AUT", "name": "Austria", "final": false },
{ "iso": "AZE", "name": "Azerbaijan", "final": true },
{ "iso": "BLR", "name": "Belarus", "final": true },
{ "iso": "BEL", "name": "Belgium", "final": false },
{ "iso": "HRV", "name": "Croatia", "final": false },
{ "iso": "CYP", "name": "Cyprus", "final": true },
{ "iso": "CZE", "name": "Czech Republic", "final": true },
{ "iso": "DNK", "name": "Denmark", "final": true },
{ "iso": "EST", "name": "Estonia", "final": true },
{ "iso": "FIN", "name": "Finland", "final": false },
{ "iso": "FRA", "name": "France", "final": true },
{ "iso": "DEU", "name": "Germany", "final": true },
{ "iso": "GEO", "name": "Georgia", "final": false },
{ "iso": "GRC", "name": "Greece", "final": true },
{ "iso": "HUN", "name": "Hungary", "final": false },
{ "iso": "ISL", "name": "Iceland", "final": true },
{ "iso": "IRL", "name": "Ireland", "final": false },
{ "iso": "ISR", "name": "Israel", "final": true },
{ "iso": "ITA", "name": "Italy", "final": true },
{ "iso": "LVA", "name": "Latvia", "final": false },
{ "iso": "LTU", "name": "Lithuania", "final": false },
{ "iso": "MKD", "name": "North Macedonia", "final": true },
{ "iso": "MLT", "name": "Malta", "final": true },
{ "iso": "MDA", "name": "Moldova", "final": false },
{ "iso": "MNE", "name": "Montenegro", "final": false },
{ "iso": "NLD", "name": "Netherlands", "final": true },
{ "iso": "NOR", "name": "Norway", "final": true },
{ "iso": "POL", "name": "Poland", "final": false },
{ "iso": "PRT", "name": "Portugal", "final": false },
{ "iso": "ROU", "name": "Romania", "final": false },
{ "iso": "RUS", "name": "Russia", "final": true },
{ "iso": "SMR", "name": "San Marino", "final": true },
{ "iso": "SRB", "name": "Serbia", "final": true },
{ "iso": "SVN", "name": "Slovenia", "final": true },
{ "iso": "ESP", "name": "Spain", "final": true },
{ "iso": "SWE", "name": "Sweden", "final": true },
{ "iso": "CHE", "name": "Switzerland", "final": true },
{ "iso": "UKR", "name": "Ukraine", "final": false },
{ "iso": "GBR", "name": "United Kingdom", "final": true }
]
// Connect to database, and insert all items in the countryList in the countries collection
mongo.connect().then(async () => {
try {
const countries = await mongo.db('eurovision').collection('countries')
const result = await countries.insertMany(countriesList)
console.log(`Added ${result.insertedCount} documents to the collection`)
mongo.close()
} catch(e) {
console.error(e)
}
})
Salve o arquivo, abra o terminal e execute node boilerplate/addCountries.js. Quando terminar, verifique sua coleção no MongoDB Atlas e você deverá ver 42 documentos na coleção “countries”.
Country entries populated in Atlas
Configurar uma função do Netlify
Precisamos criar dois endpoints para a integração com a API da Vonage. O primeiro é um endpoint de status que, para esta aplicação, não requer nenhuma lógica, mas deve retornar um status HTTP 200. Para criar e hospedar esses endpoints, usaremos o Netlify Functions. Antes disso, é necessário realizar algumas configurações.
No seu package.json arquivo, substitua a scripts seção pelo seguinte:
"scripts": {
"netlify:serve": "netlify-lambda serve functions/src",
"netlify:build": "netlify-lambda build functions/src"
},Crie um netlify.toml arquivo no diretório raiz do seu projeto e escreva o seguinte código:
[build]
functions = "./functions/build"Por fim, crie um functions diretório no seu projeto e, dentro dele, crie um src diretório. Todas as nossas funções do Netlify serão criadas nesse diretório.
No novo functions/src diretório, crie um status.js arquivo. Nele, crie a função:
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type'
}
exports.handler = async (event, context) => {
try {
return { headers, statusCode: 200, body: 'ok' }
} catch(e) {
console.error('Error', e)
return { headers, statusCode: 500, body: 'Error: ' + e }
}
}
No terminal, execute npm run netlify:serve. Em outro terminal, teste o novo endpoint executando curl http://localhost:9000/status. O terminal deve exibir uma resposta de ok.
Aceitar mensagens recebidas
Também precisaremos de um endpoint para receber dados quando for enviada uma mensagem para o nosso Número Virtual Longo (LVN). Copie e cole o conteúdo de status.js em um novo arquivo chamado inbound.js.
Criar o ponto de extremidade de entrada
No início do arquivo, inclua o pacote `querystring` (integrado ao Node.js):
const qs = require('querystring');No início do try bloco, adicione o seguinte código:
const { msisdn, to: lvn, text } = qs.parse(event.body)
const vote = text.toUpperCase().trim()
console.log(vote)Reinicie o servidor netlify-lambda, abra um novo terminal e execute npx ngrok http 9000 para criar uma versão acessível ao público do seu servidor netlify-lambda para testes. Anote a URL temporária do ngrok.
Configurar uma aplicação da API da Vonage
No diretório do seu projeto, execute nexmo app:create:
Nome do aplicativo: o que você quiser
Recursos selecionados: mensagens
URL de entrada de mensagens:
<ngrok_url>/inboundURL do status das mensagens:
<ngrok_url>/statusPúblico/Privado: deixe em branco
Essa operação cria um .nexmo-app arquivo no seu diretório. Vamos usá-lo mais tarde, mas não o compartilhe, pois ele contém sua chave privada. Anote o novo ID da aplicação exibido no seu terminal (você também pode encontrá-lo no .nexmo-app arquivo mais tarde).
Em seguida, precisamos adquirir e vincular um LVN a este aplicativo. Execute:
nexmo number:search GB --smsCopie um número e, em seguida, execute:
nexmo number:buy <number>
nexmo link:app <number> <application_id>
nexmo numbers:update <number> --mo_http_url=<ngrok_url>/inboundAgora que o LVN está configurado e encaminhando solicitações para o aplicativo, tente enviar uma mensagem para ele e veja se ela aparece no seu terminal.
Message logged in terminal
Adicione o seguinte à .env para mais tarde:
VONAGE_KEY=<your_api_key>
VONAGE_SECRET=<your_api_secret>
VONAGE_APP=<your_application_id>
VONAGE_PRIVATE_KEY=<your_private_key>Você pode encontrar a chave privada do seu aplicativo no .nexmo_app arquivo.
Armazenar o voto no banco de dados
Logo no início de inbound.js, declare e inicialize MongoClient:
require('dotenv').config()
const { MongoClient } = require('mongodb')
const mongo = new MongoClient(process.env.DB_URL, { useUnifiedTopology: true })Abaixo da console.log(vote) instrução, conecte-se ao banco de dados e insira uma nova entrada na coleção para testar se está funcionando:
await mongo.connect()
const votes = await mongo.db('eurovision').collection('votes')
const countries = await mongo.db('eurovision').collection('countries')
await votes.insertOne({ msisdn, lvn, vote })Aguarde até que seu servidor netlify-lambda reinicie automaticamente e envie outra mensagem para o seu LVN. Se você verificar sua coleção de votos no Atlas, um novo documento deverá aparecer.
Obtenha insights sobre números
A Number Insight API da Vonage, ao receber um número de telefone (MSISDN), fornece informações sobre ele. Existem três níveis: básico, padrão e avançado. Para esta aplicação, queremos saber o país de origem de um número, informação que é retornada como parte de uma consulta básica.
Logo acima de onde o headers são definidas, inclua o `require` e inicialize a biblioteca do cliente do Nexmo Node:
const Nexmo = require('nexmo')
const nexmo = new Nexmo({
apiKey: process.env.VONAGE_KEY,
apiSecret: process.env.VONAGE_SECRET,
applicationId: process.env.VONAGE_APP,
privateKey: Buffer.from(process.env.VONAGE_PRIVATE_KEY.replace(/\\n/g, "\n"), 'utf-8')
})Observação: precisamos criar um Buffer e substituir \n para que este aplicativo funcione depois de hospedado no Netlify. Em aplicativos não hospedados no Netlify, você pode fornecer isso diretamente como process.env.VONAGE_PRIVATE_KEY.
No final do arquivo, crie uma nova função para obter o código do país a partir de um número:
function getCountryCodeFromNumber(number) {
return new Promise((resolve, reject) => {
nexmo.numberInsight.get({level: 'basic', number}, async (err, res) => {
if(err) reject(err)
else resolve(res.country_code_iso3)
})
})
}
Existem outras informações que a Number Insight API irá retornar. Para esta aplicação, precisamos apenas do código ISO de 3 dígitos associado ao número de telefone. Esse código ISO também está armazenado para cada país participante em nossa countries coleção.
Acima da votes.insertOne() declaração, acrescente:
const votersCountry = await getCountryCodeFromNumber(msisdn)
console.log(votersCountry)Envie outra mensagem para o seu LVN. O código do país deve estar registrado no terminal.
Enviar uma resposta ao usuário
Quando recebermos uma mensagem, devemos responder ao usuário e informá-lo. Na parte inferior do seu aplicativo, adicione uma função para fazer isso:
function sendMessage(sender, recipient, text) {
return new Promise((resolve, reject) => {
const to = { type: 'sms', number: recipient }
const from = { type: 'sms', number: sender }
const message = { content: { type: 'text', text } }
nexmo.channel.send(to, from, message, (err, res) => {
if(err) reject(err)
resolve({ headers, statusCode: 200, body: 'ok' })
})
})
}
Agora podemos usar a função para enviar uma mensagem aos usuários e, em seguida, retornar seu valor diretamente. Substitua a return instrução no try {} bloco pela nossa nova chamada de função:
return await sendMessage(lvn, msisdn, 'Thank you for voting!')Envie uma mensagem para o seu LVN e você deverá receber uma resposta.
Verificar se o voto é válido
Não queremos armazenar todos os votos que nos são enviados. Existem algumas verificações necessárias para que um voto seja válido. Abaixo da votersCountry variável, crie as verificações:
const existingVote = await votes.findOne({ msisdn: msisdn })
const countryInFinal = await countries.findOne({ iso: vote, final: true })
const votersCountryCanVote = await countries.findOne({ iso: votersCountry })
if(existingVote) {
return await sendMessage(lvn, msisdn, 'You have already voted')
}
if(!countryInFinal) {
return await sendMessage(lvn, msisdn, 'That country is not in the final, or your message is not a valid country code.')
}
if(!votersCountryCanVote) {
return await sendMessage(lvn, msisdn, 'Your number is not from a participating country')
}
if(votersCountry == vote) {
return await sendMessage(lvn, msisdn, 'You cannot vote for your own country')
}Altere o objeto dentro de votes.insertOne() para incluir as informações que queremos armazenar:
votes.insertOne({ msisdn, vote, votersCountry })Como há instruções `return` nas instruções `if`, o voto só será inserido se nenhuma das condições for atendida, o que significa que ele é válido.
Preencher com votos
Nosso sistema de votação já está pronto. No entanto, para criar endpoints de resultados, precisaremos de milhares de votos. Assim como antes, aqui está um script que adicionará 20 mil votos. Adicione este código a um novo addVotes.js arquivo no diretório boilerplate:
require('dotenv').config()
const { MongoClient } = require('mongodb')
const mongo = new MongoClient(process.env.DB_URL, { useUnifiedTopology: true })
mongo.connect().then(async () => {
try {
const countries = await mongo.db('eurovision').collection('countries')
const votes = await mongo.db('eurovision').collection('votes')
const list = await countries.find().toArray()
const votesList = []
for(let i=0; i<20000; i++) {
const { iso: votersCountry } = list[Math.floor(Math.random() * list.length)]
const availableCountries = list.filter(c => c != votersCountry && c.final)
const { iso: vote } = availableCountries[Math.floor(Math.random() * availableCountries.length)]
votesList.push({
msisdn: String(Math.ceil(Math.random() * 100000)),
votersCountry, vote
})
}
const result = await votes.insertMany(votesList)
console.log(`Added ${result.insertedCount} documents to the collection`)
mongo.close()
} catch(e) {
console.error(e)
}
})
Exclua os documentos existentes e, em seguida, execute este script 5 ou 6 vezes. Seu banco de dados do MongoDB Atlas deve agora conter uma grande quantidade de votos de exemplo.
12000 records in the votes collection
Criar pontos de extremidade para o front-end
Existem alguns componentes em nosso front-end — precisamos de um endpoint para retornar os países que preencherão o menu suspenso e de um endpoint para retornar as pontuações de um determinado país.
Completed dashboard
Obter a lista de países
Crie um novo arquivo em /functions/src/countries.js:
require('dotenv').config()
const { MongoClient } = require('mongodb')
const mongo = new MongoClient(process.env.DB_URL, { useUnifiedTopology: true })
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Content-Type'
}
exports.handler = async (event, context) => {
try {
await mongo.connect()
const countries = await mongo.db('eurovision').collection('countries')
const list = await countries.find().toArray()
return { headers, statusCode: 200, body: JSON.stringify(list) }
} catch(e) {
console.error('Error', e)
return { headers, statusCode: 500, body: 'Error: ' + e }
}
}
Reinicie seu servidor netlify-lambda e, em seguida, teste executando curl http://localhost:9000/countries.
Obtenha resultados
Este endpoint aceitará um parâmetro de consulta de ?country=CODE. Copie e cole o código do endpoint “countries” em um novo arquivo chamado results.js. Substitua o conteúdo do try {} bloco pelo seguinte:
await mongo.connect()
const countries = await mongo.db('eurovision').collection('countries')
const votes = await mongo.db('eurovision').collection('votes')
const { country } = event.queryStringParameters
const topTen = await votes.aggregate([
{ $match: { votersCountry: country } },
{ $group: { _id: '$vote', votes: { $sum: 1 } } },
{ $sort: { votes: -1 } },
{ $limit: 10 }
]).toArray()
const points = [ 12, 10, 8, 7, 6, 5, 4, 3, 2, 1 ]
const list = await countries.find().toArray()
const results = topTen.map((votes, i) => {
const countryRecord = list.find(c => c.iso == votes._id)
return {
...votes,
points: points[i],
country: countryRecord.name
}
})
return { headers, statusCode: 200, body: JSON.stringify(results) }
A topTen variável utiliza uma agregação do MongoDB para retornar as 10 primeiras entradas, conforme votadas pelo país fornecido. Em seguida, adicionamos um valor de pontos a cada uma das entradas com o valor de pontos fornecido na points array.
Reinicie o servidor e execute curl http://localhost:9000/results?country=GBR para testar.
Front-end do Scaffold
Crie um novo arquivo na raiz do projeto chamado index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Eurovision Results Pane</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app">
<div id="leaderboard">
<h1>Leaderboard</h1>
<div class="list">
<div class="country" v-for="country in leaderboard">
<span class="name">{{country.name}}</span>
<span class="score">{{country.score}}</span>
</div>
</div>
</div>
<div id="admin">
<h1>Get Results</h1>
<form>
<select v-model="toReveal">
<option disabled value="">Select country</option>
<option v-for="country in leftToReveal" :value="country.iso">{{country.name}}</option>
</select>
<input type="submit" @click.prevent="getScores" value="Get Scores">
</form>
<div id="results">
<h2>{{resultsCountry}}</h2>
<div class="result" v-for="result in results">
<span class="name">{{result.country}}</span>
<span class="points">+{{result.points}}</span>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="client.js"></script>
</body>
</html>
Crie um style.css arquivo na raiz do projeto:
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;900&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #050636;
font-family: 'Montserrat', sans-serif;
}
#app {
display: grid;
grid-template-columns: auto 350px;
grid-gap: 1em;
padding: 1em;
}
#leaderboard {
background: white;
color: #050636;
padding: 1em 1em 0;
}
.list {
columns: 2;
column-gap: 1em;
margin-top: 1em;
}
.country,
.result {
padding: 0.5em;
background: #f0f0f0;
margin-bottom: 1em;
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-between;
font-size: 1.25em;
align-items: center;
}
.score {
font-size: 1.25em;
font-weight: bold;
}
#admin {
background: #2a2b87;
color: white;
padding: 1em;
}
form {
display: grid;
grid-template-columns: 225px auto;
grid-gap: 1em;
}
form {
margin: 1em 0;
}
.result {
background: #4c4eb3;
margin-top: 0.5em;
}Crie um client.js arquivo na raiz do projeto:
const app = new Vue({
el: '#app',
async created() {
const countryResp = await fetch(this.baseURL + '/countries');
const countries = await countryResp.json();
this.countries = countries.map(country => {
return { ...country, results: false, score: 0 }
})
},
data: {
countries: [],
toReveal: undefined,
results: undefined,
resultsCountry: undefined
},
computed: {
leaderboard() {
return this.countries.filter(c => c.final).sort((a, b) => b.score - a.score)
},
leftToReveal() {
return this.countries.filter(c => !c.results)
},
baseURL() {
return "http://localhost:9000"
},
toRevealCountry() {
const country = this.countries.find(c => c.iso == this.toReveal)
return country.name
}
},
methods: {
async getScores() {
// Get results
const resultsResp = await fetch(this.baseURL + '/results?country=' + this.toReveal);
this.results = await resultsResp.json();
// Assign points to countries
for(let result of this.results) {
const country = this.countries.find(c => c.iso == result._id)
country.score += result.points
}
// Remove item from results select
const votingCountry = this.countries.find(c => c.iso == this.toReveal)
votingCountry.results = true
// Show country name in results pane
this.resultsCountry = votingCountry.name
}
}
})
Alguns pontos importantes a serem observados:
Nesse
created()adicionamos duas propriedades a cada país — uma pontuação inicial de 0 e umaresultspropriedade que definimos como “true” assim que obtivermos os resultados para esse país.A
leftToRevealpropriedade calculada inclui apenas os países queresultsdefinido comotrue, para que não possamos contar acidentalmente um país duas vezes.
Manter os resultados entre as atualizações
Este é um sistema bastante bom e bastante robusto. Um ponto em que podemos melhorá-lo é a persistência das pontuações entre as atualizações (caso isso ocorra durante a exibição dos resultados).
No final do getScores() método, adicione os countries dados ao localStorage:
localStorage.setItem('countries', JSON.stringify(this.countries))Atualização created() para buscar apenas dados atualizados sobre os países caso não tenhamos nenhum no localStorage:
async created() {
if(localStorage.getItem('countries')) {
this.countries = JSON.parse(localStorage.getItem('countries'))
} else {
const countryResp = await fetch(this.baseURL + '/countries');
const countries = await countryResp.json();
this.countries = countries.map(country => {
return { ...country, results: false, score: 0 }
})
}
},
Hospedar no Netlify
Crie um novo arquivo na raiz do seu projeto chamado.gitignore. Os arquivos e diretórios listados nesse arquivo não serão incluídos no repositório do Git. Seu arquivo deve ficar assim:
node_modules
functions/build
.env
.nexmo-appEnvie este repositório para o GitHub e, em seguida, faça login na sua conta do Netlify. Clique em “Novo site a partir do Git”, selecione o repositório e, nas Configurações básicas de compilação , o comando de compilação deve ser npm run netlify:build. Nas Configurações avançadas de compilação , adicione cada item do seu .env arquivo.
Após a implantação, há duas alterações que você precisará fazer:
Atualize as URLs no seu aplicativo da API da Vonage para
<netlify_url>/.netlify/functions/status(ou/inbound).Em
client.jsatualize seubaseURLmétodo da seguinte forma:
baseURL() {
if(location.hostname == 'localhost' || location.hostname == "127.0.0.1") {
return "http://localhost:9000"
} else {
return "<netlify_url>/.netlify/functions"
}
},Envie um novo commit e seu site do Netlify será reimplantado automaticamente.
Conclusão e próximos passos
Existem vários componentes envolvidos neste aplicativo. No entanto, cada um deles desempenha seu papel para criar um sistema de votação do Eurovision que realmente funcione.
É possível obter vários LVNs de diferentes países usando a CLI do Nexmo ou pelo painel de controle da web. Os usuários continuarão podendo votar apenas uma vez, independentemente do LVN para o qual enviem a mensagem. Uma melhoria que você talvez queira implementar é fechar a janela de votação para que todos os países tenham o mesmo período para votar.
Você pode encontrar o projeto final em https://github.com/nexmo-community/eurovision-voting-system-js
Como sempre, se precisar de ajuda, sinta-se à vontade para entrar em contato na Slack da Comunidade de Desenvolvedores da Vonage. Esperamos vê-lo por lá.
Islândia A Islândia, aliás, teve a melhor participação em 2020.
Compartilhar:
Ex-representante de desenvolvedores da Vonage, onde sua função era apoiar a comunidade tecnológica local em Londres. Ele é um experiente organizador de eventos, jogador de jogos de tabuleiro e pai de um cachorrinho fofo chamado Moo. Ele também é o principal organizador do You Got This — uma rede de eventos sobre as habilidades essenciais necessárias para uma vida profissional feliz e saudável.