├── .dockerignore ├── .env.example ├── .gitignore ├── .idea └── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── README_JA.md ├── README_RO.md ├── README_ZH.md ├── cookie.py ├── deps.py ├── docker-compose.yml ├── images ├── WechatIMG148.jpg ├── cover.png ├── docs.png └── wechat.jpg ├── main.py ├── requirements.txt ├── schemas.py ├── test.py └── utils.py /.dockerignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | images/ 3 | 4 | .env 5 | Dockerfile 6 | docker-compose.yml 7 | README.md 8 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | BASE_URL=https://studio-api.suno.ai 2 | SESSION_ID= 3 | COOKIE= 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Python 2 | [Bb]in 3 | [Ii]nclude 4 | [Ll]ib 5 | [Ll]ib64 6 | [Ll]ocal 7 | [Ss]cripts 8 | pyvenv.cfg 9 | .venv 10 | pip-selfcheck.json 11 | .idea 12 | *.iml 13 | out 14 | gen 15 | 16 | __pycache__ 17 | .env 18 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | # GitHub Copilot persisted chat sessions 10 | /copilot/chatSessions 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | FROM python:3.10-slim-buster 3 | 4 | WORKDIR /app 5 | 6 | COPY requirements.txt ./ 7 | RUN --mount=type=cache,target=/root/.cache/pip \ 8 | pip install -r requirements.txt --no-cache-dir 9 | 10 | COPY . . 11 | 12 | EXPOSE 8000 13 | CMD [ "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000" ] 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Suno API 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [简体中文](README_ZH.md) | [日本語](README_JA.md) 2 | 3 | ### FoxAIHub 4 | 5 | FoxAIHub focuses on delivering efficient and reliable AI model API services, covering text-to-image, text-to-video, image-to-video, and music generation API, helping you stay ahead at the intersection of creativity and technology. 6 | 7 | [FoxAIHUb](https://foxaihub.com) 8 | 9 | 10 | ### Unofficial API 11 | 12 | This is an unofficial API based on Python and FastAPI. It currently supports generating songs, lyrics, etc. 13 | It comes with a built-in token maintenance and keep-alive feature, so you don't have to worry about the token expiring. 14 | 15 | ### Features 16 | 17 | - Automatic token maintenance and keep-alive 18 | - Fully asynchronous, fast, suitable for later expansion 19 | - Simple code, easy to maintain, convenient for secondary development 20 | 21 | 22 | ### Usage 23 | 24 | #### Configuration 25 | 26 | Edit the `.env.example` file, rename to `.env` and fill in the session_id and cookie. 27 | 28 | These are initially obtained from the browser, and will be automatically kept alive later. 29 | 30 | ![cookie](./images/cover.png) 31 | 32 | 33 | #### Run 34 | 35 | Install dependencies 36 | 37 | ```bash 38 | pip3 install -r requirements.txt 39 | ``` 40 | 41 | For this part, refer to the FastAPI documentation on your own. 42 | ```bash 43 | uvicorn main:app 44 | ``` 45 | 46 | #### Docker 47 | 48 | ```bash 49 | docker compose build && docker compose up 50 | ``` 51 | 52 | #### Documentation 53 | 54 | After setting up the service, visit /docs 55 | 56 | ![docs](./images/docs.png) 57 | -------------------------------------------------------------------------------- /README_JA.md: -------------------------------------------------------------------------------- 1 | # 非公式 Suno API 2 | 3 | Python と FastAPI をベースにした非公式の Suno API です。現在、曲や歌詞などの生成に対応しています。 4 | トークンのメンテナンスと keep-alive 機能が組み込まれているので、トークンの期限切れを心配する必要はありません。 5 | 6 | ### 特徴 7 | 8 | - 自動トークンメンテナンスと keep-alive 9 | - 完全非同期、高速、将来の拡張に対応 10 | - シンプルなコード、メンテナンスが容易、二次開発に便利 11 | 12 | 13 | ### 使用方法 14 | 15 | #### 設定 16 | 17 | `.env.example` ファイルを編集して `.env` にリネームし、session_id と cookie を記入する。 18 | 19 | これらは最初にブラウザから取得され、後で自動的に keep-alive されます。 20 | 21 | ![cookie](./images/cover.png) 22 | 23 | 24 | #### 実行 25 | 26 | 依存関係をインストールする 27 | 28 | ```bash 29 | pip3 install -r requirements.txt 30 | ``` 31 | 32 | この部分については、各自で FastAPI ドキュメントを参照してください。 33 | ```bash 34 | uvicorn main:app 35 | ``` 36 | 37 | #### Docker 38 | 39 | ```bash 40 | docker compose build && docker compose up 41 | ``` 42 | 43 | #### ドキュメント 44 | 45 | サービスをセットアップしたら、/docs にアクセスしてください 46 | 47 | ![docs](./images/docs.png) 48 | 49 | -------------------------------------------------------------------------------- /README_RO.md: -------------------------------------------------------------------------------- 1 | [简体中文](README_ZH.md) | [日本語](README_JA.md) 2 | ### API Neoficial 3 | 4 | Acesta este un API Suno neoficial bazat pe Python și FastAPI. În prezent, suportă generarea de cântece, versuri, etc. 5 | Vine cu o funcționalitate integrată de menținere a tokenului și de menținere a conexiunii, astfel încât să nu trebuie să vă faceți griji în legătură cu expirarea tokenului. 6 | 7 | ### Caracteristici 8 | 9 | - Menținerea automată a tokenului și a conexiunii 10 | - Complet asincron, rapid, potrivit pentru o extindere ulterioară 11 | - Cod simplu, ușor de întreținut, convenabil pentru dezvoltarea secundară 12 | 13 | ### Utilizare 14 | 15 | #### Configurare 16 | 17 | Editați fișierul `.env.example`, redenumiți-l în `.env` și completați cu session_id și cookie. 18 | 19 | Acestea sunt obținute inițial din browser și vor fi menținute automat în viitor. 20 | 21 | ![cookie](./images/cover.png) 22 | 23 | #### Rulare 24 | 25 | Instalați dependențele 26 | 27 | ```bash 28 | pip3 install -r requirements.txt 29 | ``` 30 | Pentru această parte, consultați documentația FastAPI pe cont propriu. 31 | 32 | ```bash 33 | uvicorn main:app 34 | ``` 35 | 36 | #### Docker 37 | 38 | ```bash 39 | docker compose build && docker compose up 40 | ``` 41 | 42 | #### Documentație 43 | 44 | După configurarea serviciului, vizitați /docs 45 | 46 | ![docs](./images/docs.png) 47 | 48 | ### Resurse folositoare 49 | 50 | [chatgpt web, midjourney, gpts,tts, whisper,suno-v3](https://github.com/Dooy/chatgpt-web-midjourney-proxy) 51 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | ### 非官方 Suno API 2 | 3 | 这一个基于 Python和 FastAPI 的非官方 Suno API,目前支持生成歌曲,歌词等功能。 4 | 自带维护 token 与保活功能,无需担心 token 过期问题。 5 | 6 | ### 特点 7 | 8 | - token 自动维护与保活 9 | - 全异步,速度快,适合后期扩展 10 | - 代码简单,易于维护,方便二次开发 11 | 12 | ### 使用 13 | 14 | #### 配置 15 | 16 | 编辑 `.env.example` 文件,重命名为 `.env`,填写 session_id 和 cookie 17 | 18 | 这些先从浏览器中获取,后期会自动保活。 19 | 20 | ![cookie](./images/cover.png) 21 | 22 | #### 运行 23 | 24 | 安装依赖 25 | 26 | ```bash 27 | pip3 install -r requirements.txt 28 | ``` 29 | 30 | 这一部分,自行参考 FastAPI 文档 31 | 32 | ```bash 33 | uvicorn main:app 34 | ``` 35 | 36 | #### Docker 37 | 38 | ```bash 39 | docker compose build && docker compose up 40 | ``` 41 | 42 | #### 文档 43 | 44 | 搭建服务后访问 /docs 45 | 46 | ![docs](./images/docs.png) 47 | 48 | -------------------------------------------------------------------------------- /cookie.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import os 4 | import time 5 | from http.cookies import SimpleCookie 6 | from threading import Thread 7 | 8 | import requests 9 | 10 | from utils import COMMON_HEADERS 11 | 12 | 13 | class SunoCookie: 14 | def __init__(self): 15 | self.cookie = SimpleCookie() 16 | self.session_id = None 17 | self.token = None 18 | 19 | def load_cookie(self, cookie_str): 20 | self.cookie.load(cookie_str) 21 | 22 | def get_cookie(self): 23 | return ";".join([f"{i}={self.cookie.get(i).value}" for i in self.cookie.keys()]) 24 | 25 | def set_session_id(self, session_id): 26 | self.session_id = session_id 27 | 28 | def get_session_id(self): 29 | return self.session_id 30 | 31 | def get_token(self): 32 | return self.token 33 | 34 | def set_token(self, token: str): 35 | self.token = token 36 | 37 | 38 | suno_auth = SunoCookie() 39 | suno_auth.set_session_id(os.getenv("SESSION_ID")) 40 | suno_auth.load_cookie(os.getenv("COOKIE")) 41 | 42 | 43 | def update_token(suno_cookie: SunoCookie): 44 | headers = {"cookie": suno_cookie.get_cookie()} 45 | headers.update(COMMON_HEADERS) 46 | session_id = suno_cookie.get_session_id() 47 | 48 | resp = requests.post( 49 | url=f"https://clerk.suno.com/v1/client/sessions/{session_id}/tokens?_clerk_js_version=4.72.0-snapshot.vc141245", 50 | headers=headers, 51 | ) 52 | 53 | resp_headers = dict(resp.headers) 54 | set_cookie = resp_headers.get("Set-Cookie") 55 | suno_cookie.load_cookie(set_cookie) 56 | token = resp.json().get("jwt") 57 | suno_cookie.set_token(token) 58 | # print(set_cookie) 59 | # print(f"*** token -> {token} ***") 60 | 61 | 62 | def keep_alive(suno_cookie: SunoCookie): 63 | while True: 64 | try: 65 | update_token(suno_cookie) 66 | except Exception as e: 67 | print(e) 68 | finally: 69 | time.sleep(5) 70 | 71 | 72 | def start_keep_alive(suno_cookie: SunoCookie): 73 | t = Thread(target=keep_alive, args=(suno_cookie,)) 74 | t.start() 75 | 76 | 77 | start_keep_alive(suno_auth) 78 | -------------------------------------------------------------------------------- /deps.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from cookie import suno_auth 4 | 5 | 6 | def get_token(): 7 | token = suno_auth.get_token() 8 | try: 9 | yield token 10 | finally: 11 | pass 12 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | suno-api: 5 | build: . 6 | ports: 7 | - "8000:8000" 8 | env_file: 9 | - .env 10 | -------------------------------------------------------------------------------- /images/WechatIMG148.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunoAI-API/Suno-API/953885c3b4131cb41ffec912a309cabfff7e4177/images/WechatIMG148.jpg -------------------------------------------------------------------------------- /images/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunoAI-API/Suno-API/953885c3b4131cb41ffec912a309cabfff7e4177/images/cover.png -------------------------------------------------------------------------------- /images/docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunoAI-API/Suno-API/953885c3b4131cb41ffec912a309cabfff7e4177/images/docs.png -------------------------------------------------------------------------------- /images/wechat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SunoAI-API/Suno-API/953885c3b4131cb41ffec912a309cabfff7e4177/images/wechat.jpg -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | import json 4 | 5 | from fastapi import Depends, FastAPI, HTTPException, Request, status 6 | from fastapi.middleware.cors import CORSMiddleware 7 | 8 | import schemas 9 | from deps import get_token 10 | from utils import generate_lyrics, generate_music, get_feed, get_lyrics, get_credits 11 | 12 | app = FastAPI() 13 | 14 | 15 | app.add_middleware( 16 | CORSMiddleware, 17 | allow_origins=["*"], 18 | allow_credentials=True, 19 | allow_methods=["*"], 20 | allow_headers=["*"], 21 | ) 22 | 23 | 24 | @app.get("/") 25 | async def get_root(): 26 | return schemas.Response() 27 | 28 | 29 | @app.post("/generate") 30 | async def generate( 31 | data: schemas.CustomModeGenerateParam, token: str = Depends(get_token) 32 | ): 33 | try: 34 | resp = await generate_music(data.dict(), token) 35 | return resp 36 | except Exception as e: 37 | raise HTTPException( 38 | detail=str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR 39 | ) 40 | 41 | 42 | @app.post("/generate/description-mode") 43 | async def generate_with_song_description( 44 | data: schemas.DescriptionModeGenerateParam, token: str = Depends(get_token) 45 | ): 46 | try: 47 | resp = await generate_music(data.dict(), token) 48 | return resp 49 | except Exception as e: 50 | raise HTTPException( 51 | detail=str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR 52 | ) 53 | 54 | 55 | @app.get("/feed/{aid}") 56 | async def fetch_feed(aid: str, token: str = Depends(get_token)): 57 | try: 58 | resp = await get_feed(aid, token) 59 | return resp 60 | except Exception as e: 61 | raise HTTPException( 62 | detail=str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR 63 | ) 64 | 65 | 66 | @app.post("/generate/lyrics/") 67 | async def generate_lyrics_post(request: Request, token: str = Depends(get_token)): 68 | req = await request.json() 69 | prompt = req.get("prompt") 70 | if prompt is None: 71 | raise HTTPException( 72 | detail="prompt is required", status_code=status.HTTP_400_BAD_REQUEST 73 | ) 74 | 75 | try: 76 | resp = await generate_lyrics(prompt, token) 77 | return resp 78 | except Exception as e: 79 | raise HTTPException( 80 | detail=str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR 81 | ) 82 | 83 | 84 | @app.get("/lyrics/{lid}") 85 | async def fetch_lyrics(lid: str, token: str = Depends(get_token)): 86 | try: 87 | resp = await get_lyrics(lid, token) 88 | return resp 89 | except Exception as e: 90 | raise HTTPException( 91 | detail=str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR 92 | ) 93 | 94 | 95 | @app.get("/get_credits") 96 | async def fetch_credits(token: str = Depends(get_token)): 97 | try: 98 | resp = await get_credits(token) 99 | return resp 100 | except Exception as e: 101 | raise HTTPException( 102 | detail=str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR 103 | ) 104 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp 2 | python-dotenv 3 | fastapi 4 | uvicorn 5 | pydantic 6 | requests 7 | -------------------------------------------------------------------------------- /schemas.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | 3 | from datetime import datetime 4 | from typing import Any, List, Optional, Union 5 | 6 | from pydantic import BaseModel, Field 7 | 8 | 9 | class Response(BaseModel): 10 | code: Optional[int] = 0 11 | msg: Optional[str] = "success" 12 | data: Optional[Any] = None 13 | 14 | 15 | class CustomModeGenerateParam(BaseModel): 16 | """Generate with Custom Mode""" 17 | 18 | prompt: str = Field(..., description="lyrics") 19 | mv: str = Field( 20 | ..., 21 | description="model version, default: chirp-v3-0", 22 | examples=["chirp-v3-0"], 23 | ) 24 | title: str = Field(..., description="song title") 25 | tags: str = Field(..., description="style of music") 26 | negative_tags: str = Field(..., description="negative style of music") 27 | continue_at: Optional[int] = Field( 28 | default=None, 29 | description="continue a new clip from a previous song, format number", 30 | examples=[120], 31 | ) 32 | continue_clip_id: Optional[str] = None 33 | 34 | 35 | class DescriptionModeGenerateParam(BaseModel): 36 | """Generate with Song Description""" 37 | 38 | gpt_description_prompt: str 39 | make_instrumental: bool = False 40 | mv: str = Field( 41 | default='chirp-v3-0', 42 | description="model version, default: chirp-v3-0", 43 | examples=["chirp-v3-0"], 44 | ) 45 | 46 | prompt: str = Field( 47 | default="", 48 | description="Placeholder, keep it as an empty string, do not modify it", 49 | ) 50 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import time 4 | 5 | import requests 6 | from requests import get as rget 7 | 8 | 9 | def test_generate_music(): 10 | data = { 11 | "prompt": "[Verse]\nWake up in the morning, feeling brand new\nGonna shake off the worries, leave 'em in the rearview\nStep outside, feeling the warmth on my face\nThere's something 'bout the sunshine that puts me in my place\n\n[Verse 2]\nWalking down the street, got a spring in my step\nThe rhythm in my heart, it just won't forget\nEverywhere I go, people smiling at me\nThey can feel the joy, it's contagious, can't you see?\n\n[Chorus]\nI got sunshine in my pocket, happiness in my soul\nA skip in my stride, and I'm ready to go\nNothing gonna bring me down, gonna keep on shining bright\nI got sunshine in my pocket, this world feels so right", 12 | "tags": "heartfelt anime", 13 | "mv": "chirp-v3-0", 14 | "title": "Sunshine in your Pocket", 15 | "continue_clip_id": None, 16 | "continue_at": None, 17 | } 18 | 19 | r = requests.post( 20 | "http://127.0.0.1:8000/generate/description-mode", data=json.dumps(data) 21 | ) 22 | 23 | resp = r.text 24 | print(resp) 25 | 26 | 27 | def test_generate_music_with_description(): 28 | data = { 29 | "gpt_description_prompt": "A Blues song about a person who is feeling happy and optimistic about the future.", 30 | "make_instrumental": False, 31 | "mv": "chirp-v3-0", 32 | } 33 | 34 | r = requests.post("http://127.0.0.1:8000/generate", data=json.dumps(data)) 35 | 36 | resp = r.text 37 | print(resp) 38 | 39 | 40 | def test_generate_lyrics(): 41 | data = {"prompt": ""} 42 | 43 | r = requests.post("http://127.0.0.1:8000/generate/lyrics/", data=json.dumps(data)) 44 | print(r.text) 45 | 46 | 47 | def get_lyrics(lid): 48 | r = requests.get(f"http://127.0.0.1:8000/lyrics/{lid}") 49 | print(r.text) 50 | 51 | 52 | def get_info(aid): 53 | response = requests.get(f"http://127.0.0.1:8000/feed/{aid}") 54 | 55 | data = json.loads(response.text)[0] 56 | 57 | return data["audio_url"], data["metadata"] 58 | 59 | 60 | def save_song(aid, output_path="output"): 61 | start_time = time.time() 62 | while True: 63 | audio_url, metadata = get_info(aid) 64 | if audio_url: 65 | break 66 | elif time.time() - start_time > 90: 67 | raise TimeoutError("Failed to get audio_url within 90 seconds") 68 | time.sleep(30) 69 | response = rget(audio_url, allow_redirects=False, stream=True) 70 | if response.status_code != 200: 71 | raise Exception("Could not download song") 72 | index = 0 73 | while os.path.exists(os.path.join(output_path, f"suno_{index}.mp3")): 74 | index += 1 75 | path = os.path.join(output_path, f"suno_{index}.mp3") 76 | with open(path, "wb") as output_file: 77 | for chunk in response.iter_content(chunk_size=1024): 78 | # If the chunk is not empty, write it to the file. 79 | if chunk: 80 | output_file.write(chunk) 81 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import time 4 | 5 | import aiohttp 6 | from dotenv import load_dotenv 7 | 8 | load_dotenv() 9 | 10 | BASE_URL = os.getenv("BASE_URL") 11 | 12 | COMMON_HEADERS = { 13 | "Content-Type": "text/plain;charset=UTF-8", 14 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", 15 | "Referer": "https://suno.com", 16 | "Origin": "https://suno.com", 17 | } 18 | 19 | 20 | async def fetch(url, headers=None, data=None, method="POST"): 21 | if headers is None: 22 | headers = {} 23 | headers.update(COMMON_HEADERS) 24 | if data is not None: 25 | data = json.dumps(data) 26 | 27 | print(data, method, headers, url) 28 | 29 | async with aiohttp.ClientSession() as session: 30 | try: 31 | async with session.request( 32 | method=method, url=url, data=data, headers=headers 33 | ) as resp: 34 | return await resp.json() 35 | except Exception as e: 36 | return f"An error occurred: {e}" 37 | 38 | 39 | async def get_feed(ids, token): 40 | headers = {"Authorization": f"Bearer {token}"} 41 | api_url = f"{BASE_URL}/api/feed/?ids={ids}" 42 | response = await fetch(api_url, headers, method="GET") 43 | return response 44 | 45 | 46 | async def generate_music(data, token): 47 | headers = {"Authorization": f"Bearer {token}"} 48 | api_url = f"{BASE_URL}/api/generate/v2/" 49 | response = await fetch(api_url, headers, data) 50 | return response 51 | 52 | 53 | async def generate_lyrics(prompt, token): 54 | headers = {"Authorization": f"Bearer {token}"} 55 | api_url = f"{BASE_URL}/api/generate/lyrics/" 56 | data = {"prompt": prompt} 57 | return await fetch(api_url, headers, data) 58 | 59 | 60 | async def get_lyrics(lid, token): 61 | headers = {"Authorization": f"Bearer {token}"} 62 | api_url = f"{BASE_URL}/api/generate/lyrics/{lid}" 63 | return await fetch(api_url, headers, method="GET") 64 | 65 | 66 | async def get_credits(token): 67 | headers = {"Authorization": f"Bearer {token}"} 68 | api_url = f"{BASE_URL}/api/billing/info/" 69 | respose = await fetch(api_url, headers, method="GET") 70 | return { 71 | "credits_left": respose['total_credits_left'], 72 | "period": respose['period'], 73 | "monthly_limit": respose['monthly_limit'], 74 | "monthly_usage": respose['monthly_usage'] 75 | } 76 | --------------------------------------------------------------------------------