+ Random Pic, still need fix
All checks were successful
Update Website / update (push) Successful in 4s
All checks were successful
Update Website / update (push) Successful in 4s
This commit is contained in:
parent
e374c05671
commit
49c607db4a
3 changed files with 171 additions and 1 deletions
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
const NameList = () => {
|
||||
const names = ['TicTacToe','TodoList','FoodOrderer'];
|
||||
const names = ['TicTacToe','TodoList','FoodOrderer','RandomAnimeGirl'];
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-100 flex justify-center items-center p-4">
|
||||
|
|
168
src/RandomAnimeGirl.tsx
Normal file
168
src/RandomAnimeGirl.tsx
Normal file
|
@ -0,0 +1,168 @@
|
|||
import React, { useState } from "react";
|
||||
import { blob } from "stream/consumers";
|
||||
import { Url } from "url";
|
||||
|
||||
interface ApiResponse {
|
||||
success: boolean;
|
||||
status: number;
|
||||
key?: string;
|
||||
count?: number;
|
||||
id?: string;
|
||||
colors?: {
|
||||
main: string;
|
||||
palette: string[];
|
||||
};
|
||||
image?: {
|
||||
original: {
|
||||
url: string;
|
||||
extension: string;
|
||||
};
|
||||
compressed: {
|
||||
url: string;
|
||||
extension: string;
|
||||
};
|
||||
};
|
||||
metadata?: {
|
||||
original: {
|
||||
width: number;
|
||||
height: number;
|
||||
size: number;
|
||||
extension: string;
|
||||
};
|
||||
compressed: {
|
||||
width: number;
|
||||
height: number;
|
||||
size: number;
|
||||
extension: string;
|
||||
};
|
||||
};
|
||||
category?: string;
|
||||
tags?: string[];
|
||||
rating?: "safe" | "questionable";
|
||||
anime?: {
|
||||
title: string | null;
|
||||
character: string | null;
|
||||
};
|
||||
source?: {
|
||||
url: string | null;
|
||||
direct: string | null;
|
||||
};
|
||||
attribution?: {
|
||||
artist: {
|
||||
username: string | null;
|
||||
profile: string | null;
|
||||
};
|
||||
copyright: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Api {
|
||||
constructor() { }
|
||||
static validEndpoints: string[] = ['catgirl', 'foxgirl', 'wolf-girl', 'animal-ears', 'tail', 'tail-with-ribbon', 'cuteness-is-justice', 'blue-archive', 'girl', 'young-girl', 'maid', 'maid-uniform', 'vtuber', 'w-sitting', 'lying-down', 'hands-forming-a-heart', 'wink', 'valentine', 'headphonesthigh-high-socks', 'knee-high-socks', 'white-tights', 'black-tights', 'heterochromia', 'uniform', 'sailor-uniform', 'hoodie', 'ribbon', 'white-hair', 'blue-hair', 'long-hair', 'blonde', 'blue-eyes', 'purple-eyes']
|
||||
static baseUrl: string = "https://api.nekosia.cat/api/v1/images/"
|
||||
|
||||
async getFromEndpoint(endpoint: string): Promise<ApiResponse> {
|
||||
if (endpoint! in Api.validEndpoints) {
|
||||
return { success: false, status: -1 }
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(Api.baseUrl + endpoint)
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`)
|
||||
}
|
||||
|
||||
const data: ApiResponse = await response.json()
|
||||
return data
|
||||
} catch (error) {
|
||||
console.error("Error fetching API:", error);
|
||||
throw error; // Re-throw the error for caller to handle
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async function getImage(data: ApiResponse): Promise<Blob | null> {
|
||||
if (data.source == undefined || data.source.direct == null) {
|
||||
return null
|
||||
}
|
||||
const url = data.source.direct.replace('i.pximg.net', 'p.lolicon.cyou')
|
||||
let result: Blob | null = null
|
||||
|
||||
const response = await fetch(url, { method: "GET" })
|
||||
|
||||
if (response.status != 200) {
|
||||
if (response.status == 404 && data.image != undefined) { // 尝试使用备用的
|
||||
const backup = await fetch(data.image.original.url, { method: "GET" })
|
||||
if (backup.status == 200) {
|
||||
result = await backup.blob()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = await response.blob()
|
||||
}
|
||||
|
||||
return result // null 就是获取失败了
|
||||
}
|
||||
|
||||
function getImageUrl(data: ApiResponse): string | null {
|
||||
if (data.source == undefined || data.source.direct == null) {
|
||||
return null
|
||||
}
|
||||
const url = data.source.direct.replace('i.pximg.net', 'p.lolicon.cyou')
|
||||
return url
|
||||
}
|
||||
|
||||
|
||||
function handleGetImage(type: string | null, setter: React.Dispatch<React.SetStateAction<string>>) {
|
||||
let endpoint = `${type}`
|
||||
if (type === null) {
|
||||
const randomIndex = Math.floor(Math.random() * Api.validEndpoints.length);
|
||||
endpoint = Api.validEndpoints[randomIndex]
|
||||
}
|
||||
let api = new Api();
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const result = await api.getFromEndpoint(endpoint)
|
||||
const image = null
|
||||
// const image = await getImage(result)
|
||||
if (image != null) {
|
||||
setter(URL.createObjectURL(image));
|
||||
} else {
|
||||
const imageUrl = getImageUrl(result)
|
||||
if (imageUrl != null) {
|
||||
setter(imageUrl)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
|
||||
const RandomAnimeGirl = () => {
|
||||
const [imageSrc, setImageSrc] = useState("https://p.lolicon.cyou/img-original/img/2023/09/06/19/20/27/111496024_p0.png")
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen bg-gray-100">
|
||||
<h1 className="text-3xl font-bold mb-6">Random Image Viewer</h1>
|
||||
<img
|
||||
id="image"
|
||||
src={imageSrc}
|
||||
alt="Random"
|
||||
className="w-full max-w-lg rounded shadow-lg border border-gray-300"
|
||||
/>
|
||||
<button
|
||||
onClick={() => handleGetImage(null, setImageSrc)}
|
||||
className="mt-6 px-6 py-3 text-white bg-blue-500 hover:bg-blue-600 rounded-lg shadow-md transition"
|
||||
>
|
||||
Show Random Image
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default RandomAnimeGirl
|
|
@ -7,6 +7,7 @@ import TodoList from "./TodoList";
|
|||
import NameList from "./App";
|
||||
import FoodOrderer from "./FoodOrderer";
|
||||
import { BrowserRouter, Routes, Route } from "react-router-dom";
|
||||
import RandomAnimeGirl from "./RandomAnimeGirl";
|
||||
|
||||
const root = createRoot(document.getElementById("root"));
|
||||
root.render(
|
||||
|
@ -22,6 +23,7 @@ root.render(
|
|||
<Route path="/TicTacToe" element={<TicTacToe />} />
|
||||
<Route path="/TodoList" element={<TodoList />} />
|
||||
<Route path="/FoodOrderer" element={<FoodOrderer />} />
|
||||
<Route path="/RandomAnimeGirl" element={<RandomAnimeGirl />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</StrictMode>
|
||||
|
|
Loading…
Reference in a new issue