1
0
mirror of https://gitlab.com/2-chainz/2chainz.git synced 2025-06-15 17:36:39 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
49d023b229 fix tests 2025-05-23 21:34:05 -06:00
130a9354cb finish documenting and fixing the site 2025-05-23 21:31:52 -06:00
8421d7092f Remove testing code 2025-05-23 15:59:17 -06:00
3 changed files with 120 additions and 126 deletions

View File

@ -28,8 +28,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):

View File

@ -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"])}

View File

@ -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>
"quote": "I got a pocket full of money, it got me walking all slew-foot"
}</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>
"alias": "Dos Cadenas"
}</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>