DevGang
Авторизоваться

Отслеживание подписчиков Twitter с использованием Next.js, NextAuth и TailwindCSS 

Шаги по созданию счетчика подписчиков в Твиттере с использованием Next.js, NextAuth, SWR, Tailwind CSS с поддержкой темного режима.

Чтобы узнать что-то новое, недостаточно просто прочитать документацию. Мы должны применить это на практике. Точно так же при изучении новых технологических стеков мы должны применять их, разрабатывая простые приложения, чтобы получить практический опыт. 

Итак, чтобы изучить некоторые новые технологические стеки, давайте создадим небольшое приложение. Здесь мы изучим Next.jsNextAuthSWR и Tailwind CSS, разработав приложение для подсчета подписчиков в Twitter. 

Мы собираемся создать приложение наподобие TwiterStats.

Технический стек

  1. Next.js для создания приложения ReactJS.
  2. NextAuth для реализации OAuth с Twitter.
  3. SWR для получения данных из API.
  4. Tailwind для пользовательского интерфейса
  5. Twitter Lite для получения данных из API Twitter.

Настройка Next.js и Tailwind

Мы можем настроить Tailwind с помощью next.js с помощью одной команды, как показано ниже:

npx create-next-app -e with-tailwindcss twitter-count

Приведенная выше команда автоматически настраивает установку Tailwind на основе официального примера Next.js.

После завершения установки перейдите в папку проекта с помощью команды cd twitter-count и запустите сервер разработки с помощью команды yarn dev. Вы можете увидеть страницу ниже, если нажмете в браузере http://localhost:3000.

Настройка NextAuth.js

NextAuth — это пакет аутентификации с открытым исходным кодом для Next.js. NextAuth упрощает вход в социальные сети, такие как Twitter, Google, Apple, Github и многие другие. Он также поддерживает электронную почту или вход без пароля и интеграцию с базой данных.

Добавьте в свой проект next auth, используя приведенную ниже команду

yarn add next-auth

Затем создайте файл с именем […nextauth].js в папке pages/api/auth и добавьте приведенный ниже код.

import NextAuth from "next-auth"
import TwitterProvider from "next-auth/providers/twitter"
import {cloneDeep} from "tailwindcss/lib/util/cloneDeep";

export default NextAuth({
    // Configure one or more authentication providers
    providers: [
        TwitterProvider({
            clientId: process.env.TWITTER_ID,
            clientSecret: process.env.TWITTER_SECRET
        }),
        // ...add more providers here
    ],
    callbacks: {
        async jwt({token, user, account, profile, isNewUser}) {
            if (profile) {
                token['userProfile'] = {
                    followersCount: profile.followers_count,
                    twitterHandle: profile.screen_name,
                    userID: profile.id
                };
            }
            if (account) {
                token['credentials'] = {
                    authToken: account.oauth_token,
                    authSecret: account.oauth_token_secret,
                }
            }
            return token
        },
        async session({session, token, user}) {
            // Send properties to the client, like an access_token from a provider.
            let userData = cloneDeep(token.userProfile);
            delete userData.userID;
            session.twitter = userData;
            return session;
        }
    },
    secret: process.env.NEXTAUTH_SECRET,
    pages: {
        error: '/error', // Error code passed in query string as ?error=
    }
})

Давайте разберем приведенный выше код

Над функцией NextAuth обрабатывается динамический маршрут для всех социальных сетей. Здесь мы собираемся использовать Twitter OAuth, поэтому мы добавили TwitterProvider в провайдеры. Для успешного выполнения OAuth нам требуются TWITTER_ID и TWITTER_SECRET. Получите их на платформе разработчиков Twitter, выполнив несколько простых шагов. 

Следуйте инструкциям по этой ссылке, чтобы получить доступ к Twitter API.

Получив Secrets с портала разработчика, обновите его в env и добавьте к провайдеру, как указано выше. 

Используя обратный вызов, установите необходимые данные в сеансе после успешного OAuth с Twitter. При успешном OAuth мы получаем много подробностей из Twitter, здесь мы настроим необходимые нам данные и сохраним их в сеансе.

Мы не должны раскрывать секреты, такие как authToken и authSecret на стороне клиента, поэтому мы сохраняем их в объектах токена JWT. Затем мы можем получить доступ к учетным данным пользователя на стороне сервера, используя вспомогательный метод getToken. Случайная строка secret, используется для хэширования токенов, подписи или шифрования файлов cookie и создания криптографических ключей.

Настройка поставщика сеансов

Деформируйте контекст SessionProvier в компоненте верхнего уровня, чтобы использовать хуки useSession для получения данных сеанса в дочерних компонентах, как показано ниже.

import '../styles/globals.css'
import {SessionProvider} from "next-auth/react"
import {ThemeProvider} from "next-themes";

export default function App({Component, pageProps: {session, ...pageProps},}) {
    return (
        <SessionProvider session={session} refetchInterval={5 * 60}>
            <ThemeProvider attribute="class" enableSystem={false}>
                <Component {...pageProps} />
            </ThemeProvider>
        </SessionProvider>
    )
}

refetchInterval используется для периодической загрузки сеанса в фоновом режиме.

В нашем приложении _app.js это компонент верхнего уровня, поэтому мы обернули поставщика сеансов. Здесь мы обернули контекст ThemeProvide из следующей темы, чтобы включить поддержку темного режима. 

Компонент счетчика подписчиков

Добавьте приведенный ниже код в Компоненты Подписчиков.

import useSWR from 'swr'
import {useState, useEffect} from "react";
import {signOut} from "next-auth/react";
import Image from 'next/image'
import {UserGroupIcon} from "@heroicons/react/solid";
import ToggleButton from "../components/Toggle";
import AnimatePing from "../components/animatePing";
import ProfileImage from "../public/profile-pic.png";

const fetcher = (...args) => fetch(...args).then(res => res.json());

export default function Followers({session}) {
    const [isAutoRefresh, setIsAutoRefresh] = useState(false);

    const enableAutoRefresh = () => {
        setIsAutoRefresh(!isAutoRefresh);
    };
    const {data, error} = useSWR(session ? '/api/twitter/user' : null, fetcher,
        {refreshInterval: isAutoRefresh ? 30000 : 0, revalidateOnFocus: false}
    );

    if (data && data.error && data.error.errors[0] && data.error.errors[0].code === 89) {
        signOut();
    }

    if (!data) return <div> Loading... </div>;
    const userData = data.data;
    return (
        <figure className="md:flex bg-white rounded-xl p-8 md:p-0 shadow-xl twitter-card dark:bg-gray-800">
            <Image
                src={session.user.image ? session.user.image : ProfileImage}
                alt="Picture of the author"
                className="w-24 h-24 md:w-64 md:h-auto rounded-tl-lg rounded-bl-lg mx-auto"
                width={500}
                height={500}
                priority={true}
            />
            {isAutoRefresh && <AnimatePing/>}
            <div className="pt-6 md:p-4 text-center md:text-left space-y-4">
                <div className="flex 2xl:pb-5 flex-col md:flex-row">
                    <div
                        className="flex bg-gradient-to-r from-cyan-500 to-blue-500 rounded-lg md:mr-10 p-4 mb-4 md:mb-0
                             justify-center items-center transition ease-in-out delay-150 hover:-translate-y-1
                             hover:scale-110 hover:from-pink-500 hover:to-yellow-500">
                        <UserGroupIcon className="h-10 text-white"/>
                        <div className="text-4xl ml-4 align-middle font-semibold 2xl:text-6xl">
                            {userData.followersCount}
                        </div>
                    </div>
                    <div className="flex items-center md:justify-end w-full exclude-in-image justify-center">
                        <HtmlToImage imageRef={ref} userName={session.user.name}/>
                        <ToggleButton onChange={() => enableAutoRefresh()} isAutoRefresh={isAutoRefresh}/>
                    </div>
                </div>
                {userData &&
                    <figcaption className="font-medium 2xl:pb-5">
                        <a className="text-sky-500 2xl:text-4xl" target="_blank"
                           rel="noreferrer"
                           href={`https://twitter.com/${userData.twitterHandle}`}>
                            @{userData.twitterHandle}
                        </a>
                        <div className="text-gray-700 2xl:text-3xl text-gray-400">
                            {userData && userData.location}
                        </div>
                    </figcaption>
                }
                <blockquote>
                    <p className="text-lg font-medium 2xl:text-3xl dark:text-gray-400">
                        {userData && userData.description}
                    </p>
                </blockquote>
            </div>
        </figure>
    )
}

Разбивка компонента подписчиков

SWR — это React Hooks для выборки данных, разработанный командой Next.js. Он поддерживает выборку данных в реальном времени, встроенный кеш, автоматическую повторную проверку, предварительную выборку и многое другое.

В компоненте подписчиков мы вызвали API /api/twitter/user, чтобы получить основные сведения о пользователе Twitter, такие как имя, количество подписчиков, описание профиля и местоположение. Мы использовали SWR для получения данных из API за определенный промежуток времени.
 
Поскольку данные, которые мы получаем от NextOAuth, не являются данными в реальном времени, мы используем Twitter Lite API для получения сведений о пользователе Twitter в режиме реального времени. 

Интеграция с Twitter Lite

Twitter Lite — это крошечная полнофункциональная гибкая серверная библиотека для API Twitter.

В Next.js вы также можете создавать API, файлы внутри api/* считаются конечными точками API, которые обрабатываются на сервере, а не на стороне клиента. Доступ к Twitter API возможен только со стороны сервера, поэтому у нас есть пользовательский API в папке api/ для доступа к show API с помощью пакета Twitter lite.

Добавьте приведенный ниже код pages/api/twitter/user.js чтобы получить доступ к сведениям о пользователе с помощью /api/twitter/userAPI.

import {getToken} from 'next-auth/jwt';
import Twitter from "twitter-lite";


export default async (req, res) => {
    const token = await getToken({
        req,
        secret: process.env.NEXTAUTH_SECRET
    });

    try {
        const twitterClient = new Twitter({
            consumer_key: process.env.TWITTER_ID,
            consumer_secret: process.env.TWITTER_SECRET,
            access_token_key: token.credentials.authToken, // from your User (oauth_token)
            access_token_secret: token.credentials.authSecret // from your User (oauth_token_secret)
        });
        //
        const userData = await twitterClient.get("users/show", {
            id: token.userProfile.userID,
            screen_name: token.userProfile.twitterHandle
        });

        const data = {
            twitterHandle: userData.screen_name,
            followersCount: userData.followers_count,
            description: userData.description,
            location: userData.location,
        };

        return res.status(200).json({
            status: 'Ok',
            data
        });
    } catch (error) {
        // return error;
        return res.status(500).send({ error });
    }
}

Добавьте компонент Followers в файл index.js, как показано ниже.

import {useSession, signIn, signOut} from "next-auth/react"
import {useEffect, useState} from "react";
import Layout from "../components/Layout";
import Button from "../components/Button";
import Followers from "../components/Followers";
import Image from "next/image";

export default function Home() {
    const [loader, setLoader] = useState(false);

    function oauthSignOut() {
        if (!loader) {
            setLoader(!loader);
            signOut();
        }
    }

    if (status === 'loading') return <Layout> Loading... </Layout>;

    function oauthSignIn() {
        if (!loader) {
            setLoader(!loader);
            signIn('twitter');
        }
    }
    if (session) {
        return (
            <Layout>
                <Followers session={session}/>
                <div className="flex flex-wrap items-center justify-around max-w-4xl py-6 sm:w-full 2xl:py-12">
                    <Button label="Logout" onClick={() => oauthSignOut()} loader={loader}>Sign out</Button>
                </div>
            </Layout>
        )
    }
    return (
        <Layout>
            <div className="mb-10">
                <Image
                    src="/cover-logo.png"
                    alt="Picture of the author"
                    width={800}
                    height={300}
                />
            </div>
            <Button label="Login with Twitter" onClick={() => oauthSignIn()} loader={loader}>
                Sign in
            </Button>
        </Layout>
    )
}

Здесь мы используем signIn и signOut для инициализации входа next-auth в систему OAuth. Чтобы войти в систему с помощью Twitter, мы передаем параметры Twitter методу входа, как показано ниже

signIn('twitter');

Теперь просто нажмите на URL-адрес в браузере, чтобы увидеть изменения, как показано ниже

При вызове метода signIn приложение будет перенаправлено на страницу Twitter OAuth, а нажатие кнопки « Авторизовать приложение» на странице OAuth перенаправит обратно на компонент наших подписчиков, как показано ниже.

Нам нужно настроить URL-адрес перенаправления OAuth на портале разработчиков Twitter при регистрации.

Вы можете настроить пользовательский интерфейс в соответствии с вашими потребностями. Здесь я рассмотрел только часть интеграции и базовый пользовательский интерфейс с использованием tailwind.

Развертывание в Vercel

Вы можете развернуть приложение Counter в Vercel, выполнив два шага, как показано ниже:

  1. Создать учетную запись Vercel
  2. Подключите свой репозиторий и нажмите развернуть.

Ссылки

Репозиторий GitHub -> https://github.com/Nilanth/twiter-stats

Живая демонстрация -> https://twiter-stats.vercel.app

Вывод

Мы успешно интегрировали Twitter с NextAuth и отображали количество подписчиков с помощью Next и tailwind. Теперь у нас есть практический опыт работы с этими технологическими стеками.

Спасибо за чтение

Источник:

#JavaScript #React #NestJS
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В подарок 100$ на счет при регистрации

Получить