Введение
Twilio позволяет таким разработчикам, как вы, добавлять коммуникационные технологии в свои приложения. Вы можете использовать API и SDK Twilio для отправки SMS и MMS, сообщений WhatsApp и электронных писем, а также для совершения телефонных звонков и видеозвонков.
В этом руководстве вы узнаете, как создать приложение, которое позволит вам делиться текстами любимых песен с друзьями с помощью React, Express и Twilio.
Давайте начнем!
Предпосылки
- Учетная запись Twilio и номер телефона, на который можно отправлять SMS-сообщения (вы можете зарегистрировать учетную запись Twilio бесплатно здесь)
- Node.js для создания нашего приложения React и запуска нашего сервера (вы можете создать серверный компонент этого на любом языке, но в этом посте мы собираемся сделать это в Node, чтобы мы могли сохранить все это JavaScript)
Проект, описанный в этой статье, состоит из двух частей:
Получить стартовый код
Для начала загрузите или клонируйте репозиторий, который будет содержать начальные файлы и файл .css:
git clone
https://github.com/bhagatpratham/twilio-lyrics-sharing.git
Перейдите в каталог
cd twilio-lyrics-sharing
npm install
Установите зависимости и установите переменные среды.
Последний пакет для установки — twilio
:
npm install twilio
Если вам так же, как и мне, интересно узнать, какие зависимости были установлены, вы всегда можете проверить их в файле package.json, который находится в корне проекта.
Затем создайте свое приложение для реагирования, которое будет содержать несколько начальных файлов, выполнив эту команду:
npx create-react-app client
Теперь, когда у вас есть начальный код, вы должны уделить немного времени изучению папки /src внутри twilio-lyrics-sharing-starter-kit. Вы найдете все файлы, доступные при создании реагирующего приложения.
Создание серверной части
В каталоге проекта создайте два новых файла: .env и index.js:
touch .env
touch index.js
В файл .env вы будете добавлять переменные среды, а в файл index.js вы будете писать код для своего бэкенда.
Получите учетные данные Twilio
Откройте новый файл .env в своем любимом текстовом редакторе.
Получите свой Sid учетной записи Twilio и токен аутентификации из консоли Twilio, а также номер телефона Twilio, по которому можно отправлять SMS-сообщения. Введите все три в файл .env
, который вы создали ранее, вот так:
TWILIO_ACCOUNT_SID=YOUR_ACCOUNT_SID TWILIO_AUTH_TOKEN=YOUR_AUTH_TOKEN TWILIO_PHONE_NUMBER=YOUR_TWILIO_PHONE_NUMBER
Это установит ваши учетные данные в среде. Теперь откройте index.js
, чтобы мы могли начать работу с кодом, необходимым для отправки текста.
Потребуйте и инициализируйте библиотеку Twilio с учетными данными из файла .env
и создайте базовый экспресс-сервер, как показано в приведенном ниже коде:
const express = require('express'); const bodyParser = require('body-parser'); require("dotenv").config(); const app = express(); const port = 3000; // Using the Twilio credentials const client = require('twilio')( process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN ); app.use(bodyParser.urlencoded({ extended: false })); app.listen(port, () => { console.log(`Server listening at <http://localhost>:${port}`); });
Создайте маршрут для запроса POST
чуть ниже переменной client
, где вы инициализировали учетные данные twilio.
app.post('/send-lyrics', (req, res) => { });
Конечная точка принимает два параметра в теле запроса: lyrics, который является телом текстового сообщения, и toNumber, который является номером телефона для отправки SMS-сообщения.
app.post("/send-lyrics", (req, res) => { const lyrics = req.body.lyrics; const toNumber = req.body.toNumber; });
Далее используйте клиент Twilio, который мы инициализировали ранее, чтобы создать сообщение. используйте свой номер Twilio в качестве from
номера и получите to
номер и body
сообщения из тела входящего запроса.
app.post("/send-lyrics", (req, res) => { const lyrics = req.body.lyrics; const toNumber = req.body.toNumber; client.messages .create({ body: lyrics, to: toNumber, from: process.env.TWILIO_PHONE_NUMBER, }) .then((message) => { console.log("SMS sent successfully:", message.sid); res.send("Lyrics shared successfully!"); }) .catch((err) => { console.error("Error sending SMS:", err); res.status(500).send("Error sharing lyrics!"); }); });
…
Это все, что вам нужно на сервере, давайте начнем с части React. Вот как должен выглядеть окончательный файл index.js.
const express = require("express"); const bodyParser = require("body-parser"); require("dotenv").config(); const app = express(); const port = 3000; const client = require("twilio")( process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN ); app.use(bodyParser.urlencoded({ extended: false })); app.post("/send-lyrics", (req, res) => { const lyrics = req.body.lyrics; const toNumber = req.body.toNumber; client.messages .create({ body: lyrics, to: toNumber, from: process.env.TWILIO_PHONE_NUMBER, }) .then((message) => { console.log("SMS sent successfully:", message.sid); res.send("Lyrics shared successfully!"); }) .catch((err) => { console.error("Error sending SMS:", err); res.status(500).send("Error sharing lyrics!"); }); }); app.listen(port, () => { console.log(`Server listening at <http://localhost>:${port}`); });
Запустите сервер с помощью следующей команды в вашем терминале:
nodemon index.js
Если вы все сделали правильно, вы получите следующее сообщение: Server listening at [<http://localhost:3000>](<http://localhost:3000/>)
Создание клиента
Вы начнете с компонента App
.
Откройте папку клиента, содержащую код React. Внутри папки клиента вы найдете папку src, содержащую файл App.js.
В этом компоненте вы получите текст из REST API и создадите функциональность для отправки текста на любой номер телефона, подтвержденный Twilio, с помощью SMS API Twilio.
Удалите все из файла App.js и замените его следующим кодом:
// App.js import "./App.css"; function App() { return ( <div className="App"> <section className="logo"> <h2>Lyrics Sharing App</h2> <p className="app-desc"> a simple and easy to use app to share song lyrics with your friends </p> </section> </div> ); } export default App;
Теперь мы создадим некоторые переменные состояния, используя хук useState
.
Импортируйте useState()
hook из React сверху и добавьте следующую переменную состояния, показанную в коде ниже:
// App.js import { useState } from "react"; import "./App.css"; function App() { const [lyrics, setLyrics] = useState(null); const [trackName, setTrackName] = useState(""); const [artistName, setArtistName] = useState(""); const [copied, setCopied] = useState(false); const [number, setNumber] = useState(""); return ( <div className="App"> <section className="logo"> <h2>Lyrics Sharing App</h2> <p className="app-desc"> a simple and easy to use app to share song lyrics with your friends </p> </section> </div> ); } export default App;
lyrics
, который будет использоваться для хранения текстов песен, которые вы получите из API.trackName
будет использоваться для хранения названия песни, которую пользователь хочет найти.artistName
сохранит имя исполнителя песни, которое пользователь вводит в поле поиска.copied
, будет использоваться для копирования текстаnumber
, в котором будет храниться номер телефона, введенный пользователем для обмена текстами песен.
Затем вы должны добавить следующий код внутрь return()
компонента App
.
Код определяет основную часть пользовательского интерфейса приложения, который включает в себя три основных раздела: окно поиска для ввода названия трека и исполнителя, раздел отображения для извлеченных текстов и раздел, где пользователь может ввести номер телефона. и поделитесь текстом.
<section className="main-body"> <div className="search-lyrics"> <input placeholder="Enter track name"></input> <div className="search-container"> <input placeholder="Enter artist name (optional)"></input> <button className="search-btn">Search Lyrics</button> </div> </div> <div className="lyrics"> <button className="copy-lyrics">Copy Lyrics</button> <p className="display-lyrics"> {lyrics?.lyrics || "Nothing here yet ..."} </p> </div> <div className="send-lyrics"> <label htmlFor="to">To:</label> <input className="phone-number-input" type="tel" name="to" id="to" placeholder="Enter phone number" value={number} onChange={(e) => setNumber(e.target.value)} />{" "} <button className="share-lyrics">Share Lyrics</button> </div> <p>Note: Lyrics should not exceed 1600 characters</p> </section>
Давайте добавим немного CSS, чтобы приложение выглядело красиво. Вставьте следующий код в файл App.css.
/* Define color palette */ :root { --color-primary: #ef233c; --color-secondary: #d90429; --color-accent: #8d99ae; --color-background: #edf2f4; --color-text: #2b2d42; } /* Apply global styles */ body { margin: 0; font-family: Arial, sans-serif; background-color: var(--color-background); color: var(--color-text); } /* Apply styles to App section */ .App { max-width: 800px; margin: 0 auto; padding: 40px 20px; } /* Apply styles to logo section */ .logo { text-align: center; margin-bottom: 40px; } .logo h2 { font-size: 36px; font-weight: bold; margin-bottom: 10px; color: var(--color-primary); } .logo .app-desc { font-size: 18px; margin-bottom: 0; } /* Apply styles to main-body section */ .main-body { display: flex; flex-direction: column; gap: 20px; } /* Apply styles to search-lyrics section */ .search-lyrics { display: flex; flex-direction: column; gap: 10px; } .search-lyrics input { padding: 10px; border: none; border-radius: 5px; font-size: 16px; } .search-container { display: flex; gap: 10px; align-items: center; } .search-btn { background-color: var(--color-primary); color: white; padding: 10px 20px; border: none; border-radius: 5px; font-size: 16px; cursor: pointer; } .lyrics { margin-top: 2rem; } /* Button styles */ .copy-lyrics, .share-lyrics { display: inline-block; background-color: var(--color-primary); color: var(--color-background); border: none; padding: 0.75rem 1.5rem; margin-right: 1rem; border-radius: 5px; font-size: 1rem; font-weight: bold; cursor: pointer; transition: all 0.3s ease; } .copy-lyrics:hover, .share-lyrics:hover { background-color: var(--color-secondary); } /* Display lyrics styles */ .display-lyrics { background-color: var(--color-background); color: var(--color-text); padding: 1.5rem; margin-top: 1.5rem; border-radius: 5px; font-size: 0.8rem; line-height: 1.5; } /* Send lyrics styles */ .send-lyrics { margin-top: 1.5rem; } .share-lyrics { background-color: var(--color-primary); color: var(--color-background); } .share-lyrics:hover { background-color: var(--color-secondary); } label { display: inline-block; margin-right: 1rem; font-size: 1.2rem; color: var(--color-text); } input { padding: 0.5rem 1rem; border-radius: 5px; border: 1px solid var(--color-accent); font-size: 1rem; color: var(--color-text); } input:focus { outline: none; border-color: var(--color-primary); } /* Note styles */ p { margin-top: 1.5rem; font-size: 0.9rem; color: var(--color-accent); }
Запустите приложение, переключившись в следующий каталог в вашем терминале cd twilio-lyrics-sharing/client && npm start
, и вы увидите это на странице. Убедитесь, что вы переключились на каталог клиента в своем терминале, чтобы запустить приложение React.
Если ваш серверный код уже запущен локально на PORT=3000
, то при выполнении приведенной выше команды вам будет предложено запустить проект React на другом порту. Нажмите y
, а затем return
, чтобы сделать это.
Затем вы создадите две функции**getTrack()
** и getArtist()
внутри компонента App
, прямо под объявлениями состояния, которые будут обновлять переменные состояния trackName
и artistName
, которые вы создали ранее соответственно.
Таким образом, всякий раз, когда пользователь вводит что-то в поля ввода, значение переменных будет автоматически обновляться до того, что ввел пользователь.
const getTrack = (e) => { setTrackName(e.target.value); }; const getArtist = (e) => { setArtistName(e.target.value); };
Добавьте функцию getTrack
к следующему элементу <input>
, используя атрибут onChange
.
<input placeholder="Enter track name" onChange={getTrack}> </input>
Точно так же вы должны добавить функцию getArtist
к следующему <input>
element.
<input placeholder="Enter artist name (optional)" onChange={getArtist}> </input>
Теперь вы создадите функцию с именем handleClick
, которая будет делать запрос API на **https://lyrist.vercel.app/api/ ****** и извлекать тексты для данной песни и исполнителя.
Он использует метод fetch()
для выполнения запроса GET к конечной точке URL, который включает переменные trackName
и artistName
в качестве параметров.
Если ответ от API успешен, функция извлекает данные ответа в формате JSON с помощью метода res.json()
и устанавливает текст в переменную состояния lyrics
с помощью функции setLyrics()
.
const handleClick = async () => { if (trackName.trim() === "") { console.error("Track name can't be empty!"); } else { const res = await fetch( `https://lyrist.vercel.app/api/${trackName}/${artistName}` ); if (res.ok) { const data = await res.json(); setLyrics(data); } else { res.error("Lyrics not found!"); } } };
Добавьте функцию handleClick
к кнопке Search Lyrics, используя атрибут onClick
. Таким образом, всякий раз, когда пользователь нажимает кнопку, функция отправляет запрос API для поиска текста песни.
<button className="search-btn" onClick={handleClick}>Search Lyrics</button>
Создайте еще одну функцию с именем handleCopy
, которая будет копировать текст песни в буфер обмена пользователя.
Сначала функция вызывает метод navigator.clipboard.writeText()
, передавая выражение lyrics?.lyrics
в качестве текста для копирования. Выражение lyrics?.lyrics
использует необязательную цепочку, чтобы проверить, существует ли объект лирики перед доступом к его свойству лирики.
Если объект текстов песен имеет значение null или не определен, в качестве копируемого текста будет использоваться пустая строка.
Если текст успешно скопирован, функция устанавливает для скопированной переменной состояния copied
значение true с помощью функции setCopied()
.
const handleCopy = () => { navigator.clipboard .writeText(lyrics?.lyrics || "") .then(() => { setCopied(true); }) .catch(() => { console.error("Couldn't Copy!"); }); };
Аналогичным образом добавьте функцию handleCopy
к кнопке Copy Lyrics
.
<button className="copy-lyrics" onClick={handleCopy}>Copy Lyrics</button>
Теперь нам нужно обработать функцию обмена текстами песен, которая позволит пользователю делиться текстами песен на номер телефона.
Создайте функцию shareLyrics
в компоненте App
, которая принимает два параметра: lyrics
и number
Сначала функция отправляет запрос POST на сервер Express.js, работающий на http://localhost:3000/send-lyrics
, с параметрами lyrics
и **toNumber
** как часть тела запроса.
Если ответ от сервера успешен, функция регистрирует сообщение об успешном выполнении на консоли и показывает предупреждение пользователю. В противном случае он регистрирует сообщение об ошибке и показывает предупреждение об ошибке.
const shareLyrics = async (lyrics, number) => { if (lyrics && number.trim() !== "") { try { const smsRes = await fetch("<http://localhost:3000/send-lyrics>", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: new URLSearchParams({ lyrics: lyrics, toNumber: number, }), }); if (smsRes.ok) { console.log("Lyrics shared successfully!"); alert("Lyrics shared successfully!"); return true; } else { console.error("Error sharing lyrics!"); alert("Error sharing lyrics!"); } } catch (err) { console.error("Error sharing lyrics:", err); } } return false; };
Наконец, добавьте функцию shareLyrics
к следующей кнопке, передав lyrics
и number
с помощью атрибута onClick
.
<button className="share-lyrics" onClick={() => shareLyrics(lyrics?.lyrics, number)}> Share Lyrics </button>
Это все, что вам нужно. Окончательный файл App.js
должен выглядеть так:
import { useState } from "react"; import "./App.css"; function App() { const [lyrics, setLyrics] = useState(null); const [trackName, setTrackName] = useState(""); const [artistName, setArtistName] = useState(""); const [copied, setCopied] = useState(false); const [number, setNumber] = useState(""); const getTrack = (e) => { setTrackName(e.target.value); }; const getArtist = (e) => { setArtistName(e.target.value); }; const handleClick = async () => { if (trackName.trim() === "") { console.error("Track name can't be empty!"); } else { const res = await fetch( `https://lyrist.vercel.app/api/${trackName}/${artistName}` ); if (res.ok) { const data = await res.json(); setLyrics(data); } else { res.error("Lyrics not found!"); } } }; const handleCopy = () => { navigator.clipboard .writeText(lyrics?.lyrics || "") .then(() => { setCopied(true); }) .catch(() => { console.error("Couldn't Copy!"); }); }; const shareLyrics = async (lyrics, number) => { if (lyrics && number.trim() !== "") { if (lyrics.length > 1600) { console.error("Lyrics exceed 1600 characters!"); alert("Lyrics exceed 1600 characters!"); return false; } try { const smsRes = await fetch("<http://localhost:3000/send-lyrics>", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: new URLSearchParams({ lyrics: lyrics, toNumber: number, }), }); if (smsRes.ok) { console.log("Lyrics shared successfully!"); alert("Lyrics shared successfully!"); return true; } else { console.error("Error sharing lyrics!"); alert("Error sharing lyrics!"); } } catch (err) { console.error("Error sharing lyrics:", err); } } return false; }; return ( <div className="App"> <section className="logo"> <h2>Lyrics Sharing App</h2> <p className="app-desc"> a simple and easy to use app to share song lyrics with your friends </p> </section> <section className="main-body"> <div className="search-lyrics"> <input placeholder="Enter track name" onChange={getTrack}></input> <div className="search-container"> <input placeholder="Enter artist name (optional)" onChange={getArtist} ></input> <button className="search-btn" onClick={handleClick}> Search Lyrics </button> </div> </div> <div className="lyrics"> <button className="copy-lyrics" onClick={handleCopy}> Copy Lyrics </button> <p className="display-lyrics"> {lyrics?.lyrics || "Nothing here yet ..."} </p> </div> <div className="send-lyrics"> <label htmlFor="to">To:</label> <input className="phone-number-input" type="tel" name="to" id="to" placeholder="Enter phone number" value={number} onChange={(e) => setNumber(e.target.value)} />{" "} <button className="share-lyrics" onClick={() => shareLyrics(lyrics?.lyrics, number)} > Share Lyrics </button> </div> <p>Note: Lyrics should not exceed 1600 characters</p> </section> </div> ); } export default App;
Наконец, теперь вы можете проверить, работает ли проект, запустив npm start
. Приложение загрузится в вашем браузере по адресу localhost:3000
.
Если ваш серверный код уже запущен локально на PORT=3000
, то при выполнении приведенной выше команды вам будет предложено запустить проект React на другом порту. Нажмите y
, а затем return
, чтобы сделать это.
Вы можете проверить весь код из этого примера приложения в репозитории GitHub.
Заключение
В этой статье вы узнали, как создать приложение для обмена текстами песен с помощью Twilio, React и Express. Надеюсь, вы узнали больше о некоторых нюансах React и о том, как интегрировать API-интерфейсы Twilio в свои приложения React и Express.
Чтобы сделать это приложение круче, возможно, вы можете создать свою собственную виртуальную вечеринку для прослушивания с помощью Twilio Programmable Video. Дайте мне знать в Твиттере, если у вас есть идея получше.
Дополнительные материалы на PlainEnglish.io.
Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .