mirror of
https://gitlab.com/2-chainz/2chainz.git
synced 2025-08-05 05:01:27 +00:00
Compare commits
8 Commits
08c4b96918
...
main
Author | SHA1 | Date | |
---|---|---|---|
305ee50cdf | |||
7d1c8a3e64 | |||
1da2d71eeb | |||
fbf10556ee | |||
52dd2fd00f | |||
49d023b229 | |||
130a9354cb | |||
8421d7092f |
11
Dockerfile
11
Dockerfile
@@ -10,17 +10,10 @@ ENV UV_COMPILE_BYTECODE=1
|
||||
# Copy from the cache instead of linking since it's a mounted volume
|
||||
ENV UV_LINK_MODE=copy
|
||||
|
||||
# Copy dependency files
|
||||
COPY uv.lock pyproject.toml ./
|
||||
|
||||
# Install the project's dependencies using the lockfile and settings
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --locked --no-install-project --no-dev
|
||||
|
||||
# Then, add the rest of the project source code and install it
|
||||
COPY . /app
|
||||
|
||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||
uv sync --locked --no-dev
|
||||
|
||||
CMD ["uv", "run", "fastapi", "run", "src/two_chainz", "--port", "80", "--proxy-headers"]
|
||||
CMD ["uv", "run", "--no-dev", "fastapi", "run", "src/two_chainz", "--port", "80", "--proxy-headers"]
|
||||
|
||||
|
81
data.toml
81
data.toml
@@ -26,7 +26,6 @@ quotes = [
|
||||
"If I die, bury me inside the Louis store",
|
||||
"GI-VEN-CHY, nigga God Bless you",
|
||||
"My favorite dish is turkey lasagna\nEven my pajamas designer",
|
||||
"Walked in, ill nigga alert! ill nigga alert!",
|
||||
"Like fuck your baby daddy, his daddy should've worn a condom",
|
||||
"I'm the type of nigga thats built to last.\nYou fuck with me, Ill put my foot in your ass",
|
||||
"I wish a nigga would like a kitchen cabinet",
|
||||
@@ -37,7 +36,6 @@ quotes = [
|
||||
"#making bands, yes I am",
|
||||
"I wear versace like its nike, you don't like it do you?",
|
||||
"I bet you feel this bank roll if I bump into you",
|
||||
"Like fuck your baby daddy, his daddy should've wore a condom",
|
||||
"Sprinter van on me, I got them xans on me,\nDriveway so damn long by the time I leave I'm damn asleep",
|
||||
"Bitches round my pool, I made them hoes look like my landscape",
|
||||
"Everything Proper, no propaganda",
|
||||
@@ -103,11 +101,83 @@ quotes = [
|
||||
"I'm at Esco, double park in front of the firehouse and I'm fire as hell",
|
||||
"F y'all niggas, ex-drug dealer, ex-ball player, X Games\nGoin' down like Aspen, diamonds in the watch like Aspirin",
|
||||
"I had that pussy pissin once I hit that Kidney",
|
||||
"Told my lawyer, \"Imma call you back, this my other lawyer\"",
|
||||
"if you was a computer, you would be a Microsoft",
|
||||
"you don't brush, thats the only way you gon' get some plaques today",
|
||||
"call me Dos Cadenas, por favor",
|
||||
"I be eatin shrim and crab legs every day",
|
||||
"Yesterday when I woke up, I ate lobster",
|
||||
"she said she wanna drink my kids, foster",
|
||||
"I'm indulgin' cause money the motivator",
|
||||
"Its a good day to get some paper",
|
||||
"I'm a digi-scale user, and you just a user",
|
||||
"Tighter than a thong, you're assed out",
|
||||
"Me and my wife sip wine somewhere you can't find",
|
||||
"I smell like Porsche and Benihanas",
|
||||
"I don't gatekeep, I want everyone to eat",
|
||||
"Expired tag, I ride with a lawyer",
|
||||
"After the performance, I hopped in a foreign",
|
||||
"mind full of greed - Pellegrino, lemon squeeze",
|
||||
"lookin at a chandelier during a wine tasting",
|
||||
"Louis bag, Prada bag, body bag, kinda sad",
|
||||
"rapping my therapy",
|
||||
"eat mushrooms like they jellybeans",
|
||||
"Mindin' my business, drinkin' water, doin' crunches",
|
||||
"Getting paid for discussions over Alchemist production",
|
||||
"wear a Rollie when I'm fuckin'",
|
||||
"You need to put a condom on cause you may not be that lucky",
|
||||
"drinkin codeine in my Phantom",
|
||||
"came with three hoes like I'm Santa",
|
||||
"Hustle plus passion equals success",
|
||||
"Sellin seasoning to Martha Stewart",
|
||||
"This track ought to wake'em up, call it Folgers",
|
||||
"Me llama Dos Cadenas, baby, buenas noches",
|
||||
"Yeah I like it when its tight but imma make it looser",
|
||||
"Got a gold toilet bowl to take a number deuce",
|
||||
"I gave her the D, like she was tryin to play some offense",
|
||||
"told him fly us Precheck",
|
||||
"Before we hit the driveway, got my hand on her thighs",
|
||||
"concrete jungle, I'll fuck Jane though",
|
||||
"We on different planes if we is in the same boat",
|
||||
"She so thick, its kinda hard to say skinny dip",
|
||||
"I'm cuffin, put the pussy on probation",
|
||||
"Rivalry appear, cauliflower his ear",
|
||||
"Pull a rabbit out the hat with the magic stick",
|
||||
"Checkerboard luggage, ramen in the cupboard",
|
||||
"Vocals warmed up, beyond Ford tough",
|
||||
"You know, you deserve the Pretty Pussy Award",
|
||||
"Sound like I'm stirrin' mac and cheese in your lap",
|
||||
"I got blinds in my whip like a condo",
|
||||
"Whats a gorilla to Godzilla?",
|
||||
"I don't compete, but you can't compete",
|
||||
"we on a date, make it rain some ones",
|
||||
"I keep it rollin like paraplegic",
|
||||
"I did the math, ain't no way we equal",
|
||||
"This is chess not checkers, like an A-cup",
|
||||
"Two BBLs, you know she extra",
|
||||
"In the kitchen, scale, fork, and pistol",
|
||||
"I done fell in love with a thicc bitch",
|
||||
"You know I been trappin since the dial-up",
|
||||
"I am so cold, it look like Freon attack",
|
||||
"this a Cullinan, bitch, not a Range Rover",
|
||||
"I'm the real thing, you a carbon copy",
|
||||
"I got my hands on her ass like a motorcycle",
|
||||
"I like pussy, she like pussy, we just like twins",
|
||||
"FN with hollow tips, I ain't with the politics",
|
||||
"If you don't see me shining you need an optometrist",
|
||||
"Always with the dog, like I'm Charlie Brown",
|
||||
"Tony Alimony - married to the streets",
|
||||
"My favorite plastic bag got some drugs in it",
|
||||
"I wish Nobu had a drive-thru",
|
||||
"I bet the neighbors know my name, they call me \"Oh fuck, oh shit\"",
|
||||
"I'm rich and ratchet",
|
||||
"First rapper with a Versace deal, did a chain reaction",
|
||||
]
|
||||
|
||||
|
||||
aliases = [
|
||||
{ name = "2 Chainz", weight = 50 },
|
||||
{ name = "2 Chainzzzzz", weight = 50 },
|
||||
{ name = "Tity Boi", weight = 10 },
|
||||
{ name = "Daniel Son; Necklace Don", weight = 10 },
|
||||
{ name = "Drenchgod", weight = 5 },
|
||||
@@ -120,10 +190,15 @@ aliases = [
|
||||
{ name = "JEFE", weight = 5 },
|
||||
{ name = "TONI", weight = 25 },
|
||||
{ name = "BIG TONI", weight = 10 },
|
||||
{ name = "PRETTI TONI", weight = 1 },
|
||||
{ name = "PRETTI TONI", weight = 10 },
|
||||
{ name = "TONÉ", weight = 1 },
|
||||
{ name = "2 TONE TONI", weight = 5 },
|
||||
{ name = "TONI 2-STIX", weight = 1 },
|
||||
{ name = "TONI KEYS", weight = 1 },
|
||||
{ name = "FAT TONI", weight = 10 },
|
||||
{ name = "Colossal", weight = 1 },
|
||||
{ name = "Cane Corso", weight = 1 },
|
||||
{ name = "Escobar Owner", weight = 15 },
|
||||
{ name = "Toni", weight = 10 },
|
||||
{ name = "Deuce", weight = 10 },
|
||||
]
|
||||
|
@@ -18,4 +18,8 @@ build-backend = "hatchling.build"
|
||||
packages = ["src/two_chainz"]
|
||||
|
||||
[dependency-groups]
|
||||
dev = ["httpx>=0.28.1", "pytest>=8.3.5", "ruff>=0.11.11"]
|
||||
dev = [
|
||||
"nltk>=3.9.1",
|
||||
"pytest>=8.3.5",
|
||||
"ruff>=0.11.11",
|
||||
]
|
||||
|
@@ -1,8 +1,10 @@
|
||||
from datetime import datetime
|
||||
from unittest.mock import patch
|
||||
from itertools import combinations
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from nltk.metrics.distance import edit_distance
|
||||
|
||||
import two_chainz
|
||||
from two_chainz import app
|
||||
@@ -28,8 +30,8 @@ class TestApi:
|
||||
@pytest.mark.parametrize(
|
||||
"mocked_time,start_time,expected",
|
||||
[
|
||||
(100, 50, 50), # 100 - 50 = 50 seconds uptime
|
||||
(200, 100, 100), # 200 - 100 = 100 seconds uptime
|
||||
(100, 50, "50"), # 100 - 50 = 50 seconds uptime
|
||||
(200, 100, "100"), # 200 - 100 = 100 seconds uptime
|
||||
],
|
||||
)
|
||||
def test_api_uptime_calculation(self, mocked_time, start_time, expected):
|
||||
@@ -68,8 +70,13 @@ class TestData:
|
||||
assert two_chainz.data["quotes"]
|
||||
assert two_chainz.data["aliases"]
|
||||
|
||||
@pytest.mark.parametrize("a, b", combinations(two_chainz.data["quotes"], 2))
|
||||
def test_no_duplicate_quotes(self, a, b):
|
||||
"Use the Levenshtein edit distance since I hand write all the quotes"
|
||||
assert 2 < edit_distance(a, b)
|
||||
|
||||
@pytest.mark.parametrize("quote", two_chainz.data["quotes"])
|
||||
class TestQuotes:
|
||||
class TestQuote:
|
||||
def test_no_empty(self, quote):
|
||||
assert quote
|
||||
|
||||
|
@@ -3,18 +3,19 @@ import time
|
||||
import tomllib
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
import logging
|
||||
from fastapi import FastAPI, Request
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.trustedhost import TrustedHostMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
app = FastAPI()
|
||||
app = FastAPI(
|
||||
title="2 Chainz REST",
|
||||
description="A simple API to get 2 Chainz quotes and aliases. See <a href=https://2chainz.ansonbiggs.com>2chainz.ansonbiggs.com</a> for a full explanation.",
|
||||
)
|
||||
app.add_middleware(
|
||||
TrustedHostMiddleware,
|
||||
allowed_hosts=["*"],
|
||||
)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
@@ -31,37 +32,80 @@ def read_data() -> dict[str, str]:
|
||||
data = read_data()
|
||||
|
||||
|
||||
# Log all requests to debug issues
|
||||
@app.middleware("http")
|
||||
async def log_requests(request: Request, call_next):
|
||||
# Log what's coming in
|
||||
logger.info(f"Request: {request.method} {request.url.path}")
|
||||
logger.info(f"Host header: {request.headers.get('host')}")
|
||||
logger.info(f"CF-Ray: {request.headers.get('cf-ray', 'Not from Cloudflare')}")
|
||||
@app.get(
|
||||
"/api/",
|
||||
summary="Health Check",
|
||||
description="Check API health status and uptime",
|
||||
response_description="Health status with timestamp and uptime",
|
||||
tags=["Health"],
|
||||
responses={
|
||||
200: {
|
||||
"description": "Successful health check",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": {
|
||||
"status": "ok",
|
||||
"timestamp": "2025-05-24T10:30:00",
|
||||
"uptime_seconds": "3600.5",
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
async def ping() -> dict[str, str]:
|
||||
"""
|
||||
Endpoint to check on the health of the API and to help diagnose issues.
|
||||
|
||||
try:
|
||||
response = await call_next(request)
|
||||
return response
|
||||
except Exception as e:
|
||||
logger.error(f"Request processing failed: {e}")
|
||||
raise
|
||||
|
||||
|
||||
@app.get("/api/")
|
||||
async def ping():
|
||||
Returns current status, timestamp, and uptime information.
|
||||
"""
|
||||
return {
|
||||
"status": "ok",
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"uptime_seconds": round(time.time() - start_time, 2),
|
||||
"uptime_seconds": str(round(time.time() - start_time, 2)),
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/quote")
|
||||
@app.get(
|
||||
"/api/quote",
|
||||
summary="2 Chainz Quote",
|
||||
description="Get a quote from 2 Chainz",
|
||||
tags=["Data"],
|
||||
responses={
|
||||
200: {
|
||||
"description": "Successful quote",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": {
|
||||
"quote": "Wood grain chestnut, titty fuck chest nut",
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
async def quote():
|
||||
return {"quote": random.choice(data["quotes"])}
|
||||
|
||||
|
||||
@app.get("/api/alias")
|
||||
@app.get(
|
||||
"/api/alias",
|
||||
summary="2 Chainz Alias",
|
||||
description="Get one of 2 Chainz many aliases",
|
||||
tags=["Data"],
|
||||
responses={
|
||||
200: {
|
||||
"description": "Successful alias",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": {
|
||||
"alias": "2 Chainz",
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
async def alias():
|
||||
return {"alias": random.choice(data["aliases"])}
|
||||
|
||||
|
66
uv.lock
generated
66
uv.lock
generated
@@ -1,4 +1,5 @@
|
||||
version = 1
|
||||
revision = 1
|
||||
requires-python = ">=3.13"
|
||||
|
||||
[[package]]
|
||||
@@ -11,7 +12,7 @@ dependencies = [
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "httpx" },
|
||||
{ name = "nltk" },
|
||||
{ name = "pytest" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
@@ -21,7 +22,7 @@ requires-dist = [{ name = "fastapi", extras = ["standard"], specifier = ">=0.115
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "httpx", specifier = ">=0.28.1" },
|
||||
{ name = "nltk", specifier = ">=3.9.1" },
|
||||
{ name = "pytest", specifier = ">=8.3.5" },
|
||||
{ name = "ruff", specifier = ">=0.11.11" },
|
||||
]
|
||||
@@ -62,7 +63,7 @@ name = "click"
|
||||
version = "8.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342 }
|
||||
wheels = [
|
||||
@@ -225,6 +226,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "joblib"
|
||||
version = "1.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dc/fe/0f5a938c54105553436dbff7a61dc4fed4b1b2c98852f8833beaf4d5968f/joblib-1.5.1.tar.gz", hash = "sha256:f4f86e351f39fe3d0d32a9f2c3d8af1ee4cec285aafcb27003dda5205576b444", size = 330475 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/4f/1195bbac8e0c2acc5f740661631d8d750dc38d4a32b23ee5df3cde6f4e0d/joblib-1.5.1-py3-none-any.whl", hash = "sha256:4719a31f054c7d766948dcd83e9613686b27114f190f717cec7eaa2084f8a74a", size = 307746 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markdown-it-py"
|
||||
version = "3.0.0"
|
||||
@@ -274,6 +284,21 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nltk"
|
||||
version = "3.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "joblib" },
|
||||
{ name = "regex" },
|
||||
{ name = "tqdm" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3c/87/db8be88ad32c2d042420b6fd9ffd4a149f9a0d7f0e86b3f543be2eeeedd2/nltk-3.9.1.tar.gz", hash = "sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868", size = 2904691 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/66/7d9e26593edda06e8cb531874633f7c2372279c3b0f46235539fe546df8b/nltk-3.9.1-py3-none-any.whl", hash = "sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1", size = 1505442 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "25.0"
|
||||
@@ -394,6 +419,29 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "2024.11.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8e/5f/bd69653fbfb76cf8604468d3b4ec4c403197144c7bfe0e6a5fc9e02a07cb/regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519", size = 399494 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/90/73/bcb0e36614601016552fa9344544a3a2ae1809dc1401b100eab02e772e1f/regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84", size = 483525 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/3f/f1a082a46b31e25291d830b369b6b0c5576a6f7fb89d3053a354c24b8a83/regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4", size = 288324 },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/c9/4e68181a4a652fb3ef5099e077faf4fd2a694ea6e0f806a7737aff9e758a/regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0", size = 284617 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/fd/37868b75eaf63843165f1d2122ca6cb94bfc0271e4428cf58c0616786dce/regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0", size = 795023 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/7c/d4cd9c528502a3dedb5c13c146e7a7a539a3853dc20209c8e75d9ba9d1b2/regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7", size = 833072 },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/db/46f563a08f969159c5a0f0e722260568425363bea43bb7ae370becb66a67/regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7", size = 823130 },
|
||||
{ url = "https://files.pythonhosted.org/packages/db/60/1eeca2074f5b87df394fccaa432ae3fc06c9c9bfa97c5051aed70e6e00c2/regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c", size = 796857 },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/db/ac718a08fcee981554d2f7bb8402f1faa7e868c1345c16ab1ebec54b0d7b/regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3", size = 784006 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/41/7da3fe70216cea93144bf12da2b87367590bcf07db97604edeea55dac9ad/regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07", size = 781650 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/d5/880921ee4eec393a4752e6ab9f0fe28009435417c3102fc413f3fe81c4e5/regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e", size = 789545 },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/96/53770115e507081122beca8899ab7f5ae28ae790bfcc82b5e38976df6a77/regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6", size = 853045 },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/d3/1372add5251cc2d44b451bd94f43b2ec78e15a6e82bff6a290ef9fd8f00a/regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4", size = 860182 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/e3/c446a64984ea9f69982ba1a69d4658d5014bc7a0ea468a07e1a1265db6e2/regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d", size = 787733 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/f1/e40c8373e3480e4f29f2692bd21b3e05f296d3afebc7e5dcf21b9756ca1c/regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff", size = 262122 },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/94/bc295babb3062a731f52621cdc992d123111282e291abaf23faa413443ea/regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a", size = 273545 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rich"
|
||||
version = "14.0.0"
|
||||
@@ -476,6 +524,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tqdm"
|
||||
version = "4.67.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typer"
|
||||
version = "0.15.3"
|
||||
|
@@ -40,106 +40,67 @@
|
||||
:root {
|
||||
--color: darkviolet;
|
||||
--color-bg-secondary: black;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 400px) {
|
||||
#scroll-icon {
|
||||
display: none;
|
||||
}
|
||||
--color-link: darkviolet;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header style="height: 70vh;">
|
||||
<header style="height: 90vh">
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://2chainz.ansonbiggs.com">2chainz.ansonbiggs.com</a> - A REST API for 2
|
||||
Chainz Quotes
|
||||
</li>
|
||||
</ul>
|
||||
<a href="https://2chainz.ansonbiggs.com">2chainz.ansonbiggs.com</a>
|
||||
<p>A REST API for 2 Chainz Quotes</p>
|
||||
<a href="https://gitlab.com/2-chainz/2chainz">Source Code</a>
|
||||
</nav>
|
||||
<section>
|
||||
<blockquote>
|
||||
<span id="quote"></span>
|
||||
<section style="height: 50vh">
|
||||
<blockquote style="margin: auto">
|
||||
<span id="quote">TRUUUUUUUU</span>
|
||||
<footer><i id="alias">- 2 Chainz</i></footer>
|
||||
</blockquote>
|
||||
</section>
|
||||
<p>
|
||||
<section>
|
||||
<a onclick="getQuote()" href="#"
|
||||
><b>
|
||||
<ion-icon size="large" name="refresh-circle"></ion-icon><br />
|
||||
New Quote</b
|
||||
></a
|
||||
>
|
||||
<a id="tweet" href="#"
|
||||
><b
|
||||
><ion-icon size="large" name="logo-twitter"></ion-icon> <br />
|
||||
Tweet Quote
|
||||
</b></a
|
||||
>
|
||||
</p>
|
||||
<a href="#scroll" id="scroll-icon" style="padding-top: 10vh;"
|
||||
><b style="width: 20vw">
|
||||
<ion-icon size="large" name="refresh-circle"></ion-icon>
|
||||
<span style="display: grid; place-items: center">New Quote</span>
|
||||
</b>
|
||||
</a>
|
||||
</section>
|
||||
<a href="#scroll" id="scroll-icon" style="padding-top: 10vh"
|
||||
><ion-icon size="large" name="arrow-down-sharp"></ion-icon
|
||||
></a>
|
||||
</header>
|
||||
<main>
|
||||
<hr style="padding-top: 0;" />
|
||||
<hr style="padding-top: 0" />
|
||||
<header id="scroll">
|
||||
<h2>Usage</h2>
|
||||
<p>
|
||||
For exhaustive and up to date documentation see
|
||||
<a href="/docs">/docs</a>
|
||||
</p>
|
||||
</header>
|
||||
<details open>
|
||||
<summary>Quote</summary>
|
||||
|
||||
<p>
|
||||
Returns a random 2 Chainz Quote in <code>json</code> format like the
|
||||
following example:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
send a <code>get</code> request to
|
||||
<code
|
||||
><a href="https://chainz.ansonbiggs.com/api/quote"
|
||||
>https://chainz.ansonbiggs.com/api/quote</a
|
||||
><a href="https://2chainz.ansonbiggs.com/api/quote"
|
||||
>https://2chainz.ansonbiggs.com/api/quote</a
|
||||
></code
|
||||
>
|
||||
</p>
|
||||
|
||||
<pre><code>{
|
||||
"quote": "I got a pocket full of money, it got me walking all slew-foot"
|
||||
}</code></pre>
|
||||
|
||||
<details style="margin-left: 5%;">
|
||||
<summary>Parameters</summary>
|
||||
|
||||
<p>
|
||||
This endpoint also supports an optional <code>batch</code> parameter
|
||||
to get more than one quote per request. Maximum quotes that the
|
||||
endpoint will return is the amount of quotes in
|
||||
<a
|
||||
href="https://gitlab.com/2-chainz/2-chainz-rest/-/blob/master/quote/quotes.py"
|
||||
>quotes.py</a
|
||||
>
|
||||
and is subject to change. An example return from
|
||||
<code>
|
||||
<a href="https://chainz.ansonbiggs.com/api/quote?batch=2"
|
||||
>https://chainz.ansonbiggs.com/api/quote?batch=2</a
|
||||
></code
|
||||
>
|
||||
</p>
|
||||
|
||||
<pre><code class="json">{
|
||||
"quotes": [
|
||||
"I'm in the kitchen. Yams errrrrwhere.",
|
||||
"Started from the trap, now I rap"
|
||||
]
|
||||
}</code></pre>
|
||||
</details>
|
||||
}</code></pre>
|
||||
</details>
|
||||
|
||||
<details
|
||||
><summary>Alias</summary>
|
||||
<details>
|
||||
<summary>Alias</summary>
|
||||
<p>
|
||||
Returns a random 2 Chainz alias in <code>json</code> format. The
|
||||
return values are weighted and a full list can be seen in
|
||||
@@ -151,20 +112,21 @@
|
||||
<p>
|
||||
send a <code>get</code> request to
|
||||
<code
|
||||
><a href="https://chainz.ansonbiggs.com/api/alias"
|
||||
>https://chainz.ansonbiggs.com/api/alias</a
|
||||
><a href="https://2chainz.ansonbiggs.com/api/alias"
|
||||
>https://2chainz.ansonbiggs.com/api/alias</a
|
||||
></code
|
||||
>
|
||||
</p>
|
||||
<pre><code>{
|
||||
"alias": "Dos Cadenas"
|
||||
}</code></pre>
|
||||
}</code></pre>
|
||||
</details>
|
||||
<hr />
|
||||
<section>
|
||||
<header>
|
||||
<h2>
|
||||
Projects built using 2chainz.ansonbiggs.com (Your project could be here!)
|
||||
Projects built using 2chainz.ansonbiggs.com (Your project could be
|
||||
here!)
|
||||
</h2>
|
||||
</header>
|
||||
<aside>
|
||||
@@ -214,7 +176,7 @@
|
||||
</p>
|
||||
<p>
|
||||
<small
|
||||
><a href="https://twitter.com/Anson_3D"
|
||||
><a href="https://ansonbiggs.com/#connect"
|
||||
>Please let me know if you use it though!</a
|
||||
></small
|
||||
>
|
||||
@@ -224,43 +186,31 @@
|
||||
<h3>Do I need an API key or is this API rate limited?</h3>
|
||||
<p>
|
||||
No, the API is totally free and unlimited. However, its being hosted
|
||||
by a college student so be nice.
|
||||
on a tiny machine that is overburdened by docker containers.
|
||||
</p>
|
||||
</aside>
|
||||
<aside>
|
||||
<h3>Is this project open source? Can I contribute?</h3>
|
||||
<p>
|
||||
Yes and Yes! Check out the
|
||||
<a href="https://gitlab.com/2-chainz">Project on GitLab.</a>
|
||||
<a href="https://gitlab.com/2-chainz/2chainz">Project on GitLab.</a>
|
||||
</p>
|
||||
</aside>
|
||||
<aside>
|
||||
<h3>Does 2 Chainz know about this?</h3>
|
||||
<p>
|
||||
Probably not.
|
||||
</p>
|
||||
<p>Probably not.</p>
|
||||
</aside>
|
||||
<aside>
|
||||
<h3>Why?</h3>
|
||||
<p>
|
||||
Because 2 Chainz has some of the best lines in the rap game.
|
||||
</p>
|
||||
<p>Because 2 Chainz has some of the best lines in the rap game.</p>
|
||||
</aside>
|
||||
</section>
|
||||
</main>
|
||||
<footer>
|
||||
<hr />
|
||||
<p>
|
||||
Made by <a href="https://gitlab.com/MisterBiggs">Anson Biggs</a>,
|
||||
<a href="https://twitter.com/Anson_3D">@Anson_3D </a>
|
||||
</p>
|
||||
<p>
|
||||
Inspired By <a href="https://kanye.rest/">kanye.rest</a> which was
|
||||
created by:
|
||||
<a href="https://ajzbc.com" target="_blank">Andrew Jazbec</a>,
|
||||
<a href="https://twitter.com/ajzbc" target="_blank">@ajzbc</a>
|
||||
</p>
|
||||
<p><small>Truuuuuuuu</small></p>
|
||||
<p>Made by <a href="https://ansonbiggs.com">Anson</a></p>
|
||||
<p>Inspired By <a href="https://kanye.rest/">kanye.rest</a>.</p>
|
||||
<p><small>Truuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu</small></p>
|
||||
</footer>
|
||||
<script>
|
||||
getQuote();
|
||||
@@ -270,13 +220,6 @@
|
||||
.then((resp) => resp.json())
|
||||
.then(function (data) {
|
||||
document.getElementById("quote").innerHTML = data.quote;
|
||||
|
||||
const tweet = encodeURIComponent(
|
||||
`"${data.quote}" -@2chainz via https://2chainz.ansonbiggs.com`
|
||||
);
|
||||
document.getElementById(
|
||||
"tweet"
|
||||
).href = `https://twitter.com/intent/tweet?text=${tweet}`;
|
||||
});
|
||||
|
||||
fetch("/api/alias", { method: "GET" })
|
||||
@@ -286,6 +229,13 @@
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script src="https://unpkg.com/ionicons@5.0.0/dist/ionicons.js"></script>
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"
|
||||
></script>
|
||||
<script
|
||||
nomodule
|
||||
src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"
|
||||
></script>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user