https://a.storyblok.com/f/270183/84356/5c12ecc708/twitter-positivity-score_1200x675.jpg

Descubra o seu Índice de Positividade no Twitter com o React

Publicado em April 26, 2021

Tempo de leitura: 16 minutos

Em 2019, propus a mim mesma o desafio de espalhar positividade e gentileza no meu dia a dia.

Mas logo percebi que essa meta parecia um pouco vaga e bastante indefinida. Embora tivesse boas intenções, achei difícil avaliar seu sucesso ou impacto.

Então, durante alguns meses, refleti sobre como poderia medir minha meta e tive a sorte de descobrir que a API de Análise de Texto oferece uma maneira de acompanhar meu compromisso com a positividade!

A equipe do Azure disponibilizou seus algoritmos de aprendizado de máquina como código aberto, o que significa que posso analisar a pontuação de sentimento de qualquer texto em uma escala numérica de 0 a 1 (sendo 0 negativo e 1 positivo).

Isso significa que posso avaliar a forma como me expresso e verificar se realmente tenho espalhado gentileza e positividade, especialmente nas minhas postagens nas redes sociais!

Então, pensei em criar um aplicativo em React que utilize a API do Twitter para buscar meu tweet mais recente e analisar seu sentimento, para depois usar Messages API da Nexmo para enviar um relatório para mim mesmo!

Dá uma olhada:

Pré-requisitos

Para seguir este tutorial, você precisará de um Account na Vonage. Você pode se cadastrar agora para grátis , caso ainda não tenha um Account.

Além disso, você também precisará de:

Como descobrir sua pontuação de positividade no Twitter com o React

Você vai realizar as seguintes tarefas para criar seu aplicativo:

  1. Criar um servidor de back-end com o Express

  2. Crie um aplicativo front-end com React

  3. Crie um componente React para receber um nome de usuário do Twitter

  4. Recuperar o tweet mais recente com a API do Twitter

  5. Calcular a pontuação de sentimento com a API do Microsoft Azure

  6. Envie esse relatório para o seu celular usando a Messages API da Nexmo

Este tutorial vai guiá-lo pelo processo desde o início. No entanto, se você quiser ver o código final, pode clonar o repositório Git deste projeto.

Criar um servidor de back-end com o Express

Para começar, no diretório raiz deste projeto, execute:

npm init -y

Isso cria um package.json arquivo, permitindo que você comece a instalação com apenas algumas dependências.
Para fazer isso, execute:

npm install unirest express concurrently dotenv twitter nexmo@beta && npm install nodemon --save-dev

Para que você possa executar seu servidor e seu cliente usando um único comando npm run dev, abra seu package.json arquivo e altere os scripts para que fiquem assim:

// package.json
  "scripts": {
      "start": "node server.js",
      "server": "nodemon server.js",
      "client": "npm start --prefix client",
      "dev": "concurrently \"npm run server\" \"npm run client\""
    },

Em seguida, crie mais três arquivos na raiz do seu diretório:.env, server.js e private.key:

touch .env server.js private.key

Preencha seu .env arquivo com as credenciais do Nexmo e do Twitter. Deve ficar assim:

# .env

# Nexmo's credentials
API_KEY=*****
API_SECRET=*********
APPLICATION_ID=**********
NEXMO_NUMBER=***********
# Twitter's credentials
CONSUMER_KEY=*******
CONSUMER_SECRET=*******
ACCESS_TOKEN_KEY=**************
ACCESS_TOKEN_SECRET=*************

Para inserir a chave e o segredo da API, acesse a página da Nexmo página “Introdução” do seu Painel de Controle. E você pode obter o ID da aplicação e a chave privada na seção página “Criar um aplicativo” .
Ao criar o aplicativo, você tem a opção de vinculá-lo ao seu número de telefone da Nexmo. Certifique-se de copiar e colar esse número de telefone e inseri-lo no seu .env arquivo como NEXMO_NUMBER.

Certifique-se também de gerar um par de chaves pública/privada. Colei a chave diretamente no private.key arquivo.

Para preencher as chaves de consumidor e de acesso, bem como os segredos, crie um aplicativo no Twitter e gere as chaves e os tokens.

Agora, no seu server.js arquivo, vamos inicializar nosso aplicativo Express e incluir alguns pré-requisitos:

//  server.js  
const dotenv = require('dotenv');
const express = require('express');
const bodyParser = require('body-parser');
const Nexmo = require('nexmo');
const Twitter = require('twitter');

dotenv.config();
const app = express();
app.use(bodyParser.json());

const port = 5000;

app.listen(port, () => console.log(`server started on port ${port}`));

Adicione também as diferentes credenciais necessárias para utilizar as APIs do Nexmo e do Twitter:

//  server.js  continued:

// Nexmo credentials
const nexmo = new Nexmo({
  apiKey: process.env.API_KEY,
  apiSecret: process.env.API_SECRET,
  applicationId: process.env.APPLICATION_ID,
  privateKey: './private.key'
}, {debug: true});

// Twitter credentials
const client = new Twitter({
  consumer_key: process.env.CONSUMER_KEY,
  consumer_secret: process.env.CONSUMER_SECRET,
  access_token_key: process.env.ACCESS_TOKEN_KEY,
  access_token_secret: process.env.ACCESS_TOKEN_SECRET
});

No final deste server.js arquivo, adicione as duas assinaturas dos endpoints aos quais voltaremos daqui a pouco para escrever:

//  server.js  continued:
app.post('/userName', function(req, res) {});
app.post('/sendSMS', function(req, res) {});

Crie um aplicativo front-end com React

Em seguida, ainda na raiz do seu diretório, crie seu aplicativo React executando o seguinte comando:

npx create-react-app client

Eu dei o nome de client , mas fique à vontade para dar o nome que quiser. Depois que o aplicativo React estiver criado, acesse-o e inicie-o para verificar se tudo funcionou corretamente durante o processo de instalação:

cd client && npm start

Para que você possa executar ambas as portas simultaneamente, no arquivo client/package.json arquivo, adicione:

// package.json
 "proxy": "http://localhost:5000",

Ao executar o create-react-app fornece uma série de códigos padrão. Dentro da src/ pasta há um App.js arquivo. Nesse arquivo, adicionei uma chamada a um <TwitterName /> componente que vamos desenvolver a seguir.
Meu App.js arquivo tem a seguinte aparência:

// client/src/App.js
import React from 'react';
import TwitterName from './components/twitterName';

class App extends React.Component {
  render() {
    return (
      <div>
        <TwitterName />
      </div>
    );
  }
}

export default App;

A seguir, vamos criar uma components pasta dentro de src/:

cd src && mkdir components

Nessa pasta, crie três arquivos:

touch twitterName.js sentimentCalculate.js phoneNumber.js

Criar um componente para receber um nome de usuário do Twitter

Dentro de twitterName.js junto com meu código padrão, vamos criar duas funções senduserName() e getTweet():

// client/src/components/twitterName.js

import React from 'react';
import SentimentCalculate from './sentimentCalculate';

class TwitterName extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      userName: '',
      tweetContent: '',
    };
  }
  senduserName();
  getTweet();
  render();
}

export default TwitterName;

Adicione ao render() adicionar um <input /> para receber e armazenar o nome de usuário do Twitter como estado fornecido pelo usuário.

// client/src/components/twitterName.js

 render() {
    return (
      <div>
      <label>
        Enter a Twitter Handle and find the most recent tweet:
        <input
          placeholder="twitter name"
          type="text"
          value={this.state.userName}
          onChange={(e) => this.setState({ userName: e.target.value})}
        />
      </label>
        <button onClick={this.senduserName}>
          find most recent tweet
        </button>
      </div>
    )
  }

O senduserName() é chamada assim que o usuário digita seu nome de usuário e clica no find most recent tweet botão. Essa função envia informações para o server.js back-end e tem a seguinte aparência:

//client/src/components/ twitterName.js

senduserName = (event) => {
    event.preventDefault();
    fetch('/userName', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({userName: this.state.userName})
    })
    this.getTweet()
  }

Essa função, então, chama a getTweet() função que tem a seguinte aparência:

// client/src/components/twitterName.js

  getTweet = (event) => {
    fetch('/twitter')
    .then(res => res.json())
    .then(tweetContent => this.setState({tweetContent}, () => console.log('tweet fetched: ', tweetContent)))
  }

Essa função recebe os dados do servidor e, em seguida, exibe o tweet mais recente em nossa página do React.

A única coisa que resta fazer nesta página agora é chamar o próximo componente, <SentimentCalculate /> e, portanto, na parte inferior do render() adicionamos isso e passamos o estado (tweetContent e userName) para esse componente:

// client/src/components/twitterName.js
  render() {
    return (
      <div>
        <input
          placeholder="twitter name"
          type="text"
          value={this.state.userName}
          onChange={(e) => this.setState({ userName: e.target.value})}
        />
        <button onClick={this.senduserName}>
          find most recent tweet
        </button>

        <SentimentCalculate tweetContent={this.state.tweetContent} userName={this.state.userName} />
      </div>
    )
  }

Recuperar o tweet mais recente com a API do Twitter

Vamos voltar ao server.js arquivo na raiz do nosso projeto e preencher a app.post('/userName'); função:

//server.js

// Receive input and call Twitter API
app.post('/userName', function(req, res) {
  userName = req.body.userName;
  app.get('/twitter', (req, res) => {
    // read most recent tweet
    var username = {screen_name: userName };
    client.get('statuses/user_timeline', username, function(error, tweets, response) {
      if (!error) {
        console.log(`most recent tweet: `, tweets[0].text);
        res.json(tweets[0].text)
      }
    });
  });
});

Aqui, o userName é passado pelo cliente e, em seguida, enviado para a API do Twitter. O tweet mais recente é então enviado de volta ao cliente para ser exibido em nosso código React.

Calcule a pontuação de sentimento com a API do Microsoft Azure

Vamos expandir nosso sentimentCalculate.js arquivo agora com duas funções diferentes calculateSentiment() e showTweet():

//client/src/components/sentimentCalculate.js

import React from 'react';
import unirest from 'unirest';
import PhoneNumber from './phoneNumber';
require('dotenv').config()

class SentimentCalculate extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      tweetContent: props.tweetContent,
      userName: props.userName,
      score: ''
    };
  }
  calculateSentiment();
  showTweet();
  render();
}
export default SentimentCalculate;

Observe que estou inicializando o estado e carregando no tweetContent e userName como props do <TwitterName /> componente.

A showTweet() função será bem simples e exibirá o tweet, caso ele exista. Ela também mostrará um botão para chamar a calculateSentiment() função:

//client/src/components/sentimentCalculate.js
  showTweet() {
    if (this.props.tweetContent) {
      return (
        <div>
          {this.props.tweetContent}
          <button onClick={this.calculateSentiment}>
            Calculate sentiment score
          </button>
        </div>
      )
    }
  }

Essa calculateSentiment() função ficará assim:

//client/src/components/sentimentCalculate.js

  calculateSentiment = (event) => {
    console.log("calculating sentiment for: ", this.props.tweetContent)
    event.preventDefault();
    unirest.post("https://microsoft-azure-text-analytics-v1.p.rapidapi.com/sentiment")
    .header("X-RapidAPI-Host", "microsoft-azure-text-analytics-v1.p.rapidapi.com")
    .header("X-RapidAPI-Key", process.env.REACT_APP_RAPIDAPI_KEY)
    .header("Content-Type", "application/json")
    .send({"documents":[{"language":"en","id":"string","text":this.props.tweetContent}]})
    .end((result) => {
      const newScore = result.body.documents[0].score
      console.log("The score is:", newScore)
      this.setState({ score: newScore })
    });
  }

Essa função chama o Text Analytics do Microsoft Azure por meio da Rapid API. Gosto de usar a Rapid API, pois ela me permite conectar-me a várias APIs diferentes com um único login.
Guardo a chave em um .env arquivo na client pasta. Portanto, certifique-se de criar um novo .env arquivo para proteger suas credenciais também:

# client/.env REACT_APP_RAPIDAPI_KEY=********

A calculateSentiment() função envia o tweetContent para a API e retorna uma pontuação.
Adicione à render() função um local para exibir esse novo estado:

//client/src/components/sentimentCalculate.js

  render() {
    return (
      <div>
        {this.showTweet()}
        {this.state.score && `Tweet's sentiment score: ${this.state.score}`}
        <PhoneNumber score={this.state.score} tweetContent={this.props.tweetContent} userName={this.props.userName} />
      </div>
    )
  }

Observe que, abaixo da partitura, o componente final se chama: <PhoneNumber />. Certifique-se também de passar o estado por meio de props para esse componente.

Envie seu Relatório de Sentimento de SMS com a Messages API da Nexmo

Vamos criar nosso phoneNumber.js arquivo agora com as funções sendSMS(), renderPhoneInput(), e renderSendButton() para implementar a funcionalidade de envio de nossa mensagem SMS por meio da Messages API do Nexmo:

//client/src/components/phoneNumber.js  

import React from 'react';

class PhoneNumber extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      score: props.score,
      tweetContent: props.tweetContent,
      userName: props.userName,
      number: ''
    };
    this.sendSMS = this.sendSMS.bind(this);
  }
  sendSMS();
  renderPhoneInput();
  renderSendButton();
  render() {
    return (
      <div>
        {this.renderPhoneInput()}
        {this.renderSendButton()}
      </div>
    )
  }

}
export default PhoneNumber;

O primeiro método chamado é renderPhoneInput(). Vamos desenvolvê-lo agora:

//client/src/components/phoneNumber.js  

  renderPhoneInput() {
    if (this.props.score) {
      return (
        <div>
          Phone number:
          <input
            placeholder="18005554444"
            type="tel"
            value={this.state.number}
            onChange={(e) => this.setState({ number: e.target.value})}
          />
        </div>
      );
    }
  }

Se o componente tiver recebido uma pontuação do componente anterior, esta função exibirá um campo de entrada para que o usuário forneça seu número de telefone, a fim de enviar o relatório de análise de sentimento. Assim que o usuário fornecer um número válido, a renderSendButton() função será ativada:

//client/src/components/phoneNumber.js  

  renderSendButton() {
    if (this.state.number && this.state.number.match(/\d/g).length===11) {
        return (
          <div>
            <button onClick={this.sendSMS}>
            Send the tweet’s score to my phone
            </button>
          </div>
        );
      }
  }

Esse botão, então, chama a função final, sendSMS(), que tem a seguinte aparência:

//client/src/components/phoneNumber.js  

  sendSMS() {
    fetch('/sendSMS', {
      method: 'post',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        number: this.state.number,
        score: this.props.score,
        tweetContent: this.props.tweetContent,
        userName: this.props.userName
      })
    })
   .then(res => {
      alert('Your text was successfully sent!')
    })
    .catch(function(error){ console.log(error)});
  }

Essa função envia todas as informações que coletamos do usuário para o servidor. E, por fim, avisa o usuário assim que a função for concluída com sucesso.

Nosso último passo é voltar para o server.js e escrever a app.post('/sendSMS') função:

//server.js  

// send SMS via Nexmo
app.post('/sendSMS', (req, res) => {
  res.send(req.body);
  let score = req.body.score;
  let scoreSign = '';

  // analyze the sentiment and assign emoji
  if (score > '.5') {
    scoreSign = '✅'
  } else if (score == '.5') {
    scoreSign = '😐'
  } else {
    scoreSign = '👿'
  }

  //  Nexmo Messages API
  nexmo.channel.send(
    { type: 'sms', number: req.body.number }, // To
    { type: 'sms', number: process.env.NEXMO_NUMBER }, // From
    {
      content: {
        type: 'text',
        text: `${req.body.userName}'s most recent tweet was: \"\ ${req.body.tweetContent}\"\ and the sentiment score is: ${scoreSign}`,
      }
    },
    (err, data) => {
      if (err) {
        console.log(err);
      } else {
        console.log(data);
      }
    }
  );
});

Há uma pequena lógica na parte superior para fazer uma análise de sentimento com base na pontuação. Você pode, sem dúvida, removê-la caso prefira enviar o número exato em vez de emojis.
Em seguida, o relatório é enviado por SMS do seu número Nexmo para o número que o usuário tiver fornecido.

Execute seu aplicativo

Veja a seguir como é a estrutura do meu aplicativo final:

Structure of folders and filesStructure of folders and files

O passo final é testar o código e ver como tudo funciona! Volte ao diretório raiz e execute o comando que iniciará o servidor e o cliente simultaneamente:

npm run dev

Ao acessar localhost:3000 exibirá nosso componente React que solicita ao usuário um nome de usuário do Twitter.
O tweet mais recente desse usuário será então recuperado e exibido na página.
Clique no calculate the sentiment botão para chamar a API do Microsoft Azure Text Analytics e exibir a pontuação do tweet.
Digite seu número de telefone pessoal e o relatório por SMS será enviado a você por meio da Messages API da Nexmo.

🎉Pronto!🎉 Você criou com sucesso um aplicativo React para analisar o sentimento das suas postagens no Twitter, capaz de enviar um relatório por SMS para qualquer pessoa!

Próximos passos

Se isso despertou seu interesse em explorar mais as mensagens e a análise de sentimentos, aqui estão algumas ideias do que você pode tentar a seguir:

  • A Dispatch API da Nexmo permite que você redirecione sua mensagem de acordo com o status de entrega. Experimente essa funcionalidade e tente enviar seu relatório de sentimentos também para o Viber ou o WhatsApp!

  • Experimente o recurso do Twitter /streaming e considere enviar um relatório sempre que um nome de usuário publicar um tuíte.

Compartilhar:

https://a.storyblok.com/f/270183/250x250/708316e4e8/laurenlee.png
Lauren LeeEx-funcionários da Vonage

Um professor de inglês que se tornou um engenheiro de software empático. Um otimista curioso, apaixonado por criar conteúdo acessível e ajudar desenvolvedores a aprimorar suas habilidades.