First commit
This commit is contained in:
commit
455ae8c0ee
36 changed files with 677 additions and 0 deletions
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
18
package.json
Normal file
18
package.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dayjs": "^1.10.7",
|
||||||
|
"next": "latest",
|
||||||
|
"react": "^17.0.2",
|
||||||
|
"react-dom": "^17.0.2",
|
||||||
|
"swr": "^1.0.1",
|
||||||
|
"redis": "^4.0.1",
|
||||||
|
"dotenv": "^10.0.0",
|
||||||
|
"fast-levenshtein": "^3.0.0"
|
||||||
|
}
|
||||||
|
}
|
21
pages/api/artifacts/[id].js
Normal file
21
pages/api/artifacts/[id].js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import {getArtifacts} from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function artifactHandler({query: {id}}, res) {
|
||||||
|
let artifact = JSON.parse(await getResultFromRedis(`artifact-${id}`))
|
||||||
|
if (!artifact) {
|
||||||
|
let artifacts = JSON.parse(await getResultFromRedis("artifact-all"));
|
||||||
|
if (!artifacts){
|
||||||
|
artifacts = await getArtifacts();
|
||||||
|
addResultToRedis("artifact-all", JSON.stringify(artifacts)).catch(console.error);
|
||||||
|
}
|
||||||
|
artifact = artifacts[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (artifact) {
|
||||||
|
res.status(200).json(artifact);
|
||||||
|
addResultToRedis(`artifact-${id}`, JSON.stringify(artifact)).catch(console.error)
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: `Artifact ${id} doesn't exist`})
|
||||||
|
}
|
||||||
|
}
|
21
pages/api/artifacts/index.js
Normal file
21
pages/api/artifacts/index.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import {getArtifacts} from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
let t0 = performance.now()
|
||||||
|
|
||||||
|
let artifacts = JSON.parse(await getResultFromRedis(`artifact-all`))
|
||||||
|
if (!artifacts) {
|
||||||
|
artifacts = await getArtifacts();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (artifacts) {
|
||||||
|
res.status(200).json(Object.keys(artifacts));
|
||||||
|
addResultToRedis(`artifact-all`, JSON.stringify(artifacts)).catch(console.error)
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: "An error has occurred"})
|
||||||
|
}
|
||||||
|
|
||||||
|
let t1 = performance.now();
|
||||||
|
console.debug(`Execution took ${t1-t0} ms`)
|
||||||
|
}
|
23
pages/api/artifacts/search/[id].js
Normal file
23
pages/api/artifacts/search/[id].js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import {getArtifacts} from "../utils";
|
||||||
|
import {getClosest} from "../../../../utils/levenshtein";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function artifactHandler({query: {id}}, res) {
|
||||||
|
|
||||||
|
let artifacts = JSON.parse(await getResultFromRedis('artifact-all'));
|
||||||
|
if (!artifacts) {
|
||||||
|
artifacts = await getArtifacts();
|
||||||
|
addResultToRedis('artifact-all', JSON.stringify(artifacts)).catch(console.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closestArtifacts = []
|
||||||
|
getClosest(id, artifacts).forEach(a => {
|
||||||
|
closestArtifacts.push(artifacts[a.name])
|
||||||
|
})
|
||||||
|
|
||||||
|
if (closestArtifacts) {
|
||||||
|
res.status(200).json(closestArtifacts);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: `Artifact ${id} not found`});
|
||||||
|
}
|
||||||
|
}
|
5
pages/api/artifacts/utils.js
Normal file
5
pages/api/artifacts/utils.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export async function getArtifacts(){
|
||||||
|
const res = await fetch("https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/artifacts/en.json");
|
||||||
|
const artifacts = JSON.parse(await res.text());
|
||||||
|
return artifacts;
|
||||||
|
}
|
21
pages/api/builds/[id].js
Normal file
21
pages/api/builds/[id].js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import {getBuilds} from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function buildHandler({query: {id}}, res) {
|
||||||
|
let build = JSON.parse(await getResultFromRedis(`build-${id}`));
|
||||||
|
if (!build) {
|
||||||
|
let builds = JSON.parse(await getResultFromRedis('build-all'));
|
||||||
|
if (!builds){
|
||||||
|
builds = await getBuilds();
|
||||||
|
addResultToRedis('build-all', JSON.stringify(builds)).catch(console.error);
|
||||||
|
}
|
||||||
|
build = builds[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (build) {
|
||||||
|
res.status(200).json(build);
|
||||||
|
addResultToRedis(`build-${id}`, JSON.stringify(build)).catch(console.error);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message : `Build for ${id} not found`});
|
||||||
|
}
|
||||||
|
}
|
16
pages/api/builds/index.js
Normal file
16
pages/api/builds/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import {getBuilds} from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
let builds = JSON.parse(await getResultFromRedis('build-all'));
|
||||||
|
if (!builds) {
|
||||||
|
builds = await getBuilds();
|
||||||
|
addResultToRedis('build-all', JSON.stringify(builds)).catch(console.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builds){
|
||||||
|
res.status(200).json(Object.keys(builds));
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: "An error has occurred"});
|
||||||
|
}
|
||||||
|
}
|
21
pages/api/builds/utils.js
Normal file
21
pages/api/builds/utils.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
const AsyncFunction = Object.getPrototypeOf(async function () {
|
||||||
|
}).constructor;
|
||||||
|
|
||||||
|
export async function getBuilds() {
|
||||||
|
let builds = await new AsyncFunction(
|
||||||
|
(await (await fetch(
|
||||||
|
"https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/build.js",
|
||||||
|
)).text()).replace("export const builds =", "return"),
|
||||||
|
)();
|
||||||
|
|
||||||
|
Object.values(builds).forEach(b => {
|
||||||
|
let d = [];
|
||||||
|
for (let c in b["roles"]) {
|
||||||
|
b["roles"][c]["name"] = c;
|
||||||
|
d.push(b["roles"][c]);
|
||||||
|
}
|
||||||
|
b["roles"] = d;
|
||||||
|
})
|
||||||
|
|
||||||
|
return builds;
|
||||||
|
}
|
21
pages/api/characters/[id].js
Normal file
21
pages/api/characters/[id].js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import {getCharacters} from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function characterHandler({query: {id}}, res) {
|
||||||
|
let character = JSON.parse(await getResultFromRedis(`character-${id}`));
|
||||||
|
if (!character) {
|
||||||
|
let characters = JSON.parse(await getResultFromRedis(`character-all`));
|
||||||
|
if (!characters) {
|
||||||
|
characters = await getCharacters();
|
||||||
|
addResultToRedis('character-all', JSON.stringify(characters)).catch(console.error);
|
||||||
|
}
|
||||||
|
character = characters[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character){
|
||||||
|
res.status(200).json(character);
|
||||||
|
addResultToRedis(`character-${id}`, JSON.stringify(character)).catch(console.error);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: `Character ${id} doesn't exist`});
|
||||||
|
}
|
||||||
|
}
|
15
pages/api/characters/index.js
Normal file
15
pages/api/characters/index.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import {getCharacters} from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
let characters = JSON.parse(await getResultFromRedis('character-all'));
|
||||||
|
if (!characters){
|
||||||
|
characters = await getCharacters();
|
||||||
|
addResultToRedis('character-all', JSON.stringify(characters)).catch(console.error)
|
||||||
|
}
|
||||||
|
if (characters) {
|
||||||
|
res.status(200).json(Object.keys(characters));
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: "An error has occurred"});
|
||||||
|
}
|
||||||
|
}
|
23
pages/api/characters/search/[id].js
Normal file
23
pages/api/characters/search/[id].js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import {getCharacters} from "../utils";
|
||||||
|
import {getClosest} from "../../../../utils/levenshtein";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function artifactHandler({query: {id}}, res) {
|
||||||
|
|
||||||
|
let characters = JSON.parse(await getResultFromRedis('character-all'));
|
||||||
|
if (!characters) {
|
||||||
|
characters = await getCharacters();
|
||||||
|
addResultToRedis('character-all', JSON.stringify(characters)).catch(console.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closestCharacters = []
|
||||||
|
getClosest(id, characters).forEach(a => {
|
||||||
|
closestCharacters.push(characters[a.name])
|
||||||
|
})
|
||||||
|
|
||||||
|
if (closestCharacters) {
|
||||||
|
res.status(200).json(closestCharacters);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: `Character ${id} not found`});
|
||||||
|
}
|
||||||
|
}
|
37
pages/api/characters/utils.js
Normal file
37
pages/api/characters/utils.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import {weapons} from "../weapons/utils";
|
||||||
|
import {getElements} from "../elements/utils";
|
||||||
|
import {getItems} from "../items/utils";
|
||||||
|
import {getBuilds} from "../builds/utils";
|
||||||
|
|
||||||
|
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
|
||||||
|
|
||||||
|
export async function getCharacters() {
|
||||||
|
|
||||||
|
const builds = await getBuilds();
|
||||||
|
|
||||||
|
let func = (await (await fetch(
|
||||||
|
"https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/characters.js",
|
||||||
|
)).text());
|
||||||
|
func = func.substr(func.indexOf("export const characters ="));
|
||||||
|
const characters = await new AsyncFunction(
|
||||||
|
"weapons",
|
||||||
|
"elements",
|
||||||
|
"itemList",
|
||||||
|
func.replace("export const characters = ", "return"),
|
||||||
|
)(weapons, await getElements(), await getItems());
|
||||||
|
|
||||||
|
for (let chr in characters){
|
||||||
|
characters[chr].builds = builds[chr]['roles'];
|
||||||
|
for (let y in characters[chr]['ascension']) {
|
||||||
|
for (let x in characters[chr]['ascension'][y].items) {
|
||||||
|
if (!characters[chr]['ascension'][y]["items"][x]["amount"]) {
|
||||||
|
delete characters[chr]['ascension'][y]["items"].splice(x, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return characters;
|
||||||
|
|
||||||
|
}
|
10
pages/api/domains/[id].js
Normal file
10
pages/api/domains/[id].js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import {getDomains} from "./utils";
|
||||||
|
|
||||||
|
export default async function domainHandler({query : {id}}, res) {
|
||||||
|
const domains = await getDomains();
|
||||||
|
if (domains[id]) {
|
||||||
|
res.status(200).json(domains[id]);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: `Domain ${id} doesn't exist`});
|
||||||
|
}
|
||||||
|
}
|
10
pages/api/domains/index.js
Normal file
10
pages/api/domains/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import {getDomains} from "./utils";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
const domains = await getDomains();
|
||||||
|
if (domains) {
|
||||||
|
res.status(200).json(Object.keys(domains));
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: "An error has occurred"});
|
||||||
|
}
|
||||||
|
}
|
11
pages/api/domains/utils.js
Normal file
11
pages/api/domains/utils.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
const AsyncFunction = Object.getPrototypeOf(async function () {
|
||||||
|
}).constructor;
|
||||||
|
|
||||||
|
|
||||||
|
export async function getDomains() {
|
||||||
|
return await new AsyncFunction(
|
||||||
|
(await (await fetch(
|
||||||
|
"https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/domain.js",
|
||||||
|
)).text()).replace("export const domains =", "return"),
|
||||||
|
)();
|
||||||
|
}
|
12
pages/api/elements/[id].js
Normal file
12
pages/api/elements/[id].js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import {getElements} from "./utils.js";
|
||||||
|
|
||||||
|
|
||||||
|
export default async function elementsHandler({ query: { id } }, res) {
|
||||||
|
const element = await getElements();
|
||||||
|
console.log(element, id);
|
||||||
|
if (element[id]) {
|
||||||
|
res.status(200).json(element[id]);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: `Element ${id} not found` });
|
||||||
|
}
|
||||||
|
}
|
10
pages/api/elements/index.js
Normal file
10
pages/api/elements/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import {getElements} from "./utils.js";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
const elements = await getElements();
|
||||||
|
if (elements) {
|
||||||
|
res.status(200).json(Object.keys(elements));
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: 'An error occurred' });
|
||||||
|
}
|
||||||
|
}
|
25
pages/api/elements/utils.js
Normal file
25
pages/api/elements/utils.js
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
|
||||||
|
|
||||||
|
const elementColor = {
|
||||||
|
anemo: 0x7fffd4,
|
||||||
|
cryo: 0xd6fffa,
|
||||||
|
dendro: 0x7de91c,
|
||||||
|
electro: 0xbf00ff,
|
||||||
|
geo: 0xffbf00,
|
||||||
|
hydro: 0x0f5e9c,
|
||||||
|
pyro: 0xe35822
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getElements() {
|
||||||
|
let elements = await new AsyncFunction(
|
||||||
|
(await (await fetch(
|
||||||
|
"https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/elements.js",
|
||||||
|
)).text()).replace("export const elements =", "return"),
|
||||||
|
)();
|
||||||
|
|
||||||
|
Object.keys(elements).forEach(k => {
|
||||||
|
elements[k].color = elementColor[k];
|
||||||
|
})
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}
|
13
pages/api/events/current.js
Normal file
13
pages/api/events/current.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import {compareEndTimes, isCurrentEvent} from "../../../utils/time";
|
||||||
|
import {getEvents} from "./utils";
|
||||||
|
|
||||||
|
export default async function currentEvents(req, res){
|
||||||
|
const allEvents = await getEvents();
|
||||||
|
let currents = allEvents.flat().map(isCurrentEvent).filter(x=>x);
|
||||||
|
currents = currents.sort(compareEndTimes);
|
||||||
|
if (currents) {
|
||||||
|
res.status(200).json(currents);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: "There is no event currently going"});
|
||||||
|
}
|
||||||
|
}
|
10
pages/api/events/index.js
Normal file
10
pages/api/events/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import {getEvents} from "./utils";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
const events = await getEvents();
|
||||||
|
if (events) {
|
||||||
|
res.status(200).json(events);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: "An error has occured"});
|
||||||
|
}
|
||||||
|
}
|
13
pages/api/events/upcoming.js
Normal file
13
pages/api/events/upcoming.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import {getEvents} from "./utils";
|
||||||
|
import {compareStartTimes, isUpcomingEvent} from "../../../utils/time";
|
||||||
|
|
||||||
|
export default async function upcomingEvents(req, res){
|
||||||
|
const allEvents = await getEvents();
|
||||||
|
let upcoming = allEvents.flat().map(isUpcomingEvent).filter(x=>x);
|
||||||
|
upcoming = upcoming.sort(compareStartTimes);
|
||||||
|
if (upcoming){
|
||||||
|
res.status(200).json(upcoming);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: "There is no upcoming event"});
|
||||||
|
}
|
||||||
|
}
|
12
pages/api/events/utils.js
Normal file
12
pages/api/events/utils.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import {isCurrentEvent} from "../../../utils/time";
|
||||||
|
|
||||||
|
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor;
|
||||||
|
|
||||||
|
export async function getEvents(){
|
||||||
|
const allEvents = await new AsyncFunction(
|
||||||
|
(await (await fetch(
|
||||||
|
"https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/timeline.js",
|
||||||
|
)).text()).replace("export const eventsData = ", "return"),
|
||||||
|
)();
|
||||||
|
return allEvents;
|
||||||
|
}
|
5
pages/api/index.js
Normal file
5
pages/api/index.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
export default function handle(req, res) {
|
||||||
|
const dirs = fs.readdirSync('./pages/api').filter(x=>x != "index.js")
|
||||||
|
res.status(200).json(dirs)
|
||||||
|
}
|
21
pages/api/items/[id].js
Normal file
21
pages/api/items/[id].js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { getItems } from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
import {getArtifacts} from "../artifacts/utils";
|
||||||
|
|
||||||
|
export default async function itemsHandler({ query: { id } }, res) {
|
||||||
|
let item = JSON.parse(await getResultFromRedis(`item-${id}`))
|
||||||
|
if (!item) {
|
||||||
|
let items = JSON.parse(await getResultFromRedis("item-all"));
|
||||||
|
if (!items){
|
||||||
|
items = await getItems();
|
||||||
|
addResultToRedis("item-all", JSON.stringify(items)).catch(console.error);
|
||||||
|
}
|
||||||
|
item = items[id]
|
||||||
|
}
|
||||||
|
if (item) {
|
||||||
|
res.status(200).json(item);
|
||||||
|
addResultToRedis(`item-${id}`, JSON.stringify(item)).catch(console.error)
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: `Item ${id} not found` });
|
||||||
|
}
|
||||||
|
}
|
16
pages/api/items/index.js
Normal file
16
pages/api/items/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { getItems } from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
let items = JSON.parse(await getResultFromRedis('item-all'))
|
||||||
|
if (!items) {
|
||||||
|
items = await getItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items) {
|
||||||
|
res.status(200).json(Object.keys(items));
|
||||||
|
addResultToRedis('item-all', JSON.stringify(items)).catch(console.error)
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: 'An error occurred' });
|
||||||
|
}
|
||||||
|
}
|
23
pages/api/items/search/[id].js
Normal file
23
pages/api/items/search/[id].js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import {getItems} from "../utils";
|
||||||
|
import {getClosest} from "../../../../utils/levenshtein";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function itemHandler({query: {id}}, res) {
|
||||||
|
|
||||||
|
let items = JSON.parse(await getResultFromRedis('item-all'));
|
||||||
|
if (!items) {
|
||||||
|
items = await getItems();
|
||||||
|
addResultToRedis('item-all', JSON.stringify(items)).catch(console.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closestItems = []
|
||||||
|
getClosest(id, items).forEach(a => {
|
||||||
|
closestItems.push(items[a.name])
|
||||||
|
})
|
||||||
|
|
||||||
|
if (closestItems) {
|
||||||
|
res.status(200).json(closestItems);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: `Item ${id} not found`});
|
||||||
|
}
|
||||||
|
}
|
9
pages/api/items/utils.js
Normal file
9
pages/api/items/utils.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
|
||||||
|
|
||||||
|
export async function getItems() {
|
||||||
|
return await new AsyncFunction(
|
||||||
|
(await (await fetch(
|
||||||
|
"https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/itemList.js",
|
||||||
|
)).text()).replace("export const itemList =", "return"),
|
||||||
|
)();
|
||||||
|
}
|
21
pages/api/weapons/[id].js
Normal file
21
pages/api/weapons/[id].js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { getWeapons } from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function weaponsHandler({ query: { id } }, res) {
|
||||||
|
let weapon = JSON.parse(await getResultFromRedis(`weapon-${id}`));
|
||||||
|
if (!weapon) {
|
||||||
|
let weapons = JSON.parse(await getResultFromRedis("weapon-all"));
|
||||||
|
if (!weapons){
|
||||||
|
weapons = await getWeapons();
|
||||||
|
addResultToRedis("weapon-all", JSON.stringify(weapons)).catch(console.error);
|
||||||
|
}
|
||||||
|
weapon = weapons[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weapon) {
|
||||||
|
res.status(200).json(weapon);
|
||||||
|
addResultToRedis(`weapon-${id}`, JSON.stringify(weapon)).catch(console.error);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: `Item ${id} not found` });
|
||||||
|
}
|
||||||
|
}
|
16
pages/api/weapons/index.js
Normal file
16
pages/api/weapons/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { getWeapons } from "./utils";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
|
||||||
|
let weapons = JSON.parse(await getResultFromRedis("weapon-all"));
|
||||||
|
if (!weapons)
|
||||||
|
weapons = await getWeapons();
|
||||||
|
|
||||||
|
if (weapons) {
|
||||||
|
res.status(200).json(Object.keys(weapons));
|
||||||
|
addResultToRedis("weapon-all", JSON.stringify(weapons)).catch(console.error);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({ message: 'An error has occurred' });
|
||||||
|
}
|
||||||
|
}
|
23
pages/api/weapons/search/[id].js
Normal file
23
pages/api/weapons/search/[id].js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import {getWeapons} from "../utils";
|
||||||
|
import {getClosest} from "../../../../utils/levenshtein";
|
||||||
|
import {addResultToRedis, getResultFromRedis} from "../../../../utils/redis";
|
||||||
|
|
||||||
|
export default async function weaponsHandler({query: {id}}, res) {
|
||||||
|
|
||||||
|
let weapons = JSON.parse(await getResultFromRedis('weapon-all'));
|
||||||
|
if (!weapons) {
|
||||||
|
weapons = await getWeapons();
|
||||||
|
addResultToRedis('weapon-all', JSON.stringify(weapons)).catch(console.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closestWeapons = []
|
||||||
|
getClosest(id, weapons).forEach(w => {
|
||||||
|
closestWeapons.push(weapons[w.name])
|
||||||
|
})
|
||||||
|
|
||||||
|
if (closestWeapons) {
|
||||||
|
res.status(200).json(closestWeapons);
|
||||||
|
} else {
|
||||||
|
res.status(404).json({message: `Weapon ${id} not found`});
|
||||||
|
}
|
||||||
|
}
|
47
pages/api/weapons/utils.js
Normal file
47
pages/api/weapons/utils.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import { getItems } from "../items/utils";
|
||||||
|
|
||||||
|
const AsyncFunction = Object.getPrototypeOf(async function () { }).constructor;
|
||||||
|
|
||||||
|
export const weapons = {
|
||||||
|
sword: {
|
||||||
|
id: "sword",
|
||||||
|
name: "Sword",
|
||||||
|
},
|
||||||
|
bow: {
|
||||||
|
id: "bow",
|
||||||
|
name: "Bow",
|
||||||
|
},
|
||||||
|
polearm: {
|
||||||
|
id: "polearm",
|
||||||
|
name: "Polearm",
|
||||||
|
},
|
||||||
|
claymore: {
|
||||||
|
id: "claymore",
|
||||||
|
name: "Claymore",
|
||||||
|
},
|
||||||
|
catalyst: {
|
||||||
|
id: "catalyst",
|
||||||
|
name: "Catalyst",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export async function getWeapons() {
|
||||||
|
|
||||||
|
const data = JSON.parse(await (await fetch("https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/weapons/en.json")).text());
|
||||||
|
|
||||||
|
let func = (await (await fetch(
|
||||||
|
"https://raw.githubusercontent.com/MadeBaruna/paimon-moe/main/src/data/weaponList.js",
|
||||||
|
)).text());
|
||||||
|
func = func.slice(func.indexOf("export const weaponList ="));
|
||||||
|
|
||||||
|
let weaponList = await new AsyncFunction("weapons", "itemList",
|
||||||
|
func.replace("export const weaponList = ", "return"),
|
||||||
|
)(weapons, await getItems());
|
||||||
|
|
||||||
|
Object.values(weaponList).forEach(x => {
|
||||||
|
weaponList[x.id].extras = data[x.id];
|
||||||
|
})
|
||||||
|
|
||||||
|
return weaponList;
|
||||||
|
}
|
18
utils/levenshtein.js
Normal file
18
utils/levenshtein.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const levenshtein = require("fast-levenshtein");
|
||||||
|
|
||||||
|
export function getClosest(input, list, limit=5){
|
||||||
|
let t0 = performance.now();
|
||||||
|
const things = []
|
||||||
|
for (let s in list) {
|
||||||
|
let ns = s.replaceAll("_"," ");
|
||||||
|
if (ns.toLowerCase().includes(input.toLowerCase())){
|
||||||
|
things.push({name: s, dist: 0})
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
things.push({name: s, dist: levenshtein.get(input, ns)})
|
||||||
|
}
|
||||||
|
things.sort((a,b) => a.dist - b.dist);
|
||||||
|
let t1 = performance.now();
|
||||||
|
console.debug(`Levenshtein took ${t1-t0} ms`)
|
||||||
|
return things.splice(0,limit);
|
||||||
|
}
|
15
utils/redis.js
Normal file
15
utils/redis.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
const redis = require("redis");
|
||||||
|
const client = redis.createClient("redis://localhost:6379");
|
||||||
|
client.connect();
|
||||||
|
|
||||||
|
|
||||||
|
export async function getResultFromRedis(key){
|
||||||
|
if (await client.exists(key)) {
|
||||||
|
return await client.get(key)
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function addResultToRedis(key, value){
|
||||||
|
await client.set(key, value, {EX: 600});
|
||||||
|
}
|
52
utils/time.js
Normal file
52
utils/time.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
const dayjs = require('dayjs');
|
||||||
|
|
||||||
|
export const getTimeDifferenceAsia = () => {
|
||||||
|
const now = dayjs();
|
||||||
|
const local = now.utcOffset();
|
||||||
|
const serverTime = now.utcOffset(8);
|
||||||
|
return serverTime - local;
|
||||||
|
};
|
||||||
|
|
||||||
|
function convertToNow(event){
|
||||||
|
let start;
|
||||||
|
if (event["timezoneDependent"]) {
|
||||||
|
start = dayjs(event.start, 'YYYY-MM-DD HH:mm:ss').subtract(getTimeDifferenceAsia(), 'minute');
|
||||||
|
} else {
|
||||||
|
start = dayjs(event.start, 'YYYY-MM-DD HH:mm:ss').subtract(0, 'minute');
|
||||||
|
}
|
||||||
|
const end = dayjs(event.end, 'YYYY-MM-DD HH:mm:ss').subtract(0, 'minute');
|
||||||
|
|
||||||
|
return [start, end];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isCurrentEvent(event) {
|
||||||
|
const [start, end] = convertToNow(event);
|
||||||
|
|
||||||
|
const timeSinceStart = -start.diff(dayjs(), 'day', true);
|
||||||
|
const timeUntilEnd = end.diff(dayjs(), 'day', true);
|
||||||
|
|
||||||
|
if (timeSinceStart > 0 && timeUntilEnd > 0){
|
||||||
|
event["startTimestamp"] = start.unix();
|
||||||
|
event["endTimestamp"] = end.unix();
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isUpcomingEvent(event){
|
||||||
|
const [start, ] = convertToNow(event);
|
||||||
|
const timeUntilStart = start.diff(dayjs(), 'day', true);
|
||||||
|
|
||||||
|
if (timeUntilStart > 0){
|
||||||
|
event["startTimestamp"] = start.unix();
|
||||||
|
event["endTimestamp"] = 0;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compareStartTimes(a, b) {
|
||||||
|
return dayjs(a.start).diff(dayjs(b.start), 'day', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compareEndTimes(a, b) {
|
||||||
|
return dayjs(a.end).diff(dayjs(b.end), 'day', true);
|
||||||
|
}
|
Loading…
Reference in a new issue