ในคำแนะนำทีละขั้นตอนนี้ ฉันพูดถึงวิธีที่ฉันสร้าง Tweet Scheduler โดยใช้ Upstash QStash, Upstash Redis, Next.js Server Actions และ Vercel การกำหนดเวลาโพสต์ Twitter ช่วยให้คุณคงสถานะที่สม่ำเสมอ มีส่วนร่วมกับผู้ชมของคุณในเวลาที่เหมาะสม และจัดการกลยุทธ์เนื้อหาของคุณได้อย่างมีประสิทธิภาพ
ข้อกำหนดเบื้องต้น
คุณจะต้องมีสิ่งต่อไปนี้:
- Node.js 18 หรือใหม่กว่า
- บัญชี Upstash
- บัญชีทวิตเตอร์
- บัญชี Vercel
กลุ่มเทคโนโลยี
คู่มือนี้ใช้เทคโนโลยีต่อไปนี้:
ขั้นตอน
หากต้องการทำตามคำแนะนำนี้ให้เสร็จสิ้นและปรับใช้ตัวกำหนดเวลาทวีตของคุณเอง คุณจะต้องทำตามขั้นตอนเหล่านี้:
- การตั้งค่า Upstash Redis
- การตั้งค่า Upstash QStash
- การตั้งค่าแอปพลิเคชันนักพัฒนา Twitter
- สร้างแอปพลิเคชัน Next.js ใหม่
- ใช้การตรวจสอบสิทธิ์ผู้ใช้ด้วย Twitter OAuth 2.0
- สร้างอินเทอร์เฟซผู้ใช้เพื่อกำหนดเวลาทวีต
- กำหนดเวลาทวีตโดยใช้ Upstash QStash
- ปรับใช้กับ Vercel
การตั้งค่า Upstash Redis
เมื่อคุณสร้างบัญชี Upstash และเข้าสู่ระบบแล้ว คุณจะไปที่แท็บ Redis และสร้างฐานข้อมูล


หลังจากที่คุณสร้างฐานข้อมูลแล้ว ให้เลื่อนลงไปจนกว่าคุณจะพบส่วน REST API และเลือก 09 ปุ่ม คัดลอกเนื้อหาและบันทึกไว้ในที่ที่ปลอดภัย

การตั้งค่าอัพสแตช QStash
หากต้องการกำหนดเวลาคำขอ POST ไปยังจุดสิ้นสุดการกำหนดเวลาในช่วงเวลาที่กำหนด คุณจะใช้ QStash ไปที่แท็บ QStash และเลื่อนลงไปที่แท็บตัวสร้างคำขอ

คัดลอก QStash URL, TOKEN, คีย์การลงนามปัจจุบัน และคีย์การลงนามถัดไป และบันทึกไว้ในที่ที่ปลอดภัย

การตั้งค่าแอปพลิเคชันนักพัฒนา Twitter
หากต้องการตั้งค่าการรับรองความถูกต้องด้วย Twitter OAuth 2.0 คุณจะต้องสร้างแอปพลิเคชันในพอร์ทัลนักพัฒนา Twitter หากต้องการตั้งค่าแอปพลิเคชัน Twitter ให้ทำดังต่อไปนี้:
- เปิดพอร์ทัลนักพัฒนาของ Twitter> โครงการ
- สร้างโครงการ
- ไปที่แท็บการตั้งค่าในการตั้งค่าแอปพลิเคชันของคุณ และดำเนินการดังต่อไปนี้:
- เลือก
14ในการอนุญาตของแอป . - เลือก
22ในประเภทของแอป . - กรอก
32เป็น URI เรียกกลับ / URL ตอบกลับ .
- เลือก
- ไปที่
41ในการตั้งค่าแอปพลิเคชันของคุณ ให้เลื่อนลงและดำเนินการดังต่อไปนี้:- คัดลอก
54และเก็บไว้ที่ไหนสักแห่งที่ปลอดภัยเป็น63. - คัดลอก
78และเก็บไว้ที่ไหนสักแห่งที่ปลอดภัยเป็น82.
- คัดลอก
นั่นคือทั้งหมดที่คุณต้องมีเพื่อตั้งค่าแอปพลิเคชัน Twitter Developer สำหรับ OAuth 2.0 ให้สำเร็จ
สร้างแอปพลิเคชัน Next.js ใหม่
เริ่มต้นด้วยการสร้างโครงการ Next.js ใหม่ เปิดเทอร์มินัลของคุณและรันคำสั่งต่อไปนี้:
npx create-next-app@latest schedule-qstash-queue-upstash เมื่อได้รับแจ้ง ให้เลือก:
97รหัส> เมื่อได้รับแจ้งให้ใช้ TypeScript108รหัส> เมื่อได้รับแจ้งให้ใช้ ESLint117รหัส> เมื่อได้รับแจ้งให้ใช้ Tailwind CSS129รหัส> เมื่อได้รับแจ้งให้ใช้130ไดเร็กทอรี143รหัส> เมื่อได้รับแจ้งให้ใช้ App Router157รหัส> เมื่อได้รับแจ้งให้ปรับแต่งนามแฝงการนำเข้าเริ่มต้น (167).
เมื่อเสร็จแล้ว ให้ย้ายไปยังไดเร็กทอรีโปรเจ็กต์และเริ่มแอปในโหมดการพัฒนาโดยดำเนินการคำสั่งต่อไปนี้:
cd schedule-qstash-queue-upstash
npm run dev แอปควรทำงานบน localhost:3000
ตอนนี้ สร้าง 179 ไฟล์ที่รากของโครงการของคุณ คุณกำลังจะเพิ่มรายการที่เราบันทึกไว้จากส่วนด้านบน
มันควรมีลักษณะดังนี้:
# .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
หากต้องการสร้างต้นแบบอินเทอร์เฟซผู้ใช้อย่างรวดเร็ว คุณจะต้องตั้งค่า 181 ด้วย Next.js 190รหัส> คือชุดของส่วนประกอบที่ออกแบบมาอย่างสวยงามซึ่งคุณสามารถคัดลอกและวางลงในแอปของคุณได้ ในหน้าต่างเทอร์มินัลของคุณ ให้รันคำสั่งด้านล่างเพื่อเริ่มการตั้งค่า 206 :
npx shadcn-ui@latest init
คุณจะถูกถามคำถามสองสามข้อเพื่อกำหนดค่า 219 ให้เลือกดังต่อไปนี้:
222รหัส> เมื่อได้รับแจ้งให้ใช้ TypeScript236รหัส> เมื่อได้รับแจ้งให้เลือกสไตล์ที่จะใช้240รหัส> เมื่อได้รับแจ้งให้เลือกสีพื้นฐาน259รหัส> เมื่อได้รับแจ้งให้ป้อนไฟล์ CSS ส่วนกลาง267รหัส> เมื่อได้รับแจ้งให้ใช้ตัวแปร CSS สำหรับสี273รหัส> เมื่อได้รับแจ้งให้ป้อนคำนำหน้า tailwind ที่กำหนดเอง285รหัส> เมื่อได้รับแจ้งให้ป้อนตำแหน่งของ tailwind.config.js295รหัส> เมื่อได้รับแจ้งให้กำหนดค่านามแฝงสำหรับส่วนประกอบ304รหัส> เมื่อได้รับแจ้งให้กำหนดค่านามแฝงสำหรับยูทิลิตี้315รหัส> เมื่อได้รับแจ้งให้เลือกการใช้งานส่วนประกอบเซิร์ฟเวอร์ React322รหัส> เมื่อได้รับแจ้งให้ดำเนินการเขียนการกำหนดค่าไปยังส่วนประกอบ.json
เมื่อเสร็จแล้ว คุณได้ตั้งค่า CLI ที่ช่วยให้เราสามารถเพิ่มส่วนประกอบ React ลงในแอปพลิเคชัน Next.js ของคุณได้อย่างง่ายดาย ถัดไป ในหน้าต่างเทอร์มินัลของคุณ ให้รันคำสั่งด้านล่างเพื่อรับองค์ประกอบปุ่ม อินพุต พื้นที่ข้อความ ป๊อปโอเวอร์ ปฏิทิน และขนมปังปิ้ง:
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
เมื่อเสร็จแล้ว คุณจะเห็น 331 ไดเรกทอรีภายใน 342 ไดเร็กทอรีที่มี 358 , 361รหัส> , 371รหัส> , 384รหัส> , 394รหัส> , 405รหัส> , 413รหัส> , 428รหัส> และ 431 .
จากนั้น เปิด 440 ไฟล์และทำการเพิ่มเติมต่อไปนี้:
+ // 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>
)
}
ในการเปลี่ยนแปลงโค้ดข้างต้น คุณได้นำเข้า 457 แล้ว ส่วนประกอบ (สร้างโดย 463 ) และตรวจสอบให้แน่ใจว่ามีอยู่ในแอปพลิเคชัน Next.js ทั้งหมดของคุณ ช่วยให้คุณสามารถแสดงการแจ้งเตือนแบบโทสต์ได้จากทุกที่ในโค้ดของคุณผ่านทาง 474 ขอเกี่ยว.
สร้างคิวขั้นสูงเพื่อจัดเก็บทวีตตามกำหนดเวลา
ในส่วนนี้ คุณจะได้เรียนรู้วิธีใช้ Upstash Queue เพื่อจัดเก็บข้อมูลทวีตตามกำหนดเวลา คุณจะได้เรียนรู้วิธีสร้างโค้ดฝั่งเซิร์ฟเวอร์ซึ่งเรียกใช้เป็นฟังก์ชันแทนการใช้บนเส้นทาง API โดยใช้การดำเนินการของเซิร์ฟเวอร์ Next.js
ขั้นแรก ในหน้าต่างเทอร์มินัลของคุณ ให้ดำเนินการต่อไปนี้เพื่อติดตั้ง Upstash SDK:
npm install @upstash/qstash @upstash/queue @upstash/redis@1.28.0 คำสั่งดังกล่าวจะติดตั้งแพ็คเกจต่อไปนี้:
488รหัส> :SDK เพื่อโต้ตอบกับอินสแตนซ์ Upstash QStash ของคุณผ่านคำขอ HTTP493รหัส> :SDK เพื่อจัดการคิวข้อความตามสตรีม สนับสนุนโดย Upstash Redis504รหัส> :SDK เพื่อโต้ตอบผ่านคำขอ HTTP ด้วย Redis ซึ่งสร้างขึ้นบน Upstash REST API
เริ่มต้นไคลเอนต์ Upstash Redis และ Upstash Queue
หากต้องการใช้ไลบรารีที่ติดตั้งด้านบนเพื่อโต้ตอบกับ Upstash Queue ของคุณ ให้สร้างไฟล์ 517 ด้วยรหัสต่อไปนี้:
// 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,
}) โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
529และ533คลาสที่ส่งออกโดยแพ็คเกจ - ส่งออก
545อินสแตนซ์ที่ชี้ไปที่ Upstash Redis URL พร้อมด้วยโทเค็นการอนุญาตคำขอ - ส่งออก
553อินสแตนซ์ที่ชี้ไปที่ Upstash Redis ที่สร้างขึ้นด้านบน ตั้งชื่อคิวเป็น560และ575ถึง 5 ทำให้สามารถประมวลผลข้อความพร้อมกันได้สูงสุด 5 รายการ
เมื่อใช้อินสแตนซ์คิว คุณจะสร้างการดำเนินการเซิร์ฟเวอร์ Next.js ที่จะยอมรับข้อความทวีตและวันที่ทวีตเพื่อสร้างและผลักดันออบเจ็กต์ทวีตเข้าไปในคิวสำหรับการประมวลผลในอนาคต สร้างไฟล์ 580 ด้วยรหัสต่อไปนี้:
// 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 }
}
} โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
599ตัวอย่าง - ส่งออกการทำงานของเซิร์ฟเวอร์ชื่อ
605ที่ยอมรับการส่งแบบฟอร์มที่มีข้อความและวันที่ของทวีตตามกำหนดเวลา - คำนวณเวลาระหว่างนั้นจนถึงเวลาที่ทวีตถูกกำหนดไว้
- แทรกวัตถุทวีตที่มีวันที่และข้อความที่มีการหน่วงเวลาที่ตั้งไว้เป็นเวลาที่คำนวณไว้ข้างต้น
ด้วยวิธีนี้ คุณจึงมั่นใจได้ว่าทวีตจะถูกผลักไปที่คิวเฉพาะเมื่อมีการกำหนดเวลาไว้เท่านั้น วิธีนี้ช่วยลดความยุ่งยากในการรักษาสถานะของคิว ทำให้มั่นใจได้ว่า เท่านั้น ทวีตที่กำหนดไว้ในแต่ละวันจะอยู่ในคิว
มาดูการขออนุญาตจากผู้ใช้เพื่อทวีตในนามของพวกเขาโดยใช้โฟลว์ PKCE ของ OAuth 2.0
ใช้การตรวจสอบสิทธิ์ผู้ใช้ด้วย Twitter OAuth 2.0
ในส่วนนี้ คุณจะได้เรียนรู้วิธีตั้งค่าขั้นตอนการตรวจสอบสิทธิ์ Twitter OAuth 2.0 ในแอปพลิเคชันของคุณโดยการกำหนดค่าไคลเอนต์ Twitter OAuth และใช้ฟังก์ชันตัวช่วยที่ Twitter SDK มอบให้สำหรับงานการตรวจสอบสิทธิ์ ขั้นตอนการตรวจสอบสิทธิ์เกี่ยวข้องกับการสร้างการอนุญาตและจุดสิ้นสุดการโทรกลับ ทำให้ผู้ใช้สามารถให้สิทธิ์การเข้าถึงและรับโทเค็น โดยโทเค็นการเข้าถึงจะถูกจัดเก็บไว้ใน Upstash Redis คุณยังจะสร้างสถานะการตรวจสอบสิทธิ์ผ่านจุดสิ้นสุดที่ระบุว่ามีโทเค็นการเข้าถึงที่ถูกต้องใน Upstash Redis
ขั้นแรก ในหน้าต่างเทอร์มินัลของคุณ ให้รันคำสั่งด้านล่างเพื่อติดตั้งไลบรารีที่จำเป็นสำหรับการใช้การรับรองความถูกต้อง Twitter OAuth 2.0:
npm install twitter-api-sdk คำสั่งดังกล่าวจะติดตั้งแพ็คเกจต่อไปนี้:
611รหัส> :TypeScript SDK สำหรับ Twitter API
สร้างไคลเอนต์การตรวจสอบสิทธิ์ Twitter
เพื่อให้สามารถสร้าง URL การอนุญาตโดยไม่ต้องเจาะลึกความซับซ้อนของ Twitter API คุณจะต้องใช้ไคลเอนต์การรับรองความถูกต้องโดย Twitter SDK สร้างไฟล์ 625 ภายใน 632 ไดเร็กทอรีด้วยรหัสต่อไปนี้:
// 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 จากนั้นจะส่งออกไคลเอ็นต์การตรวจสอบสิทธิ์ซึ่งจะช่วยประหยัดเวลาในการเรียนรู้ไวยากรณ์ Twitter API โดยจัดให้มีฟังก์ชันตัวช่วยในการสร้าง URL การอนุญาตและขอโทเค็นการเข้าถึงจากผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์
เตรียม URL การอนุญาต Twitter
ขั้นตอนแรกในโฟลว์ OAuth 2.0 คือผู้ใช้จะถูกเปลี่ยนเส้นทางไปยัง URL การให้สิทธิ์ URL การอนุญาตเป็นจุดสิ้นสุดที่เซิร์ฟเวอร์ OAuth 2.0 มอบให้ โดยที่ผู้ใช้ถูกเปลี่ยนเส้นทางเพื่อเริ่มกระบวนการอนุญาตโดยการให้สิทธิ์แก่แอปพลิเคชันไคลเอนต์ โดยปกติ ผู้ใช้จะมีตัวเลือกหลายตัวเลือก (เช่น 643 , 658รหัส> ฯลฯ) ที่หน้าจอลงชื่อเข้าใช้/อัป จากนั้นจะพาไปยังหน้าจอการอนุญาตที่โฮสต์ไว้ของแพลตฟอร์ม (ที่นี่ Twitter)
สร้างไฟล์ 663 ด้วยรหัสต่อไปนี้:
// 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)
} โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
675ฟังก์ชันตัวช่วยที่ขยาย Web Response API - นำเข้า
684สร้างไว้ก่อนหน้านี้ - ส่งออก
697ตัวจัดการ HTTP ซึ่งตอบสนองต่อคำขอ GET ขาเข้าบน707. - สร้าง URL การอนุญาตโดยใช้
711ฟังก์ชันตัวช่วยของ Twitter SDK - เปลี่ยนเส้นทางไปยัง URL การอนุญาตที่สร้างขึ้นโดยใช้
725วิธีการ NextResponse
เรามาต่อกันที่การสร้างอุปกรณ์ปลายทางที่ตอบสนองต่อคำขอเมื่อผู้ใช้อนุญาตแอปพลิเคชัน Twitter ของคุณด้วยการเข้าถึง
เตรียม URL โทรกลับเพื่อขออนุมัติ
ขั้นตอนที่สองในโฟลว์ OAuth 2.0 ตอบสนองต่อการโทรกลับจากแพลตฟอร์มการตรวจสอบสิทธิ์ ในการจัดการคำขอโทรกลับการอนุญาตที่เข้ามาจาก Twitter คุณจะต้องกำหนดค่าตำแหน่งข้อมูลในแอปพลิเคชันของคุณซึ่งผู้ใช้จะถูกเปลี่ยนเส้นทางหลังจากให้สิทธิ์การเข้าถึง URL โทรกลับนี้จำเป็นสำหรับการรับรหัสอนุญาต ทำให้แอปพลิเคชันของคุณสามารถบันทึกโทเค็นการเข้าถึงที่ได้รับใน Upstash Redis ด้วยโทเค็นนั้น คุณสามารถทวีตอัตโนมัติผ่าน API ในแอปพลิเคชันของคุณได้
สร้างไฟล์ 730 ด้วยรหัสต่อไปนี้:
// 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)
} โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
748อินสแตนซ์ที่ใช้ Upstash Redis - นำเข้า
758ฟังก์ชันตัวช่วยที่ขยาย Web Response API - นำเข้า
760สร้างไว้ก่อนหน้านี้ - ส่งออก
773ตัวจัดการ HTTP ซึ่งตอบสนองต่อคำขอ GET ขาเข้าบน786. - ทำลายโครงสร้าง
790พารามิเตอร์การค้นหาจาก URL โทรกลับ - สร้าง URL การอนุญาตเหมือนก่อนหน้านี้เป็นแฮ็กเพื่ออัปเดตสถานะภายในที่สร้างโดย SDK
- เรียก
808ทำงานโดย Twitter SDK เพื่อรับการเข้าถึงและรีเฟรชโทเค็น ซึ่งจะช่วยให้คุณสร้างทวีตผ่าน API ได้ - ทำลายโครงสร้าง
810จาก824วัตถุที่ได้รับ - บันทึกค่าโทเค็นการเข้าถึงที่ได้รับด้วย
833เป็นกุญแจสำคัญใน Upstash Redis - เปลี่ยนเส้นทางไปยัง URL ดัชนี (
849) โดยใช้859วิธีการ NextResponse
ตอนนี้คุณดำเนินการขั้นตอน Twitter OAuth 2.0 เสร็จแล้ว
มี 865 ที่ถูกต้อง ในอินสแตนซ์ Upstash Redis เป็นตัวบ่งชี้สถานะโฟลว์การตรวจสอบสิทธิ์ หากต้องการสื่อสารสิ่งเดียวกันในส่วนติดต่อผู้ใช้ ให้สร้างไฟล์ 879 ด้วยรหัสต่อไปนี้:
// 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 })
} โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
880อินสแตนซ์ที่ใช้ Upstash Redis - นำเข้า
892ฟังก์ชันตัวช่วยที่ขยาย Web Response API - ส่งออก
900ตัวจัดการ HTTP ซึ่งตอบสนองต่อคำขอ GET ขาเข้าบน916. - ดึงค่าที่เกี่ยวข้องกับ
928คีย์ใน Upstash Redis - ส่งคืนการตอบสนอง JSON ที่มี
938บูลีนที่ระบุว่ามีโทเค็นการเข้าถึงที่ถูกต้องอยู่ใน Upstash Redis หรือไม่
มาดูการสร้างอินเทอร์เฟซผู้ใช้เพื่อใช้จุดสิ้นสุด API ที่คุณสร้างขึ้นกันดีกว่า
สร้างอินเทอร์เฟซผู้ใช้เพื่อกำหนดเวลาทวีต
ในส่วนนี้ คุณจะได้เรียนรู้วิธีสร้างสถานะแบบฟอร์มเชิงโต้ตอบโดยใช้ React hooks 947 และ 958 และเรียกใช้การทำงานของเซิร์ฟเวอร์เพื่อกำหนดเวลาทวีต
ขั้นแรก คุณจะต้องสร้างส่วนประกอบ React ที่แสดงแบบฟอร์มที่มีข้อมูลทวีตที่จะกำหนดเวลาไว้ และแสดงการแจ้งเตือนแบบโทสต์ที่ระบุว่าข้อมูลทวีตนั้นหรือไม่ สร้างไฟล์ 963 ด้วยรหัสต่อไปนี้:
// 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 →</>}
</Button>
</>
)
} โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้าส่วนประกอบที่สร้างโดย
974คำสั่ง CLI ก่อนหน้านี้ - ส่งออกองค์ประกอบ React ที่แสดง
986ที่ซ่อนไว้ด้วยสายตา องค์ประกอบ HTML ที่อธิบายวันที่ของทวีตตามกำหนดเวลา - ส่วนประกอบยังแสดงผล
991องค์ประกอบ HTML เพื่อยอมรับข้อความทวีตจากผู้ใช้ด้วยสายตา - ส่วนประกอบยังแสดงผล
1004ซึ่งถูกปิดใช้งานตามเงื่อนไขตามสถานะของการส่งแบบฟอร์มก่อนหน้า - ส่วนประกอบยังใช้
1014ขอเพื่อรีเซ็ตแบบฟอร์มหากการกระทำของเซิร์ฟเวอร์ส่งผลให้สำเร็จ ไม่ว่าจะด้วยวิธีใด ระบบจะแสดงการแจ้งเตือนแบบปิ้งที่มุมขวาล่างเพื่อระบุสถานะของคำขอ
ต่อไป คุณจะสร้างส่วนประกอบที่แสดงสถานะสถานะการตรวจสอบสิทธิ์ Twitter ของผู้ใช้ สร้างไฟล์ 1027 ด้วยรหัสต่อไปนี้:
// 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>
)
} โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
1038และ1048hooks โดย React เพื่อใช้ในการดึงข้อมูลสถานะของการตรวจสอบสิทธิ์ผู้ใช้ - ส่งออกส่วนประกอบ React ที่แสดงผล
1057ส่วนประกอบ (โดย1061) ในสถานะที่แตกต่างกัน โดยเชื่อมโยงแต่ละสถานะกับสถานะการตรวจสอบสิทธิ์ Twitter ของผู้ใช้
เพื่อแสดงแบบฟอร์มสำหรับผู้ใช้ที่อนุญาตให้พวกเขาโต้ตอบและกำหนดเวลาทวีตขณะที่พวกเขาเปิดเส้นทางดัชนี (เช่น 1074 ) สร้างไฟล์ 1083 ด้วยรหัสต่อไปนี้:
// 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>
)
} โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
1090และ1106ส่วนประกอบที่สร้างขึ้นก่อนหน้านี้ - นำเข้า
1117hook โดย React เพื่อให้สามารถประมวลผลข้อมูลที่ส่งคืนโดยการกระทำของเซิร์ฟเวอร์ Next.js โดยใช้1121ตัวแปรและอนุญาตให้เรียกใช้การกระทำของเซิร์ฟเวอร์ผ่านการส่งแบบฟอร์ม - นำเข้า
1136การทำงานของเซิร์ฟเวอร์ที่สร้างขึ้นก่อนหน้านี้ - ส่งออกส่วนประกอบ React ที่มี
1147ส่วนประกอบที่มี1150id และตั้งค่าให้เรียกใช้1169เมื่อผู้ใช้ส่งแบบฟอร์ม
กำหนดเวลาทวีตโดยใช้ Upstash QStash
หากต้องการกำหนดเวลาทวีตในนามของผู้ใช้ คุณจะต้องสร้างตำแหน่งข้อมูลที่จะใช้ข้อมูลทวีตที่จัดเก็บไว้ใน Upstash Queue จากนั้น POST ไปที่ Twitter API เพื่อดำเนินการทวีต สร้างไฟล์ 1176 ด้วยรหัสต่อไปนี้:
// 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) โค้ดด้านบนทำหน้าที่ดังต่อไปนี้:
- นำเข้า
1188และ1193อินสแตนซ์ที่ใช้ Upstash Redis และ Upstash Queue ตามลำดับ - นำเข้า
1203ฟังก์ชั่นโดย Upstash ที่จะตรวจสอบลายเซ็นคำขอเพื่อให้แน่ใจว่าคำขอมาจาก QStash เท่านั้น - สร้างฟังก์ชัน
1218ที่ยอมรับข้อความทวีตและโทเค็นการเข้าถึงเพื่อดำเนินการทวีตในนามของผู้ใช้ที่ได้รับการรับรองความถูกต้อง - สร้าง
1220ตัวจัดการ HTTP ซึ่งตอบสนองต่อคำขอ POST ขาเข้าที่1233. ดึงข้อความ 4 ข้อความจาก Upstash Queue และเรียกใช้1248ฟังก์ชั่นในการทวีตในนามของผู้ใช้
การใช้ Upstash QStash คุณสามารถกำหนดเวลากระบวนการดำเนินการทวีตได้ สมมติว่าคุณต้องการทำให้เป็นอัตโนมัติ โดยทุกๆ วันในเวลาเที่ยงคืน กระบวนการจะเริ่มต้นเองและทวีตก็ดับลง ในการทำเช่นนั้น คุณจะใช้จุดสิ้นสุดที่สร้างขึ้นก่อนหน้านี้:1252 ใน QStash

ไปที่แท็บ QStash ในคอนโซล Upstash เลื่อนลงไปที่แท็บ Request Builder และดำเนินการต่อไปนี้:
- เลือก
1268แท็บ - กรอก
1272เป็น URL ที่สมบูรณ์ไปยัง1286ของคุณ จุดสิ้นสุด - เลือก
1291เป็น1306. - เลือก
1318เป็น1327. - คลิก
1330.
ด้วยขั้นตอนข้างต้น คุณได้สร้างงานที่ POST เป็น 1347 ทุกวันเวลาเที่ยงคืน
นั่นเป็นการเรียนรู้มากมาย! คุณทำเสร็จแล้วตอนนี้ ✨
ปรับใช้กับ Vercel
ตอนนี้พื้นที่เก็บข้อมูลพร้อมที่จะปรับใช้กับ Vercel แล้ว ใช้ขั้นตอนต่อไปนี้เพื่อปรับใช้:
- เริ่มต้นด้วยการสร้างพื้นที่เก็บข้อมูล GitHub ที่มีโค้ดของแอปของคุณ
- จากนั้น ไปที่แดชบอร์ด Vercel และสร้างโปรเจ็กต์ใหม่ .
- เชื่อมโยงโปรเจ็กต์ใหม่กับที่เก็บ GitHub ที่คุณเพิ่งสร้างขึ้น
- ในการตั้งค่า ให้อัปเดต
1352เพื่อจับคู่กับ1368ในพื้นที่ของคุณ ไฟล์ - คลิก
1370.
ข้อมูลเพิ่มเติม
หากต้องการข้อมูลเชิงลึกโดยละเอียดเพิ่มเติม โปรดสำรวจข้อมูลอ้างอิงที่อ้างถึงในโพสต์นี้
- พื้นที่เก็บข้อมูล GitHub
- ขั้นตอนของ Twitter OAuth 2.0
- การสร้างโทเค็นแอป Twitter
- ตอบสนองแบบฟอร์ม Hooks
- การทำงานของเซิร์ฟเวอร์ Next.js
บทสรุป
ในคู่มือนี้ คุณได้เรียนรู้วิธีสร้าง Tweet Scheduler ที่มีประสิทธิภาพโดยใช้ประโยชน์จากฐานข้อมูล Redis อันทรงพลังของ Upstash และคิว QStash ความสามารถในการปรับขนาดของ Upstash ช่วยให้มั่นใจได้ถึงการจัดเก็บและการกำหนดเวลาทวีตที่เชื่อถือได้ รวมกับการใช้งานที่ราบรื่นบน Vercel สร้างระบบอัตโนมัติเต็มรูปแบบ