阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

63 個專案實戰,寫出作品集,讓面試官眼前一亮!

立即開始免費試讀!

在 Composio,我們在 Twitter 上非常活躍,發布更新並與用戶互動。但每天發布推文並重新發布就變成了一項繁忙的任務。

因此,我建立了一個 AI 工具,可以為團隊執行所有這些任務,同時團隊可以專注於其他重要任務。

圖片說明


Composio - 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 的雲端平台,可協助建置、執行和改進應用程式

圖片說明


先決條件

為了建立這個專案,我們需要以下內容:

  • OpenAI API 金鑰
To generate OpenAI API Key, go to their [site](https://platform.openai.com/docs/overview), create an account, and generate an API Key.

圖片說明

  • API金鑰組成
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

讓我們開始吧

在這個專案中,我們將

  1. 設定 Firebase 身份驗證

  2. 使用 Composio 和 CrewAI 建構 AI 代理

  3. 使用 FastAPI 建立後端

  4. 使用 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 儀表板並監控您的整合。


Firebase 身份驗證

現在,我們將設定 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 代理

現在讓我們開始建立 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函數檢查貼文的引用是否可用。如果有報價,它將重新發布帶有報價的推文;否則,它只會重新發布該推文。


設定 FastAPI 後端

現在,我們將設定後端並在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 %}


原文出處:https://dev.to/composiodev/built-an-ai-tool-to-help-my-team-tweet-smart-goodbye-manual-posting-hello-viral-hits-5fap


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。

阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

63 個專案實戰,寫出作品集,讓面試官眼前一亮!

立即開始免費試讀!