在 Composio,我們在 Twitter 上非常活躍,發布更新並與用戶互動。但每天發布推文並重新發布就變成了一項繁忙的任務。
因此,我建立了一個 AI 工具,可以為團隊執行所有這些任務,同時團隊可以專注於其他重要任務。
這是我們的簡短介紹
Composio 是一個開源 AI 整合平台,可讓您建立 AI 代理並整合到您的應用程式中。 Composio 附帶超過 150 種工具和集成,您可以使用它們來建立人工智慧驅動的應用程式。我們提供 GitHub、Gmail、Discord、Slack 等第三方服務。
在此處了解有關 Composio 的更多訊息
{% cta https://dub.composio.dev/FZLK76b %}為 Composio 儲存庫加註星標 ⭐{% endcta %}
該專案可以透過建立人工智慧生成的引人入勝的貼文、轉發和引用其他創作者轉發的推文來發布推文。
集成工具- 設定 Twitter (X) 工具集成
定義操作函數 -建立檔案來定義代理將執行的操作,並包含對應的函數
存取帳戶- AI 工具將要求存取用戶的 Twitter 帳戶
執行操作- 機器人分析它獲得的輸入,並根據輸入選擇必須執行的相關操作
我們將使用以下技術:
前端- React、Vite、TailwindCSS
後端-FastAPI
身份驗證- Firebase
AI 代理- 組合和 CrewAI
Composio - 用於建構人工智慧代理和整合工具的開源平台
CrewAI - 用於建構協作式多個人工智慧機器人系統的開源框架
React + Vite - React 建立 UI,Vite 快速開發和部署應用程式
FastAPI - 用於更快建立 REST API 的 Python 框架
Firebase - Google 的雲端平台,可協助建置、執行和改進應用程式
為了建立這個專案,我們需要以下內容:
To generate OpenAI API Key, go to their [site](https://platform.openai.com/docs/overview), create an account, and generate an API Key.
To create Composio API Key, Sign up [here](https://app.composio.dev/)
After integrating the Twitter tool, and connecting an account with it, you will find the Entity id
To get the App id, go to [API section](https://docs.composio.dev/api-reference/apps/get-apps), and run your Composio API Key. You will get your App id in the result
在這個專案中,我們將
設定 Firebase 身份驗證
使用 Composio 和 CrewAI 建構 AI 代理
使用 FastAPI 建立後端
使用 React、Vite 和 TailwindCSS 建立前端
首先,克隆此repo 。
若要克隆,請執行以下命令:
git clone https://github.com/abhishekpatil4/Tweetify.git
進入後端目錄,執行setup.sh
檔。這是設定程式碼。
#!/bin/bash
# Create a virtual environment
echo "Creating virtual environment..."
python3 -m venv ~/.venvs/gmail_agent
# Activate the virtual environment
echo "Activating virtual environment..."
source ~/.venvs/gmail_agent/bin/activate
# Install libraries from requirements.txt
echo "Installing libraries from requirements.txt..."
pip install -r requirements.txt
# Login to your account
echo "Login to your Composio account"
composio login
# Add calendar tool
echo "Add Twitter tool"
composio add twitter
# Copy env backup to .env file
if [ -f ".env.example" ]; then
echo "Copying .env.example to .env..."
cp .env.example .env
else
echo "No .env.example file found. Creating a new .env file..."
touch .env
fi
# Prompt user to fill the .env file
echo "Please fill in the .env file with the necessary environment variables."
echo "Setup completed successfully!"
在.env
檔中新增 API 金鑰。
若要執行安裝文件,請執行以下命令:
chmod +x setup.sh
./setup.sh
這將建立一個Python虛擬環境並使用requirements.txt
檔案安裝必要的庫。
它會將您重新導向到 Composio,使用您的帳戶憑證登入。
然後您將被重定向到 Twitter,使用您的憑證登錄,並授予您 Twitter 帳戶的存取權限。
完成整合後,您可以存取 Composio 儀表板並監控您的整合。
現在,我們將設定 Google 的 Firebase 用於使用者的身份驗證和授權。
首先導入必要的庫並指定使用者的憑證。這些憑證將用於身份驗證目的。
import firebase_admin
from firebase_admin import credentials, auth, firestore
from pathlib import Path
import os
from dotenv import load_dotenv
load_dotenv()
creds = {
"type": os.environ.get("type"),
"project_id": os.environ.get("project_id"),
"private_key_id": os.environ.get("private_key_id"),
"private_key": os.environ.get("private_key"),
"client_email": os.environ.get("client_email"),
"client_id": os.environ.get("client_id"),
"auth_uri": os.environ.get("auth_uri"),
"token_uri": os.environ.get("token_uri"),
"auth_provider_x509_cert_url":
os.environ.get("auth_provider_x509_cert_url"),
"client_x509_cert_url": os.environ.get("client_x509_cert_url"),
}
憑證以 JSON 格式指定。
使用Firestore.
firebase_admin.initialize_app(credentials.Certificate(creds))
db = firestore.client()
這使我們能夠在 Firestore 中以集合的形式儲存文件並對其進行操作。
實用函數允許我們存取 Firestore 中存在的文件並根據我們的要求操作它們。
def get_user_by_username(username):
users_ref = db.collection('users')
query = users_ref.where('uid', '==', username).limit(1)
docs = query.get()
for doc in docs:
return doc.to_dict()
return False
此函數透過根據uid
欄位查詢users
集合,從 Firestore 檢索使用者文件。
def update_twitter_integration_id(username: str, twitter_integration_id: str):
users_ref = db.collection('users')
query = users_ref.where('username', '==', username).limit(1)
docs = query.get()
for doc in docs:
try:
doc.reference.update(
{'twitterIntegrationId': twitter_integration_id})
print(f"Successfully updated twitterIntegrationId for user {username}")
return True
except Exception as e:
print(f"Error updating twitterIntegrationId for user {username}: {e}")
return False
print(f"User {username} not found")
return False
此函數透過在users
集合中搜尋匹配的username
來更新 Firestore 文件中的twitterIntegrationId
欄位。
def get_twitter_integration_id(username: str) -> str:
users_ref = db.collection('users')
query = users_ref.where('username', '==', username).limit(1)
docs = query.get()
for doc in docs:
user_data = doc.to_dict()
return user_data.get('twitterIntegrationId', '')
print(f"User {username} not found")
return ''
此函數透過在users
集合中搜尋匹配的username
來從 Firestore 文件中檢索twitterIntegrationId
欄位。
def get_composio_api_key(username: str) -> str:
users_ref = db.collection('users')
query = users_ref.where('username', '==', username).limit(1)
docs = query.get()
for doc in docs:
user_data = doc.to_dict()
return user_data.get('composio_api_key', '')
print(f"User {username} not found")
return ''
此函數透過查詢users
集合中是否有相符的username
來從 Firestore 文件中取得composio_api_key
欄位。
現在讓我們開始建立 AI 代理程式。
由於我們專案的主要功能是發布新推文、轉發和引用推文,因此我們將建立三個單獨的文件來處理這些任務。
為了產生新推文、發布和轉發它,我們將建立new_tweet_repost.py
檔案並在其中建立 AI 代理。
首先導入必要的函式庫和函數。
import os
from composio_crewai import Action, ComposioToolSet
from crewai import Agent, Crew, Task, Process
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
from firebase.init_class import FirebaseService
from twitter_functions import get_user_id_by_username
載入環境變數並啟動 Firebase 服務。
load_dotenv()
firebase_service = FirebaseService()
現在,建立 OpenAI 的實例。這裡我們使用gpt-4o
模型。
llm = ChatOpenAI(model="gpt-4o")
現在,我們將建立代理來產生和發布推文。
def post_twitter_message(entity_id: str, message: str) -> str:
comp_api_key = firebase_service.get_composio_api_key(entity_id)
composio_toolset = ComposioToolSet(api_key=comp_api_key, entity_id=entity_id)
tools = composio_toolset.get_actions(actions=[Action.TWITTER_CREATION_OF_A_POST])
在這裡,我們初始化了一個函數post_twitter_message
來產生一條推文。我們使用 Composio API 金鑰和實體金鑰來啟動ComposioToolSet
。
我們使用get_actions
來使用composio_toolset
中所需的操作。 TWITTER_CREATION_OF_A_POST
是我們要使用該工具執行的操作的 ID。
現在,建立將執行該任務的 AI 代理程式。我們將分配背景故事、角色和其他必要的參數,以便代理人能夠更多地了解其任務。
twitter_agent = Agent(
role="Twitter Agent",
goal="Create and post tweets on Twitter",
backstory="You're an AI assistant that crafts and shares tweets on Twitter.",
verbose=True,
llm=llm,
tools=tools,
allow_delegation=False,
)
現在,我們將定義要執行的任務的描述。該描述將用於建立 AI 代理將執行的分配(任務)。
task_description = f"""
1. Post the following message on Twitter:
"{message}"
2. Return only the tweet ID of the posted tweet.
"""
process_twitter_request = Task(
description=task_description,
agent=twitter_agent,
expected_output="The tweet ID of the posted tweet.",
)
然後,我們將建立工作人員來定義任務執行、代理協作和整體工作流程的策略。
twitter_processing_crew = Crew(
agents=[twitter_agent],
tasks=[process_twitter_request],
verbose=1,
process=Process.sequential,
)
最後使用這個建立的crew執行任務並傳回結果。
result = twitter_processing_crew.kickoff()
return result
我們將遵循相同的方法來建立轉發推文的功能。這是它的完整程式碼。
def repost_tweet(admin_entity_id: str, entity_id: str, task_description: str) -> str:
comp_api_key = firebase_service.get_composio_api_key(admin_entity_id)
composio_toolset = ComposioToolSet(api_key=comp_api_key, entity_id=entity_id)
tools = composio_toolset.get_actions(actions=[Action.TWITTER_CREATION_OF_A_POST, Action.TWITTER_CAUSES_THE_USER_IN_THE_PATH_TO_REPOST_THE_SPECIFIED_POST])
twitter_agent = Agent(
role="Twitter Agent",
goal="Repost tweets on Twitter",
backstory="You're an AI assistant that reposts tweets on Twitter, if a quote is provided, add the quote to the tweet, if no quote is provided, repost the tweet without a quote.",
verbose=True,
llm=llm,
tools=tools,
allow_delegation=False,
)
process_twitter_request = Task(
description=task_description,
agent=twitter_agent,
expected_output="Result of the repost",
)
twitter_processing_crew = Crew(
agents=[twitter_agent],
tasks=[process_twitter_request],
verbose=1,
process=Process.sequential,
)
result = twitter_processing_crew.kickoff()
return result
在此函數中,我們使用了TWITTER_CAUSES_THE_USER_IN_THE_PATH_TO_REPOST_THE_SPECIFIED_POST
操作 ID,它將重新發布用戶的推文。
現在,我們將建立一個函數來建立推文、發布並重新發布。這裡我們建立了函數create_new_tweet_and_repost
並使用post_twitter_message
函數來產生推文並發布它。
def create_new_tweet_and_repost(initial_tweet_entity_id: str, initial_tweet: str, repost_data_list: list):
tweet_id = post_twitter_message(initial_tweet_entity_id, initial_tweet)
要重新發布,我們必須檢查推文中是否存在引用。如果有報價,我們將重新發布報價,否則只需重新發布即可。
for repost_data in repost_data_list:
entity_id = repost_data["entity_id"]
quote = repost_data["quote"]
if quote:
task_description = f"""
Repost the tweet with ID {tweet_id} with the following quote:
"{quote}"
"""
else:
user_id = get_user_id_by_username(entity_id)
task_description = f"""
Repost the tweet with ID {tweet_id} without any quote and user ID {user_id}
"""
最後,執行repost_tweet
函數並傳回結果。
repost_result = repost_tweet(initial_tweet_entity_id, entity_id, task_description)
print(f"Repost result for {entity_id}: {repost_result}")
我們將建立一個quote_generator.py
檔案來產生引號以重新發布帶有引號的推文。
首先導入必要的庫並初始化環境變數。
import os
from openai import OpenAI
from dotenv import load_dotenv
load_dotenv()
使用 OpenAI API 建立客戶端並指定 OpenAI API 金鑰。
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
現在,建立一個generate_repost_quote
函數並建立quote
陣列和user_prompts
字串。
def generate_repost_quote(prompt: str, tweet_content: str, number_of_quotes: int) -> list[str]:
quotes = []
user_prompt = prompt + " Tweet content: " + tweet_content
最後,執行循環以根據使用者傳遞的number_of_quotes
產生引號數。
for _ in range(number_of_quotes):
completion = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "Generate a meaningful repost quote with hashtags and an emoji"},
{"role": "user", "content": user_prompt}
]
)
quote = completion.choices[0].message.content.strip()
quotes.append(quote)
return quotes
此處使用gpt-4o-mini
型號。我們在content
中指定了對使用者和系統的不同提示。產生的報價將追加到quotes
陣列中,最後傳回結果quotes
陣列。
我們將建立一個respost_existing_tweet.py
檔案並建立函數repost_tweet
來重新發布現有的推文。
我們將遵循與new_tweet_repost.py
檔案中的repost_tweet
函數相同的方法。這是repost_existing_tweet.py
的完整程式碼:
import os
from composio_crewai import Action, ComposioToolSet
from crewai import Agent, Crew, Task, Process
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
from pathlib import Path
from firebase.init import get_composio_api_key
from twitter_functions import get_user_id_by_username
load_dotenv()
llm = ChatOpenAI(model="gpt-4o")
def repost_tweet(admin_entity_id: str, entity_id: str, task_description: str) -> str:
comp_api_key = get_composio_api_key(admin_entity_id)
composio_toolset = ComposioToolSet(api_key=comp_api_key, entity_id=entity_id)
tools = composio_toolset.get_actions(actions=[Action.TWITTER_CREATION_OF_A_POST, Action.TWITTER_CAUSES_THE_USER_IN_THE_PATH_TO_REPOST_THE_SPECIFIED_POST])
twitter_agent = Agent(
role="Twitter Agent",
goal="Repost tweets on Twitter",
backstory="You're an AI assistant that reposts tweets on Twitter, if a quote is provided, add the quote to the tweet, if no quote is provided, repost the tweet without a quote.",
verbose=True,
llm=llm,
tools=tools,
allow_delegation=False,
)
process_twitter_request = Task(
description=task_description,
agent=twitter_agent,
expected_output="Result of the repost",
)
twitter_processing_crew = Crew(
agents=[twitter_agent],
tasks=[process_twitter_request],
verbose=1,
process=Process.sequential,
)
result = twitter_processing_crew.kickoff()
return result
def repost_existing(admin_entity_id: str, tweet_id: str, repost_data_list: list):
for repost_data in repost_data_list:
entity_id = repost_data["entity_id"]
quote = repost_data["quote"]
if quote:
task_description = f"""
Repost the tweet with ID {tweet_id} with the following quote:
"{quote}"
"""
else:
user_id = get_user_id_by_username(entity_id)
task_description = f"""
Repost the tweet with ID {tweet_id} without any quote and user ID {user_id}
"""
repost_result = repost_tweet(admin_entity_id, entity_id, task_description)
print(f"Repost result for {entity_id}: {repost_result}")
return "Tweeting and reposting process completed."
repost_tweet
函數將重新發布推文, repost_existing
函數檢查貼文的引用是否可用。如果有報價,它將重新發布帶有報價的推文;否則,它只會重新發布該推文。
現在,我們將設定後端並在main.py
檔案中定義所需的端點。這些端點將在前端用於連接到後端。
首先導入必要的庫並建立 FastAPI 應用程式。
from fastapi import FastAPI, HTTPException, Request, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel
from fastapi.middleware.cors import CORSMiddleware
from firebase.init import auth
from composio_config import createNewEntity, isEntityConnected, createTwitterIntegrationAndInitiateAdminConnection
import logging
from quote_generator import generate_repost_quote
from new_tweet_repost import create_new_tweet_and_repost
from twitter_functions import get_tweet_text_by_id, get_user_data_by_username
from repost_existing_tweet import repost_existing
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
指定來源和中間件。
origins = [
"https://tweetify-three.vercel.app",
"http://localhost:5173",
"http://localhost",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
取得令牌並將其用於身份驗證。
def verify_token(auth_credentials: HTTPAuthorizationCredentials = Depends(
HTTPBearer())):
token = auth_credentials.credentials
try:
decoded_token = auth.verify_id_token(token)
return decoded_token
except Exception:
raise HTTPException(status_code=401, detail="Invalid or expired token")
定義 Pydantic 模型。
class UserData(BaseModel):
admin_username: str
username: str
appType: str
class TwitterUserData(BaseModel):
username: str
class InitialiseAgentData(BaseModel):
username: str
class TweetData(BaseModel):
prompt: str
tweetContent: str
numberOfQuotes: int
class GetTweetData(BaseModel):
tweet_id: str
class TweetRequestData(BaseModel):
initial_tweet_entity_id: str
post: str
repost_data_list: list
class RepostExistingData(BaseModel):
admin_entity_id: str
tweet_id: str
repost_data_list: list
class NewIntegrationData(BaseModel):
username: str
redirectUrl: str
class NewEntityData(BaseModel):
username: str
newUserId: str
redirectUrl: str
指定端點及其傳回的結果。
@app.post("/newintegration")
async def handle_request(user_data: NewIntegrationData,
decoded_token: dict = Depends(verify_token)):
user_id = decoded_token['uid']
username = user_data.username
redirectUrl = user_data.redirectUrl
res = createTwitterIntegrationAndInitiateAdminConnection(username, redirectUrl)
return res
@app.post("/newentity")
async def handle_request(user_data: NewEntityData,
decoded_token: dict = Depends(verify_token)):
user_id = decoded_token['uid']
username = user_data.username
newUserId = user_data.newUserId
redirectUrl = user_data.redirectUrl
res = createNewEntity(username, newUserId, redirectUrl)
return res
@app.post("/checkconnection")
async def handle_request(user_data: UserData,
decoded_token: dict = Depends(verify_token)):
user_id = decoded_token['uid']
admin_username = user_data.admin_username
username = user_data.username
appType = user_data.appType
res = isEntityConnected(admin_username, username, appType)
return res
@app.post("/getquotes")
async def handle_request(tweet_data: TweetData,
decoded_token: dict = Depends(verify_token)):
user_id = decoded_token['uid']
prompt = tweet_data.prompt
tweet_content = tweet_data.tweetContent
number_of_quotes = tweet_data.numberOfQuotes
res = generate_repost_quote(prompt, tweet_content, number_of_quotes)
return {"quotes": res}
@app.post("/newtweetandrepost")
async def handle_request(tweet_request_data: TweetRequestData,
decoded_token: dict = Depends(verify_token)):
initial_tweet_entity_id = tweet_request_data.initial_tweet_entity_id
initial_tweet = tweet_request_data.post
repost_data_list = tweet_request_data.repost_data_list
res = create_new_tweet_and_repost(initial_tweet_entity_id, initial_tweet, repost_data_list)
return {"result": res}
@app.post("/repostexisting")
async def handle_request(tweet_request_data: RepostExistingData,
decoded_token: dict = Depends(verify_token)):
admin_entity_id = tweet_request_data.admin_entity_id
tweet_id = tweet_request_data.tweet_id
repost_data_list = tweet_request_data.repost_data_list
res = repost_existing(admin_entity_id, tweet_id, repost_data_list)
return {"result": res}
@app.post("/gettweet")
async def handle_request(tweet_data: GetTweetData, decoded_token: dict = Depends(verify_token)):
tweet_id = tweet_data.tweet_id
try:
tweet_text = get_tweet_text_by_id(tweet_id)
return {"tweet_text": tweet_text}
except requests.exceptions.RequestException as e:
if e.response.status_code == 400:
return {"error": "An error occurred: 400 Client Error: Bad Request for url: https://api.twitter.com/2/tweets"}, 400
return {"error": str(e)}, 500
@app.post("/getusertwitterdata")
async def handle_request(user_data: TwitterUserData, decoded_token: dict = Depends(verify_token)):
username = user_data.username
try:
res = get_user_data_by_username(username)
if res is None:
return {"error": "An error occurred while fetching user data."}, 500
return res
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
return {"error": "Username not found."}, 404
elif e.response.status_code == 429:
return {"error": "Too many requests. Please try again later."}, 429
else:
return {"error": f"HTTP error occurred: {e}"}, e.response.status_code
except requests.exceptions.RequestException as e:
return {"error": f"An error occurred: {e}"}, 500
@app.get("/")
async def handle_request():
return "ok"
這些端點的作用如下:
/newintergation
- 建立新的整合並將管理員與 Twitter 帳戶連接起來。返回管理員的詳細訊息
/newentity
- 使用提供的使用者憑證建立新實體,並使用verify_token
函數使用提供的令牌對使用者進行身份驗證。
/checkconnection
- 檢查所提供的管理員憑證與新建立的實體是否成功建立連線。
/generatequotes
- 使用提供的參數(如提示、tweet_content、number_of_quotes 和用戶詳細資訊)產生多個報價。
/newtweetandrepost
- 使用我們建立的 AI 代理程式產生新查詢並提供所有必要的輸入
/repostexisting
- 使用entity_id、tweet_id 和repost_data_list 重新發布現有推文。
/gettweet
- 使用推文的 id 回推文的內容
/getusertwitterdata
- 傳回使用令牌進行身份驗證的使用者的 Twitter 資料
/
- 這是測試端點,用於簡單檢查後端 API 是否成功執行。如果API執行成功,它將返回“ok”。
最後,定義Uvicorn伺服器。
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
若要啟動伺服器,請執行以下命令:
python main.py
您的伺服器將在連接埠8000
上執行
讓我們開始建立專案的前端。為了簡單起見,我們不會深入研究每個元件。
這將是我們的主頁元件。
import Hero from "../components/Hero";
import Benefits from "../components/Benefits";
import FAQ from "../components/FAQ";
import Working from "../components/Working";
import ActionButton from "../components/ActionButton";
import DemoVideo from "../components/DemoVideo";
const Home = () => {
return <section className="bg-white dark:bg-gray-900 mt-24">
<div className="px-4 mx-auto max-w-screen-xl text-center py-16">
<Hero />
<Benefits />
<DemoVideo />
<Working />
<FAQ />
<div className="mt-32">
<ActionButton displayName={"Get started"} link={"#"} />
</div>
</div>
</section>
}
export default Home;
這將產生一個如下所示的主頁:
連接 Twitter 帳戶後,它會將您重新導向到「設定」頁面。
點擊此處查看“設定”頁面的完整程式碼。
在此頁面上,使用者可以新增他們的 Composio API 金鑰。連接他們的 Twitter 帳戶並向其加入更多用戶。
這是App.jsx
程式碼:
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "./config/firebase";
import Navbar from "./components/Navbar";
import Home from "./pages/Home";
import Footer from "./components/Footer";
import ScrollToTop from "./components/ScrollToTop";
import { useState, useEffect } from "react";
import Login from "./pages/Login";
import Settings from "./pages/Settings";
import NotFound from "./pages/NotFound";
import SkeletonLoader from "./components/SkeletonLoader";
import { SnackbarProvider } from 'notistack'
import CreatePost from "./pages/CreatePost";
import RepostExistingTweet from "./pages/Repost";
const ProtectedRoute = ({ user, children }) => {
if (!user) {
return <Navigate to="/login" replace />;
}
return children;
};
const App = () => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setUser(user);
setLoading(false);
});
return () => unsubscribe();
}, []);
if (loading) {
return <SkeletonLoader />
}
return (
<BrowserRouter>
<SnackbarProvider autoHideDuration={3000} preventDuplicate={true} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}>
<Navbar user={user} />
<ScrollToTop />
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/Settings" element={
<ProtectedRoute user={user}>
<Settings user={user} />
</ProtectedRoute>
} />
<Route path="/createpost" element={
<ProtectedRoute user={user}>
<CreatePost user={user} />
</ProtectedRoute>
} />
<Route path="/repost" element={
<ProtectedRoute user={user}>
<RepostExistingTweet user={user} />
</ProtectedRoute>
} />
<Route path="/" element={<Home />} />
<Route path="*" element={<NotFound />} />
</Routes>
<Footer />
</SnackbarProvider>
</BrowserRouter>
);
}
export default App;
Firebase 驗證- 我們使用onAuthStateChanged
來管理身份驗證。它追蹤身份驗證狀態。接下來,如果使用者成功通過身份驗證,則會將使用者重新導向到下一步,即「設定」頁面。
路由與重定向- 我們使用了react-router-dom
來處理專案中的路由。這允許我們在遵循身份驗證狀態的同時導航到不同的路由(例如/settings
、 /login
和/
)。
骨架載入器- 我們新增了一個骨架載入器,它將在 Firebase 執行身份驗證任務並更新身份驗證狀態時顯示。
最後,使用以下命令執行應用程式:
npm run dev
這將在本地主機上部署您的應用程式。
這是該應用程式的快速演示:
{% 嵌入 https://drive.google.com/file/d/1hQSjQc0GdQj8kPrrIlqLJvPzUpphU5hc/view %}
您可以在這裡嘗試即時應用程式。
在本文中,我們建立了一個完整的人工智慧工具,它連接到您的 Twitter 帳戶,並且可以發布新推文、轉發和引用轉發推文。
感謝您閱讀這篇文章。看看 Composio 並給我們一個 Star⭐ 以表達您的支持
{% cta https://dub.composio.dev/FZLK76b %}為 Composio 儲存庫加註星標 ⭐{% endcta %}