chore: fmt [no ci]
This commit is contained in:
+20
-20
@@ -6,23 +6,23 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
rules:
|
rules:
|
||||||
- host: api.dgnr.us
|
- host: api.dgnr.us
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- backend:
|
- backend:
|
||||||
service:
|
service:
|
||||||
name: enka-api
|
name: enka-api
|
||||||
port:
|
port:
|
||||||
number: 80
|
number: 80
|
||||||
path: /
|
path: /
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
- host: api.astrxl.dev
|
- host: api.astrxl.dev
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- backend:
|
- backend:
|
||||||
service:
|
service:
|
||||||
name: enka-api
|
name: enka-api
|
||||||
port:
|
port:
|
||||||
number: 80
|
number: 80
|
||||||
path: /
|
path: /
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ kind: Kustomization
|
|||||||
namespace: enka
|
namespace: enka
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
- namespace.yaml
|
- namespace.yaml
|
||||||
- deployment.yaml
|
- deployment.yaml
|
||||||
- service.yaml
|
- service.yaml
|
||||||
- ingress.yaml
|
- ingress.yaml
|
||||||
- secret.yaml
|
- secret.yaml
|
||||||
- service-account.yaml
|
- service-account.yaml
|
||||||
- role.yaml
|
- role.yaml
|
||||||
- role-binding.yaml
|
- role-binding.yaml
|
||||||
- token-secret.yaml
|
- token-secret.yaml
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ roleRef:
|
|||||||
kind: Role
|
kind: Role
|
||||||
name: ci-deployer
|
name: ci-deployer
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: ci-deployer
|
name: ci-deployer
|
||||||
namespace: enka
|
namespace: enka
|
||||||
|
|||||||
+15
-15
@@ -4,18 +4,18 @@ metadata:
|
|||||||
name: ci-deployer
|
name: ci-deployer
|
||||||
namespace: enka
|
namespace: enka
|
||||||
rules:
|
rules:
|
||||||
- apiGroups: ["apps"]
|
- apiGroups: ["apps"]
|
||||||
resources: ["deployments"]
|
resources: ["deployments"]
|
||||||
verbs: ["get", "list", "watch", "update", "patch"]
|
verbs: ["get", "list", "watch", "update", "patch"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["pods"]
|
resources: ["pods"]
|
||||||
verbs: ["get", "list", "watch"]
|
verbs: ["get", "list", "watch"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["services"]
|
resources: ["services"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
||||||
- apiGroups: ["networking.k8s.io"]
|
- apiGroups: ["networking.k8s.io"]
|
||||||
resources: ["ingresses"]
|
resources: ["ingresses"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
verbs: ["get", "list", "watch", "create", "update", "patch"]
|
||||||
- apiGroups: ["batch"]
|
- apiGroups: ["batch"]
|
||||||
resources: ["jobs"]
|
resources: ["jobs"]
|
||||||
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
|
||||||
|
|||||||
+3
-3
@@ -6,8 +6,8 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
port: 80
|
port: 80
|
||||||
targetPort: 3000
|
targetPort: 3000
|
||||||
selector:
|
selector:
|
||||||
app: enka-api
|
app: enka-api
|
||||||
|
|||||||
+76
-70
@@ -484,82 +484,88 @@ export function card(app: App) {
|
|||||||
afterResponse: ({ log }) => log`Rendering completed`,
|
afterResponse: ({ log }) => log`Rendering completed`,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.get("/enka/:username", async ({ params: { username }, query: { lang } }) => {
|
.get(
|
||||||
const errorLoc = cardErrorLocs[lang === "th" ? "th" : "en"];
|
"/enka/:username",
|
||||||
try {
|
async ({ params: { username }, query: { lang } }) => {
|
||||||
const cacheKey = `enka-redir::${username}`;
|
const errorLoc = cardErrorLocs[lang === "th" ? "th" : "en"];
|
||||||
if (feature("API")) {
|
try {
|
||||||
const cached = cache.get<Response>(cacheKey);
|
const cacheKey = `enka-redir::${username}`;
|
||||||
if (cached) return cached.clone();
|
if (feature("API")) {
|
||||||
}
|
const cached = cache.get<Response>(cacheKey);
|
||||||
|
if (cached) return cached.clone();
|
||||||
|
}
|
||||||
|
|
||||||
const [hoyo] = await fetch(
|
const [hoyo] = await fetch(
|
||||||
`https://enka.network/api/profile/${username}/hoyos/`,
|
`https://enka.network/api/profile/${username}/hoyos/`,
|
||||||
)
|
|
||||||
.then(throwNotOk)
|
|
||||||
.then(
|
|
||||||
(r) =>
|
|
||||||
r.json() as Promise<
|
|
||||||
Record<string, { hoyo_type: number; order: NumberLike }>
|
|
||||||
>,
|
|
||||||
)
|
)
|
||||||
.then((e) =>
|
.then(throwNotOk)
|
||||||
Object.entries(e)
|
.then(
|
||||||
.map(([k, v]) => ({ hash: k, ...v }))
|
(r) =>
|
||||||
.sort((a, b) => Number(a.order) - Number(b.order))
|
r.json() as Promise<
|
||||||
.filter((e) => e.hoyo_type === 0),
|
Record<string, { hoyo_type: number; order: NumberLike }>
|
||||||
|
>,
|
||||||
|
)
|
||||||
|
.then((e) =>
|
||||||
|
Object.entries(e)
|
||||||
|
.map(([k, v]) => ({ hash: k, ...v }))
|
||||||
|
.sort((a, b) => Number(a.order) - Number(b.order))
|
||||||
|
.filter((e) => e.hoyo_type === 0),
|
||||||
|
);
|
||||||
|
if (!hoyo) return status(404, errorLoc.profileNotFound);
|
||||||
|
const buildsArr = fetch(
|
||||||
|
`https://enka.network/api/profile/${username}/hoyos/${hoyo.hash}/builds/`,
|
||||||
|
)
|
||||||
|
.then(throwNotOk)
|
||||||
|
.then(
|
||||||
|
(r) =>
|
||||||
|
r.json() as Promise<
|
||||||
|
Record<string, { id: number; order: NumberLike }[]>
|
||||||
|
>,
|
||||||
|
);
|
||||||
|
const builds = await buildsArr.then((e) =>
|
||||||
|
((
|
||||||
|
pair:
|
||||||
|
| [string, { id: number; order: `${number}` }[]]
|
||||||
|
| undefined,
|
||||||
|
) =>
|
||||||
|
pair
|
||||||
|
? {
|
||||||
|
char: pair[0],
|
||||||
|
...pair[1]
|
||||||
|
.sort((a, b) => Number(a.order) - Number(b.order))
|
||||||
|
.shift(),
|
||||||
|
}
|
||||||
|
: undefined)(Object.entries(e).shift()),
|
||||||
);
|
);
|
||||||
if (!hoyo) return status(404, errorLoc.profileNotFound);
|
if (!builds?.id) return status(404, errorLoc.buildNotFound);
|
||||||
const buildsArr = fetch(
|
|
||||||
`https://enka.network/api/profile/${username}/hoyos/${hoyo.hash}/builds/`,
|
|
||||||
)
|
|
||||||
.then(throwNotOk)
|
|
||||||
.then(
|
|
||||||
(r) =>
|
|
||||||
r.json() as Promise<
|
|
||||||
Record<string, { id: number; order: NumberLike }[]>
|
|
||||||
>,
|
|
||||||
);
|
|
||||||
const builds = await buildsArr.then((e) =>
|
|
||||||
((
|
|
||||||
pair: [string, { id: number; order: `${number}` }[]] | undefined,
|
|
||||||
) =>
|
|
||||||
pair
|
|
||||||
? {
|
|
||||||
char: pair[0],
|
|
||||||
...pair[1]
|
|
||||||
.sort((a, b) => Number(a.order) - Number(b.order))
|
|
||||||
.shift(),
|
|
||||||
}
|
|
||||||
: undefined)(Object.entries(e).shift()),
|
|
||||||
);
|
|
||||||
if (!builds?.id) return status(404, errorLoc.buildNotFound);
|
|
||||||
|
|
||||||
const res = redirect(
|
const res = redirect(
|
||||||
`/v1/card/enka/${username}/${hoyo.hash}/${builds.char}/${builds.id}`,
|
`/v1/card/enka/${username}/${hoyo.hash}/${builds.char}/${builds.id}`,
|
||||||
);
|
|
||||||
queueMicrotask(async () => {
|
|
||||||
cache.set(cacheKey, res, 1000 * 60); // cache for 1 minute
|
|
||||||
cache.set(
|
|
||||||
`enka-redir::${username}::${hoyo.hash}`,
|
|
||||||
await buildsArr,
|
|
||||||
1000 * 120,
|
|
||||||
);
|
);
|
||||||
});
|
queueMicrotask(async () => {
|
||||||
|
cache.set(cacheKey, res, 1000 * 60); // cache for 1 minute
|
||||||
|
cache.set(
|
||||||
|
`enka-redir::${username}::${hoyo.hash}`,
|
||||||
|
await buildsArr,
|
||||||
|
1000 * 120,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return res.clone();
|
return res.clone();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof ResponseNotOkError && err.status === 404)
|
if (err instanceof ResponseNotOkError && err.status === 404)
|
||||||
return status(404, errorLoc.profileNotFound);
|
return status(404, errorLoc.profileNotFound);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
query: t.Partial(
|
{
|
||||||
t.Object({
|
query: t.Partial(
|
||||||
lang: Locale,
|
t.Object({
|
||||||
}),
|
lang: Locale,
|
||||||
),
|
}),
|
||||||
})
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
.get(
|
.get(
|
||||||
"/enka/:username/:hash/:char/:build",
|
"/enka/:username/:hash/:char/:build",
|
||||||
async ({
|
async ({
|
||||||
|
|||||||
@@ -243,8 +243,7 @@ export async function ListPage(
|
|||||||
cons:
|
cons:
|
||||||
avatarInfoList?.find(
|
avatarInfoList?.find(
|
||||||
(e) => e.avatar.avatarId === a.avatar.avatarId,
|
(e) => e.avatar.avatarId === a.avatar.avatarId,
|
||||||
)!.talentIdList?.length ??
|
)!.talentIdList?.length ?? a.talentLevel,
|
||||||
a.talentLevel,
|
|
||||||
}))
|
}))
|
||||||
.map(({ a, c, cons }) => (
|
.map(({ a, c, cons }) => (
|
||||||
<div tw="relative flex flex-col rounded-[.3em] overflow-hidden shadow-[0_.08em_.35em_rgba(0,0,0,.18)]">
|
<div tw="relative flex flex-col rounded-[.3em] overflow-hidden shadow-[0_.08em_.35em_rgba(0,0,0,.18)]">
|
||||||
|
|||||||
+20
-5
@@ -33,19 +33,31 @@ export function webhookMerger(app: App) {
|
|||||||
|
|
||||||
const oldData = existing.data;
|
const oldData = existing.data;
|
||||||
const flushed = new Set<string>();
|
const flushed = new Set<string>();
|
||||||
existing.data = merge(oldData, body, undefined, MAX_FIELD_LENGTH, flushed);
|
existing.data = merge(
|
||||||
|
oldData,
|
||||||
|
body,
|
||||||
|
undefined,
|
||||||
|
MAX_FIELD_LENGTH,
|
||||||
|
flushed,
|
||||||
|
);
|
||||||
existing.count++;
|
existing.count++;
|
||||||
|
|
||||||
if (flushed.size > 0) {
|
if (flushed.size > 0) {
|
||||||
existing.count = 1;
|
existing.count = 1;
|
||||||
forward(id, url, oldData);
|
forward(id, url, oldData);
|
||||||
existing.timer = setTimeout(() => forward(id, url, existing.data), bufferTime);
|
existing.timer = setTimeout(
|
||||||
|
() => forward(id, url, existing.data),
|
||||||
|
bufferTime,
|
||||||
|
);
|
||||||
return status(202);
|
return status(202);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug`collected ${existing}`;
|
log.debug`collected ${existing}`;
|
||||||
|
|
||||||
existing.timer = setTimeout(() => forward(id, url, existing.data), bufferTime);
|
existing.timer = setTimeout(
|
||||||
|
() => forward(id, url, existing.data),
|
||||||
|
bufferTime,
|
||||||
|
);
|
||||||
|
|
||||||
return status(202);
|
return status(202);
|
||||||
}
|
}
|
||||||
@@ -77,11 +89,14 @@ async function getRoutes(): Promise<RouteMap> {
|
|||||||
function parseRouteMap(raw: string): RouteMap {
|
function parseRouteMap(raw: string): RouteMap {
|
||||||
const parsed = JSON.parse(raw) as unknown;
|
const parsed = JSON.parse(raw) as unknown;
|
||||||
|
|
||||||
if (!Array.isArray(parsed)) throw new Error("WH_ROUTE_MAP must be a JSON array");
|
if (!Array.isArray(parsed))
|
||||||
|
throw new Error("WH_ROUTE_MAP must be a JSON array");
|
||||||
|
|
||||||
for (const [index, route] of parsed.entries()) {
|
for (const [index, route] of parsed.entries()) {
|
||||||
if (!Array.isArray(route) || route.length !== 3) {
|
if (!Array.isArray(route) || route.length !== 3) {
|
||||||
throw new Error(`WH_ROUTE_MAP route ${index} must be [id, url, bufferTime]`);
|
throw new Error(
|
||||||
|
`WH_ROUTE_MAP route ${index} must be [id, url, bufferTime]`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [id, url, bufferTime] = route;
|
const [id, url, bufferTime] = route;
|
||||||
|
|||||||
Reference in New Issue
Block a user