Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

Upstash でツイート スケジューラを作成する:ステップバイステップ ガイド

このステップバイステップ ガイドでは、Upstash QStash、Upstash Redis、Next.js Server Actions、Vercel を使用してツイート スケジューラーを構築した方法について説明します。 Twitter の投稿をスケジュールすると、一貫したプレゼンスを維持し、最適なタイミングで視聴者と関わり、コンテンツ戦略を効率的に管理できます。

前提条件

以下が必要になります。

  • Node.js 18 以降
  • Upstash アカウント
  • Twitter アカウント
  • Vercel アカウント

技術スタック

このガイドでは次のテクノロジーが使用されています。

テクノロジー 説明 Upstashサーバーレス データベース プラットフォーム。私たちは、ツイートをキューに保存するために Upstash Queue と QStash を使用し、指定された頻度でスケジュール API を POST するためにそれぞれ使用しています。Next.jsWeb 用の React フレームワーク。ラピッド UI プロトタイピングには Populate shadcn/ui を使用しています。カスタム デザインの構築には TailwindCSSCSS フレームワーク。Web アプリケーションのデプロイとスケーリングには VercelA クラウド プラットフォーム。一貫したコード スタイルには PrettierOpinionated コード フォーマッタを使用します。

手順

このガイドを完了し、独自のツイート スケジューラを展開するには、次の手順に従う必要があります。

  • Upstash Redis のセットアップ
  • Upstash QStash のセットアップ
  • Twitter 開発者アプリケーションのセットアップ
  • 新しい Next.js アプリケーションを作成する
  • Twitter OAuth 2.0 を使用したユーザー認証を実装する
  • ツイートをスケジュールするためのユーザー インターフェースを構築する
  • Upstash QStash を使用してツイートをスケジュールする
  • Vercel にデプロイ

Upstash Redis のセットアップ

Upstash アカウントを作成してログインしたら、[Redis] タブに移動してデータベースを作成します。

Upstash でツイート スケジューラを作成する:ステップバイステップ ガイド

Upstash でツイート スケジューラを作成する:ステップバイステップ ガイド

データベースを作成したら、REST API セクションが見つかるまで下にスクロールし、.env を選択します。 ボタン。コンテンツをコピーし、安全な場所に保存します。

Upstash でツイート スケジューラを作成する:ステップバイステップ ガイド

Upstash QStash のセットアップ

特定の間隔でスケジューリング エンドポイントへの POST リクエストをスケジュールするには、QStash を使用します。 「QStash」タブに移動し、「Request Builder」タブまで下にスクロールします。

Upstash でツイート スケジューラを作成する:ステップバイステップ ガイド

QStash URL、TOKEN、現在の署名キー、次の署名キーをコピーし、安全な場所に保存します。

Upstash でツイート スケジューラを作成する:ステップバイステップ ガイド

Twitter 開発者アプリケーションのセットアップ

Twitter OAuth 2.0 による認証を設定するには、Twitter Developer Portal でアプリケーションを作成します。 Twitter アプリケーションを設定するには、次の手順を実行します。

  • Twitter のデベロッパー ポータル> プロジェクトを開きます。
  • プロジェクトを作成します。
  • アプリケーション設定の [設定] タブに移動し、次の操作を実行します。
    • Read and write and Direct message を選択します アプリの権限で .
    • Web App, Automated App or Bot を選択します アプリの種類で .
    • http://localhost:3000/api/auth/callback/twitter を入力してください コールバック URI / リダイレクト URL として .
  • Keys and tokens に移動します。 アプリケーション設定のタブをクリックし、下にスクロールして次の操作を行います:
    • Client ID をコピーします。 それを TWITTER_CLIENT_ID として安全な場所に保存します。 .
    • Client Secret をコピーします。 それを TWITTER_CLIENT_SECRET として安全な場所に保存します。 .

Twitter 開発者アプリケーションを OAuth 2.0 用に正常にセットアップするために必要な設定はこれだけです。

新しい Next.js アプリケーションを作成する

新しい Next.js プロジェクトを作成することから始めましょう。ターミナルを開いて次のコマンドを実行します。

npx create-next-app@latest schedule-qstash-queue-upstash

プロンプトが表示されたら、次のものを選択します。

  • Yes TypeScript を使用するように求められた場合。
  • No ESLint を使用するように求められた場合。
  • Yes Tailwind CSS を使用するよう求められた場合。
  • No src/ を使用するように求められた場合 ディレクトリ。
  • Yes App Router を使用するように求められた場合。
  • No デフォルトのインポート エイリアス (@/*) をカスタマイズするように求められた場合 ).

それが完了したら、プロジェクト ディレクトリに移動し、次のコマンドを実行してアプリを開発モードで開始します。

cd schedule-qstash-queue-upstash
npm run dev

アプリは localhost:3000 で実行されている必要があります。

次に、.env を作成します。 プロジェクトのルートにあるファイル。上記のセクションで保存したアイテムを追加します。

次のようになります:

# .env
 
# Obtained from the steps as above
 
# Twitter Environment Variables
TWITTER_CLIENT_ID="..."
TWITTER_CLIENT_SECRET="..."
TWITTER_AUTH_CALLBACK_URL="http://localhost:3000/api/auth/callback/twitter"
 
# Upstash Environment Variables
UPSTASH_REDIS_REST_URL="https://...upstash.io"
UPSTASH_REDIS_REST_TOKEN="...="
QSTASH_URL="https://qstash.upstash.io/v2/publish/"
QSTASH_TOKEN="...="
QSTASH_CURRENT_SIGNING_KEY="sig_..."
QSTASH_NEXT_SIGNING_KEY="sig_..."

shadcn/ui コンポーネントの統合

ユーザー インターフェイスのプロトタイプをすばやく作成するには、shadcn/ui をセットアップします。 Next.js を使用します。 shadcn/ui は、コピーしてアプリに貼り付けることができる、美しくデザインされたコンポーネントのコレクションです。ターミナル ウィンドウで以下のコマンドを実行して、shadcn/ui のセットアップを開始します。 :

npx shadcn-ui@latest init

components.json を設定するために、いくつかの質問が表示されます。 、次を選択します:

  • Yes TypeScript を使用するように求められた場合。
  • Default 使用するスタイルを選択するよう求められたら。
  • Slate ベースカラーの選択を求められた場合。
  • app/globals.css グローバル CSS ファイルの入力を求められた場合。
  • yes 色に CSS 変数を使用するように求められた場合。
  • Leave blank カスタムの追い風プレフィックスを入力するよう求められた場合。
  • tailwind.config.ts tailwind.config.js の場所を入力するよう求められた場合。
  • @/components コンポーネントのエイリアスを構成するよう求められた場合。
  • @/lib/utils utils のエイリアスを構成するよう求められた場合。
  • Yes React サーバー コンポーネントの使用方法を選択するよう求められた場合。
  • Yes 構成をコンポーネント.json に書き込むように求めるプロンプトが表示されたら。

それが完了すると、Next.js アプリケーションに React コンポーネントを簡単に追加できる CLI が設定されました。次に、ターミナル ウィンドウで以下のコマンドを実行して、ボタン、入力、テキストエリア、ポップオーバー、カレンダー、トースト要素を取得します。

npx shadcn-ui@latest add button
npx shadcn-ui@latest add input
npx shadcn-ui@latest add textarea
npx shadcn-ui@latest add toast
npx shadcn-ui@latest add popover
npx shadcn-ui@latest add calendar

それが完了すると、ui が表示されます。 app/components 内のディレクトリ button.tsx を含むディレクトリ 、input.tsxcalendar.tsxinput.tsxpopover.tsxtextarea.tsxtoast.tsxtoaster.tsx 、および use-toast.ts .

次に、app/layout.tsx を開きます。 ファイルを開き、次の追加を行います。

+ // File: app/layout.tsx
 
import './globals.css'
+ import { cn } from '@/lib/utils'
import type { Metadata } from 'next'
+ import { Inter } from 'next/font/google'
+ import { Toaster } from '@/components/ui/toaster'
 
+ const fontSans = Inter({
+ subsets: ['latin'],
+ variable: '--font-sans',
+ })
 
export const metadata: Metadata = {
 title: 'Create Next App',
 description: 'Generated by create next app',
}
 
export default function RootLayout({
 children,
}: Readonly<{
 children: React.ReactNode
}>) {
 return (
 <html lang="en">
 <body
+ className={cn(fontSans.variable, 'min-w-screen flex min-h-screen flex-col items-center justify-center bg-background font-sans antialiased')}
 >
 {children}
+ <Toaster />
 </body>
 </html>
 )
}

上記のコード変更では、Toaster をインポートしました。 コンポーネント (shadcn/ui によって作成されました) )、それが Next.js アプリケーション全体に存在することを確認しました。 useToast を介して、コード内のどこからでもトースト通知を表示できるようになります。 フック。

スケジュールされたツイートを保存するための Upstash キューを作成する

このセクションでは、Upstash Queue を使用してスケジュールされたツイート情報を保存する方法を学習します。 Next.js サーバー アクションを使用して、API ルート経由ではなく関数として呼び出されるサーバー側コードを作成する方法を学習します。

まず、ターミナル ウィンドウで次のコマンドを実行して、Upstash SDK をインストールします。

npm install @upstash/qstash @upstash/queue @upstash/redis@1.28.0

上記のコマンドは、次のパッケージをインストールします。

  • @upstash/qstash :HTTP リクエストを介して Upstash QStash インスタンスと対話するための SDK。
  • @upstash/queue :Upstash Redis によってサポートされる、ストリーム ベースのメッセージ キューを管理する SDK。
  • @upstash/redis :Upstash REST API 上に構築された、HTTP リクエストを介して Redis と対話するための SDK。

Upstash Redis および Upstash Queue クライアントを初期化する

上記でインストールしたライブラリを使用して Upstash キューと対話するには、ファイル lib/upstash.ts を作成します。 次のコードを使用します:

// File: lib/upstash.ts
 
import { Redis } from '@upstash/redis'
import { Queue } from '@upstash/queue'
 
export const redis = new Redis({
 url: process.env.UPSTASH_REDIS_REST_URL as string,
 token: process.env.UPSTASH_REDIS_REST_TOKEN as string,
})
 
export const queue = new Queue({
 redis,
 queueName: 'tweets',
 concurrencyLimit: 5,
})

上記のコードは次のことを行います:

  • Redis をインポートします と Queue パッケージによってエクスポートされたクラス。
  • redis をエクスポートします リクエスト認可トークンを含む Upstash Redis URL を指すインスタンス。
  • queue をエクスポートします 上記で作成した Upstash Redis を指すインスタンス。キュー名を tweets に設定します。 と concurrencyLimit から 5 まで。最大 5 つのメッセージを同時に処理できます。

キュー インスタンスを使用して、ツイート テキストとツイート日付を受け入れて形成し、その後の処理のためにツイート オブジェクトをキューにプッシュする Next.js サーバー アクションを作成します。ファイル app/schedule.server.tsx を作成します 次のコードを使用します:

// File: app/schedule.server.tsx
 
'use server'
 
import { queue } from '@/lib/upstash'
import type { FormProps } from './form'
 
export async function schedule(_: any, formData: FormData): Promise<FormProps> {
 try {
 const tweet_text = formData.get('tweet_text') as string
 const tweet_date = formData.get('tweet_date') as string
 const now = new Date().getTime()
 const delay = new Date(tweet_date).getTime() - now
 await queue.sendMessage({ tweet_text, tweet_date }, delay)
 return { ok: true, tweet_date }
 } catch (e) {
 console.log(e)
 return { ok: false }
 }
}

上記のコードは次のことを行います:

  • queue をインポートします インスタンス
  • schedule という名前のサーバー アクションをエクスポートします。 、スケジュール予定のツイートのテキストと日付を含むフォームの送信を受け入れます。
  • そこからツイートがスケジュールされている時刻までの時間を計算します。
  • 上記で計算した時間に設定された遅延を使用して、日付とテキストを含むツイート オブジェクトを挿入します。

これにより、スケジュールされたときにのみツイートがキューにプッシュされるようになります。これにより、キューの状態を維持するプロセスが容易になり、 キューの状態のみが保証されます。 特定の日にスケジュールされたツイートはキューで利用できます。

OAuth 2.0 PKCE フローを使用して、ユーザーに代わってツイートするための承認をユーザーから取得することに移りましょう。

Twitter OAuth 2.0 によるユーザー認証の実装

このセクションでは、Twitter OAuth クライアントを構成し、認証タスク用に Twitter SDK によって提供されるヘルパー関数を使用して、アプリケーションで Twitter OAuth 2.0 認証フローをセットアップする方法を学習します。認証フローには、認可エンドポイントとコールバック エンドポイントの作成が含まれ、ユーザーがアクセスを許可してトークンを受信できるようにします。アクセス トークンは Upstash Redis に保存されます。また、Upstash Redis に有効なアクセス トークンが存在することを示すエンドポイントを介した認証ステータスも作成します。

まず、ターミナル ウィンドウで以下のコマンドを実行して、Twitter OAuth 2.0 認証の実装に必要なライブラリをインストールします。

npm install twitter-api-sdk

上記のコマンドは、次のパッケージをインストールします。

  • twitter-api-sdk :Twitter API 用の TypeScript SDK。

Twitter 認証クライアントを作成する

Twitter API の複雑さを深く掘り下げずに認証 URL を生成できるようにするには、Twitter SDK による認証クライアントを使用します。ファイル twitter.ts を作成します lib 内 次のコードを含むディレクトリ:

// File: lib/twitter.ts
 
import { auth } from 'twitter-api-sdk'
 
export const authClient = new auth.OAuth2User({
 client_id: process.env.TWITTER_CLIENT_ID as string,
 callback: process.env.TWITTER_AUTH_CALLBACK_URL as string,
 client_secret: process.env.TWITTER_CLIENT_SECRET as string,
 scopes: ['tweet.write', 'tweet.read', 'offline.access', 'users.read'],
})

上記のコードは、Twitter SDK から認証ヘルパーをインポートすることから始まります。次に、認可 URL を生成し、認証されたユーザーにアクセス トークンをリクエストするためのヘルパー関数を提供することで、Twitter API 構文を学習する時間を節約する認証クライアントをエクスポートします。

Twitter 認証 URL を準備する

OAuth 2.0 フローの最初のステップは、ユーザーが認可 URL にリダイレクトされることです。認可 URL は、OAuth 2.0 サーバーによって提供されるエンドポイントで、ユーザーはクライアント アプリケーションにアクセス許可を付与することで認可プロセスを開始するようにリダイレクトされます。通常、ユーザーには複数の選択肢 (Continue with Twitter など) が表示されます。 、Continue with Google 、など)サインイン/アップ画面で、その後、プラットフォーム(ここでは Twitter)がホストする認証画面に移動します。

ファイル app/api/auth/twitter/route.ts を作成します 次のコードを使用します:

// File: app/api/auth/twitter/route.ts
 
export const dynamic = 'force-dynamic'
 
import { NextResponse } from 'next/server'
import { authClient } from '@/lib/twitter'
 
export async function GET() {
 // Obtain an authorization URL from Twitter
 const authUrl = authClient.generateAuthURL({
 state: 'state',
 code_challenge: 'challenge',
 code_challenge_method: 'plain',
 })
 // Return with a 303 as a redirect to the authorization URL
 return NextResponse.redirect(authUrl, 303)
}

上記のコードは次のことを行います:

  • NextResponse をインポートします Web Response API を拡張するヘルパー関数。
  • authClient をインポートします 前に作成しました。
  • GET をエクスポートします /api/auth/twitter で受信した GET リクエストに応答する HTTP ハンドラ .
  • generateAuthURL を使用して認証 URL を生成します。 Twitter SDK のヘルパー関数
  • redirect を使用して、生成された認証 URL にリダイレクトします。 NextResponse のメソッド。

ユーザーが Twitter アプリケーションにアクセスを許可したときにリクエストに応答するエンドポイントの作成に進みましょう。

認可コールバック URL を準備する

OAuth 2.0 フローの 2 番目のステップは、認証プラットフォームからのコールバックに応答することです。 Twitter から受信した承認コールバック リクエストを処理するには、アクセスを許可した後にユーザーがリダイレクトされるエンドポイントをアプリケーション内に構成します。このコールバック URL は認証コードを受信するために不可欠であり、アプリケーションが Upstash Redis で取得したアクセス トークンを保存できるようになります。このトークンを使用すると、アプリケーションの API を介してツイートを自動化できます。

ファイル app/api/auth/callback/twitter/route.ts を作成します 次のコードを使用します:

// File: app/api/auth/callback/twitter/route.ts
 
export const dynamic = 'force-dynamic'
 
import { redis } from '@/lib/upstash'
import { NextResponse } from 'next/server'
import { authClient } from '@/lib/twitter'
 
export async function GET(request: Request) {
 // Look for the callback URL to contain code
 const code = new URL(request.url).searchParams.get('code')
 // If no code query param found, return 403
 if (!code) return NextResponse.json({}, { status: 403 })
 // If code query param found, create another authorization URL to update internal code_verifier
 authClient.generateAuthURL({
 state: 'state',
 code_challenge: 'challenge',
 code_challenge_method: 'plain',
 })
 // Obtain the access_token to use it for making requests in the future
 const {
 token: { access_token },
 } = await authClient.requestAccessToken(code)
 // Save the access_token in Upstash
 await redis.set('twitter_oauth_access_token', access_token)
 // Return back to homepage
 return NextResponse.redirect(new URL('/', request.url), 303)
}

上記のコードは次のことを行います:

  • redis をインポートします Upstash Redis を使用しているインスタンス。
  • NextResponse をインポートします Web Response API を拡張するヘルパー関数。
  • authClient をインポートします 前に作成しました。
  • GET をエクスポートします /api/auth/callback/twitter で受信した GET リクエストに応答する HTTP ハンドラー .
  • code を構造解除します コールバック URL からのクエリ パラメータ。
  • SDK によって作成された内部状態を更新するためのハックとして、前述のように認可 URL を作成します。
  • requestAccessToken を呼び出します Twitter SDK によるアクセス トークンとリフレッシュ トークンを取得する関数。これにより、API 経由でツイートを作成できるようになります。
  • access_token を構造化します。 token から オブジェクトが取得されました。
  • twitter_oauth_access_token で取得したアクセス トークンの値を保存します。 Upstash Redis のキーとして。
  • インデックス URL (/) にリダイレクトします。 ) redirect を使用 NextResponse のメソッド。

これで Twitter OAuth 2.0 フローは完了です。

有効な twitter_oauth_access_token を持っていること Upstash Redis インスタンスの は、認証フローのステータスのインジケーターです。ユーザー インターフェイスで同じことを通信するには、ファイル app/api/auth/twitter/authenticated/route.ts を作成します。 次のコードを使用します:

// File: app/api/auth/twitter/authenticated/route.ts
 
export const dynamic = 'force-dynamic'
 
import { redis } from '@/lib/upstash'
import { NextResponse } from 'next/server'
 
export async function GET() {
 try {
 const access_token = await redis.get<string>('twitter_oauth_access_token')
 if (!access_token) return NextResponse.json({ ok: false }, { status: 200 })
 return NextResponse.json({ ok: true }, { status: 200 })
 }
 catch(e) {}
 return NextResponse.json({ ok: false }, { status: 200 })
}

上記のコードは次のことを行います:

  • redis をインポートします Upstash Redis を使用しているインスタンス。
  • NextResponse をインポートします Web Response API を拡張するヘルパー関数。
  • GET をエクスポートします /api/auth/twitter/authenticated で受信した GET リクエストに応答する HTTP ハンドラー .
  • twitter_oauth_access_token に関連付けられた値を取得します Upstash Redis でキーを押します。
  • ok を含む JSON 応答を返します。 Upstash Redis に有効なアクセス トークンが存在するかどうかを示すブール値。

作成したこれらの API エンドポイントを使用するためのユーザー インターフェースの作成に移りましょう。

ツイートをスケジュールするためのユーザー インターフェイスを構築する

このセクションでは、React フック useFormState を使用してリアクティブ フォーム ステートを作成する方法を学習します。 および useFormStatus 、サーバー アクションを呼び出してツイートをスケジュールします。

まず、スケジュールされるツイートの情報を含むフォームをレンダリングし、ツイート情報があるかどうかを示すトースト通知を表示する React コンポーネントを作成します。ファイル app/form.tsx を作成します 次のコードを使用します:

// File: app/form.tsx
 
'use client'
 
// UI Imports
import { cn } from '@/lib/utils'
import { format } from 'date-fns'
import { Button } from '@/components/ui/button'
import { Calendar } from '@/components/ui/calendar'
import { useToast } from '@/components/ui/use-toast'
import { Textarea } from '@/components/ui/textarea'
import { Calendar as CalendarIcon } from 'lucide-react'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
 
// Form Status hook
import { useFormStatus } from 'react-dom'
import { useEffect, useState } from 'react'
 
// Define Form Props
export interface FormProps {
 ok?: boolean
 tweet_date?: string
}
 
export default function ({ ok, tweet_date }: FormProps) {
 const { toast } = useToast()
 // Use React's useFormStatus hook to detect form submission state
 const { pending } = useFormStatus()
 
 useEffect(() => {
 // If the form is not pending
 if (!pending) {
 // If the server ok-ed the query, reset the form
 if (ok) {
 const scheduleForm = document.getElementById('schedule_form') as HTMLFormElement
 if (scheduleForm) scheduleForm.reset()
 // Display that scheduling was succesful
 toast({
 title: 'Scheduled Tweet',
 description: tweet_date,
 })
 } else {
 // Display that scheduling failed
 toast({
 variant: 'destructive',
 title: 'Uh oh! Something went wrong.',
 description: 'There was a problem with your request.',
 })
 }
 }
 }, [pending])
 
 // Listen to the date picker changes
 const [date, setDate] = useState<Date>()
 
 return (
 <>
 <span className="font-semibold">Tweet Scheduler</span>
 {/* Date Picker for Scheduling Tweet on future dates */}
 <input id="tweet_date" name="tweet_date" className="hidden" value={date?.toString()} />
 <Popover>
 <PopoverTrigger asChild>
 <Button variant={'outline'} className={cn('w-[280px] justify-start text-left font-normal', !date && 'text-muted-foreground')}>
 <CalendarIcon className="mr-2 h-4 w-4" />
 {date ? format(date, 'PPP') : <span>Pick a date</span>}
 </Button>
 </PopoverTrigger>
 <PopoverContent className="w-auto p-0">
 <Calendar mode="single" selected={date} onSelect={setDate} />
 </PopoverContent>
 </Popover>
 {/* Text Area for Entering Text of Tweet */}
 <Textarea id="tweet_text" name="tweet_text" className="min-h-[300px] w-[280px]" placeholder="Tweet" />
 {/* Schedule Button Tweet */}
 <Button disabled={pending} className="w-[280px]">
 {pending ? 'Scheduling...' : <>Schedule &rarr;</>}
 </Button>
 </>
 )
}

上記のコードは次のことを行います:

  • shadcn/ui によって作成されたコンポーネントをインポートします CLI コマンドを以前に実行しました。
  • 視覚的に非表示の input をレンダリングする React コンポーネントをエクスポートします。 スケジュールされたツイートの日付を記述する HTML 要素。
  • コンポーネントは textarea もレンダリングします ユーザーからツイートのテキストを視覚的に受け入れるための HTML 要素。
  • コンポーネントは Button もレンダリングします。 これは、以前のフォーム送信のステータスに基づいて条件付きで無効になります。
  • コンポーネントは useEffect も使用します サーバーアクションが成功した場合にフォームをリセットするフック。いずれの場合も、リクエストのステータスを示すトースト通知が右下隅に表示されます。

次に、ユーザーの Twitter 認証ステータスを表示するコンポーネントを作成します。ファイル components/twitter.tsx を作成します 次のコードを使用します:

// File: components/twitter.tsx
 
'use client'
 
import { useEffect, useState } from 'react'
import { Button } from '@/components/ui/button'
 
export default function () {
 const state: { [k: string]: { message: string; variant: 'outline' | 'secondary' | 'destructive' } } = {
 pending: {
 message: '...',
 variant: 'outline',
 },
 true: {
 message: '✔️ Authenticated Instance',
 variant: 'secondary',
 },
 false: {
 message: '1-Time Authentication with Twitter →',
 variant: 'destructive',
 },
 }
 
 const [authenticated, setAuthenticated] = useState<string | boolean>('pending')
 useEffect(() => {
 fetch('/api/auth/twitter/authenticated')
 .then((res) => res.json())
 .then((res) => {
 setAuthenticated(res.ok as boolean)
 })
 }, [])
 
 {
 /* Authenticate with Twitter */
 }
 return (
 <Button
 className="w-[280px]"
 onClick={() => {
 if (!authenticated) window.location.href = '/api/auth/twitter'
 }}
 variant={state[authenticated.toString()].variant}
 >
 {state[authenticated.toString()].message}
 </Button>
 )
}

上記のコードは次のことを行います:

  • useEffect をインポートします および useState React によってフックされ、ユーザー認証のステータスを取得するために使用されます。
  • Button をレンダリングする React コンポーネントをエクスポートします。 コンポーネント (shadcn/ui による) )さまざまな状態で、それぞれをユーザーの Twitter 認証ステータスに関連付けます。

ユーザーがインデックス ルートを開くときにインタラクションとツイートのスケジュールを設定できるフォームをレンダリングします (例:/)。 )、ファイル app/page.tsx を作成します。 次のコードを使用します:

// File: app/page.tsx
 
'use client'
 
// Form with Pending Status
import Form from './form'
 
// Form with access to the server returned data
import { useFormState } from 'react-dom'
 
// Scheduling Next.js Action
import Twitter from '@/components/twitter'
import { schedule } from './schedule.server'
 
export default function () {
 const [state, formAction] = useFormState(schedule, {})
 return (
 <div className="flex w-[300px] flex-col gap-y-3 p-5">
 <Twitter />
 <form id="schedule_form" action={formAction} className="flex w-[300px] flex-col gap-y-3">
 <Form {...state} />
 </form>
 </div>
 )
}

上記のコードは次のことを行います:

  • Form をインポートします および Twitter 以前に作成したコンポーネント
  • useFormState をインポートします React によるフックにより、state を使用して Next.js サーバー アクションによって返されたデータを処理できるようになります。 変数を設定し、フォーム送信を通じてサーバー アクションの呼び出しを許可します。
  • schedule をインポートします 以前に作成されたサーバー アクション。
  • <form> を含む React コンポーネントをエクスポートします。 schedule_form のコンポーネント id であり、formAction を呼び出すように設定されています。 ユーザーがフォームを送信したとき。

Upstash QStash を使用してツイートをスケジュールする

ユーザーに代わってツイートをスケジュールするには、Upstash Queue に保存されているツイート データを使用するエンドポイントを作成し、Twitter API に POST してツイートを実行します。ファイル app/api/schedule/route.ts を作成します 次のコードを使用します:

// File: app/api/schedule/route.ts
 
export const dynamic = 'force-dynamic'
 
import { NextResponse } from 'next/server'
import { queue, redis } from '@/lib/upstash'
import { verifySignatureAppRouter } from '@upstash/qstash/dist/nextjs'
 
interface TweetBody {
 tweet_text?: string
 tweet_date?: number
}
 
async function tweet(access_token: string, text: string | undefined) {
 if (text) {
 await fetch('https://api.twitter.com/2/tweets', {
 method: 'POST',
 headers: {
 'Content-Type': 'application/json',
 Authorization: ['Bearer', access_token].join(' '),
 },
 body: JSON.stringify({ text }),
 })
 }
}
 
async function handler() {
 const access_token = await redis.get<string>('twitter_oauth_access_token')
 if (!access_token) return NextResponse.json({}, { status: 403 })
 const tweets = await Promise.all(Array.from({ length: 4 }, () => queue.receiveMessage<TweetBody>()))
 await Promise.all(tweets.map((i) => tweet(access_token, i?.body?.tweet_text)))
 return NextResponse.json({}, { status: 200 })
}
 
export const POST = verifySignatureAppRouter(handler)

上記のコードは次のことを行います:

  • redis をインポートします と queue Upstash Redis と Upstash Queue をそれぞれ使用するインスタンス
  • verifySignatureAppRouter をインポートします Upstash による機能。リクエストの署名を検証して、リクエストが QStash からのみであることを確認します。
  • 関数 tweet を作成します ツイート テキストとアクセス トークンを受け入れ、認証されたユーザーに代わってツイートを実行します。
  • POST を作成します /api/schedule で受信した POST リクエストに応答する HTTP ハンドラ 。 Upstash キューから 4 つのメッセージをフェッチし、tweet を呼び出します。 ユーザーに代わってツイートを実行する機能

Upstash QStash を使用すると、ツイートを実行するプロセスをスケジュールできます。毎日深夜にプロセスが自動的に開始され、ツイートが送信されるように自動化したいとします。これを行うには、前に作成したエンドポイント /api/schedule を使用します。 QStash 内。

Upstash でツイート スケジューラを作成する:ステップバイステップ ガイド

Upstash コンソールの [QStash] タブに移動し、[Request Builder] タブまで下にスクロールして、次の操作を実行します。

  • Endpoint を選択します タブ。
  • URL を入力します。 /api/schedule への絶対 URL として エンドポイント。
  • Type を選択します Scheduled として .
  • Every を選択します every day at midnight として .
  • Schedule をクリックします .

上記の手順により、/api/schedule に POST するジョブが作成されました。 毎日真夜中。

とても勉強になりました!これですべて完了です ✨

Vercel に展開

これで、リポジトリを Vercel にデプロイする準備が整いました。導入するには、次の手順を使用します。

  • まず、アプリのコードを含む GitHub リポジトリを作成します。
  • 次に、Vercel ダッシュボードに移動し、新しいプロジェクトを作成します。 .
  • 新しいプロジェクトを、作成したばかりの GitHub リポジトリにリンクします。
  • 設定内 、Environment Variables を更新します。  ローカルの .env にあるものと一致するようにする  ファイル。
  • Deploy をクリックします .

詳細情報

さらに詳しい洞察については、この投稿で引用されている参考文献を参照してください。

  • GitHub リポジトリ
  • Twitter OAuth 2.0 フロー
  • Twitter アプリ トークンの生成
  • React フォームフック
  • Next.js サーバーのアクション

結論

このガイドでは、Upstash の強力な Redis データベースと QStash キューを活用して、堅牢なツイート スケジューラを構築する方法を学びました。 Upstash のスケーラビリティにより、信頼性の高いストレージとツイートのスケジュール設定が Vercel でのシームレスな展開と組み合わされて、完全に自動化されたシステムを実現します。


  1. RedisDays NewYork2022の概要

    ロンドンですべてのリアルタイムデータを中心とした1日を開始し、続いてサンフランシスコで開発者に焦点を当てた1日を過ごした後、RedisDays 2022はニューヨークで終了し、最新のRedis開発に関するすべてのセッションが行われました。人工知能/機械学習(AI / ML)で。 RedisDays New Yorkのセッションでは、最新のデータスタックはパフォーマンスファーストのアプローチで構築する必要があることが明らかになりました。つまり、基調講演でRedisCMOのMikeAnandが説明したように、「最新のデータモデルと処理エンジンをサポートし、AI / MLを有効にし、コンポーザブ

  2. Redis ZRANGE –Ascランク範囲でソートされたセットの要素を取得する方法

    このチュートリアルでは、特定の範囲の間でスコアの昇順でランク付けされた、並べ替えられた設定値の1つ以上の要素を取得する方法について学習します。このために、Redis ZRANGEを使用します コマンド。 ZRANGEコマンド ZRANGEコマンドは、指定された範囲で定義された、指定されたキーに保管されているソート済み設定値の1つ以上の要素を返します。並べ替えられたセットの要素は、スコアの昇順です。スコアが等しい要素には、辞書式順序の昇順が使用されます。 範囲は、開始(包括的)オフセットと終了(包括的)オフセットによって定義されます。これらのオフセットはゼロベースのインデックスであり、