Compare commits
2 Commits
82b0a0ee71
...
7f5587546c
Author | SHA1 | Date | |
---|---|---|---|
7f5587546c | |||
64f918c325 |
@ -32,3 +32,13 @@ spec:
|
|||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: ssr-backend-secret
|
name: ssr-backend-secret
|
||||||
key: MONGO_URI
|
key: MONGO_URI
|
||||||
|
- name: NUMBER_ONE_WEBHOOK
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: ssr-backend-secret
|
||||||
|
key: NUMBER_ONE_WEBHOOK
|
||||||
|
- name: TRACKED_PLAYERS_WEBHOOK
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: ssr-backend-secret
|
||||||
|
key: TRACKED_PLAYERS_WEBHOOK
|
@ -1,6 +0,0 @@
|
|||||||
export const Config = {
|
|
||||||
mongoUri: process.env.MONGO_URI,
|
|
||||||
apiUrl: process.env.API_URL || "https://ssr.fascinated.cc/api",
|
|
||||||
trackedPlayerWebhook: process.env.TRACKED_PLAYERS_WEBHOOK,
|
|
||||||
numberOneWebhook: process.env.NUMBER_ONE_WEBHOOK,
|
|
||||||
};
|
|
@ -10,7 +10,6 @@ import { etag } from "@bogeychan/elysia-etag";
|
|||||||
import AppController from "./controller/app.controller";
|
import AppController from "./controller/app.controller";
|
||||||
import * as dotenv from "@dotenvx/dotenvx";
|
import * as dotenv from "@dotenvx/dotenvx";
|
||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
import { Config } from "./common/config";
|
|
||||||
import { setLogLevel } from "@typegoose/typegoose";
|
import { setLogLevel } from "@typegoose/typegoose";
|
||||||
import PlayerController from "./controller/player.controller";
|
import PlayerController from "./controller/player.controller";
|
||||||
import { PlayerService } from "./service/player.service";
|
import { PlayerService } from "./service/player.service";
|
||||||
@ -22,6 +21,7 @@ import { connectScoreSaberWebSocket } from "@ssr/common/websocket/scoresaber-web
|
|||||||
import ImageController from "./controller/image.controller";
|
import ImageController from "./controller/image.controller";
|
||||||
import ReplayController from "./controller/replay.controller";
|
import ReplayController from "./controller/replay.controller";
|
||||||
import { ScoreService } from "./service/score.service";
|
import { ScoreService } from "./service/score.service";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
// Load .env file
|
// Load .env file
|
||||||
dotenv.config({
|
dotenv.config({
|
||||||
|
@ -8,9 +8,9 @@ import { GlobeIcon } from "../../components/globe-icon";
|
|||||||
import NodeCache from "node-cache";
|
import NodeCache from "node-cache";
|
||||||
import ScoreSaberLeaderboardToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-token";
|
import ScoreSaberLeaderboardToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-token";
|
||||||
import ScoreSaberPlayer, { getScoreSaberPlayerFromToken } from "@ssr/common/types/player/impl/scoresaber-player";
|
import ScoreSaberPlayer, { getScoreSaberPlayerFromToken } from "@ssr/common/types/player/impl/scoresaber-player";
|
||||||
import { Config } from "../common/config";
|
|
||||||
import { Jimp } from "jimp";
|
import { Jimp } from "jimp";
|
||||||
import { extractColors } from "extract-colors";
|
import { extractColors } from "extract-colors";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
const cache = new NodeCache({ stdTTL: 60 * 60, checkperiod: 120 });
|
const cache = new NodeCache({ stdTTL: 60 * 60, checkperiod: 120 });
|
||||||
const imageOptions = { width: 1200, height: 630 };
|
const imageOptions = { width: 1200, height: 630 };
|
||||||
|
@ -8,9 +8,9 @@ import ScoreSaberPlayerScoreToken from "@ssr/common/types/token/scoresaber/score
|
|||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { MessageBuilder, Webhook } from "discord-webhook-node";
|
import { MessageBuilder, Webhook } from "discord-webhook-node";
|
||||||
import { Config } from "../common/config";
|
|
||||||
import { formatPp } from "@ssr/common/utils/number-utils";
|
import { formatPp } from "@ssr/common/utils/number-utils";
|
||||||
import { isProduction } from "@ssr/common/utils/utils";
|
import { isProduction } from "@ssr/common/utils/utils";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
export class PlayerService {
|
export class PlayerService {
|
||||||
/**
|
/**
|
||||||
|
@ -2,9 +2,9 @@ import ScoreSaberPlayerScoreToken from "@ssr/common/types/token/scoresaber/score
|
|||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { MessageBuilder, Webhook } from "discord-webhook-node";
|
import { MessageBuilder, Webhook } from "discord-webhook-node";
|
||||||
import { Config } from "../common/config";
|
|
||||||
import { formatPp } from "@ssr/common/utils/number-utils";
|
import { formatPp } from "@ssr/common/utils/number-utils";
|
||||||
import { isProduction } from "@ssr/common/utils/utils";
|
import { isProduction } from "@ssr/common/utils/utils";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
export class ScoreService {
|
export class ScoreService {
|
||||||
/**
|
/**
|
||||||
|
14
projects/common/src/config.ts
Normal file
14
projects/common/src/config.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
export const Config = {
|
||||||
|
/**
|
||||||
|
* All projects
|
||||||
|
*/
|
||||||
|
websiteUrl: process.env.NEXT_PUBLIC_SITE_URL || "https://ssr.fascinated.cc",
|
||||||
|
apiUrl: process.env.NEXT_PUBLIC_SITE_API || "https://ssr.fascinated.cc/api",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backend
|
||||||
|
*/
|
||||||
|
trackedPlayerWebhook: process.env.TRACKED_PLAYERS_WEBHOOK,
|
||||||
|
numberOneWebhook: process.env.NUMBER_ONE_WEBHOOK,
|
||||||
|
mongoUri: process.env.MONGO_URI,
|
||||||
|
} as const;
|
@ -4,6 +4,7 @@ import { PlayerHistory } from "../player-history";
|
|||||||
import ScoreSaberPlayerToken from "../../token/scoresaber/score-saber-player-token";
|
import ScoreSaberPlayerToken from "../../token/scoresaber/score-saber-player-token";
|
||||||
import { formatDateMinimal, getDaysAgoDate, getMidnightAlignedDate } from "../../../utils/time-utils";
|
import { formatDateMinimal, getDaysAgoDate, getMidnightAlignedDate } from "../../../utils/time-utils";
|
||||||
import { getPageFromRank } from "../../../utils/utils";
|
import { getPageFromRank } from "../../../utils/utils";
|
||||||
|
import { Config } from "../../../config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ScoreSaber player.
|
* A ScoreSaber player.
|
||||||
@ -75,12 +76,10 @@ export default interface ScoreSaberPlayer extends Player {
|
|||||||
* Gets the ScoreSaber Player from an {@link ScoreSaberPlayerToken}.
|
* Gets the ScoreSaber Player from an {@link ScoreSaberPlayerToken}.
|
||||||
*
|
*
|
||||||
* @param token the player token
|
* @param token the player token
|
||||||
* @param apiUrl the api url for SSR
|
|
||||||
* @param playerIdCookie the id of the claimed player
|
* @param playerIdCookie the id of the claimed player
|
||||||
*/
|
*/
|
||||||
export async function getScoreSaberPlayerFromToken(
|
export async function getScoreSaberPlayerFromToken(
|
||||||
token: ScoreSaberPlayerToken,
|
token: ScoreSaberPlayerToken,
|
||||||
apiUrl: string,
|
|
||||||
playerIdCookie?: string
|
playerIdCookie?: string
|
||||||
): Promise<ScoreSaberPlayer> {
|
): Promise<ScoreSaberPlayer> {
|
||||||
const bio: ScoreSaberBio = {
|
const bio: ScoreSaberBio = {
|
||||||
@ -105,7 +104,7 @@ export async function getScoreSaberPlayerFromToken(
|
|||||||
.get<{
|
.get<{
|
||||||
statistics: { [key: string]: PlayerHistory };
|
statistics: { [key: string]: PlayerHistory };
|
||||||
}>(
|
}>(
|
||||||
`${apiUrl}/player/history/${token.id}${playerIdCookie && playerIdCookie == token.id ? "?createIfMissing=true" : ""}`
|
`${Config.apiUrl}/player/history/${token.id}${playerIdCookie && playerIdCookie == token.id ? "?createIfMissing=true" : ""}`
|
||||||
)
|
)
|
||||||
.json();
|
.json();
|
||||||
if (history) {
|
if (history) {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { PlayerHistory } from "../types/player/player-history";
|
import { PlayerHistory } from "../types/player/player-history";
|
||||||
|
import { kyFetch } from "./utils";
|
||||||
|
import { Config } from "../config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts the player history based on date,
|
* Sorts the player history based on date,
|
||||||
@ -11,3 +13,12 @@ export function sortPlayerHistory(history: Map<string, PlayerHistory>) {
|
|||||||
(a, b) => Date.parse(b[0]) - Date.parse(a[0]) // Sort in descending order
|
(a, b) => Date.parse(b[0]) - Date.parse(a[0]) // Sort in descending order
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the player is being tracked.
|
||||||
|
*
|
||||||
|
* @param id the player id
|
||||||
|
*/
|
||||||
|
export async function trackPlayer(id: string) {
|
||||||
|
await kyFetch(`${Config.apiUrl}/player/history/${id}?createIfMissing=true`);
|
||||||
|
}
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export const config = {
|
|
||||||
siteUrl: process.env.NEXT_PUBLIC_SITE_URL || "https://ssr.fascinated.cc",
|
|
||||||
siteApi: process.env.NEXT_PUBLIC_SITE_API || "https://ssr.fascinated.cc/api",
|
|
||||||
};
|
|
@ -7,7 +7,7 @@ import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
|||||||
import ScoreSaberLeaderboardScoresPageToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-scores-page-token";
|
import ScoreSaberLeaderboardScoresPageToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-scores-page-token";
|
||||||
import NodeCache from "node-cache";
|
import NodeCache from "node-cache";
|
||||||
import ScoreSaberLeaderboardToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-token";
|
import ScoreSaberLeaderboardToken from "@ssr/common/types/token/scoresaber/score-saber-leaderboard-token";
|
||||||
import { config } from "../../../../../config";
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
const UNKNOWN_LEADERBOARD = {
|
const UNKNOWN_LEADERBOARD = {
|
||||||
title: "ScoreSaber Reloaded - Unknown Leaderboard",
|
title: "ScoreSaber Reloaded - Unknown Leaderboard",
|
||||||
@ -84,7 +84,7 @@ export async function generateMetadata(props: Props): Promise<Metadata> {
|
|||||||
description: `View the scores for ${leaderboard.songName} by ${leaderboard.songAuthorName}!`,
|
description: `View the scores for ${leaderboard.songName} by ${leaderboard.songAuthorName}!`,
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: `${config.siteApi}/image/leaderboard/${leaderboard.id}`,
|
url: `${Config.apiUrl}/image/leaderboard/${leaderboard.id}`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { config } from "../../../config";
|
|
||||||
import { AppStatistics } from "@ssr/common/types/backend/app-statistics";
|
import { AppStatistics } from "@ssr/common/types/backend/app-statistics";
|
||||||
import Statistic from "@/components/home/statistic";
|
import Statistic from "@/components/home/statistic";
|
||||||
import { kyFetch } from "@ssr/common/utils/utils";
|
import { kyFetch } from "@ssr/common/utils/utils";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
export const dynamic = "force-dynamic"; // Always generate the page on load
|
export const dynamic = "force-dynamic"; // Always generate the page on load
|
||||||
|
|
||||||
export default async function HomePage() {
|
export default async function HomePage() {
|
||||||
const statistics = await kyFetch<AppStatistics>(config.siteApi + "/statistics");
|
const statistics = await kyFetch<AppStatistics>(Config.apiUrl + "/statistics");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="flex flex-col items-center w-full gap-6 text-center">
|
<main className="flex flex-col items-center w-full gap-6 text-center">
|
||||||
|
@ -7,9 +7,9 @@ import { ScoreSort } from "@ssr/common/types/score/score-sort";
|
|||||||
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
||||||
import ScoreSaberPlayerScoresPageToken from "@ssr/common/types/token/scoresaber/score-saber-player-scores-page-token";
|
import ScoreSaberPlayerScoresPageToken from "@ssr/common/types/token/scoresaber/score-saber-player-scores-page-token";
|
||||||
import ScoreSaberPlayer, { getScoreSaberPlayerFromToken } from "@ssr/common/types/player/impl/scoresaber-player";
|
import ScoreSaberPlayer, { getScoreSaberPlayerFromToken } from "@ssr/common/types/player/impl/scoresaber-player";
|
||||||
import { config } from "../../../../../config";
|
|
||||||
import NodeCache from "node-cache";
|
import NodeCache from "node-cache";
|
||||||
import { getCookieValue } from "@ssr/common/utils/cookie-utils";
|
import { getCookieValue } from "@ssr/common/utils/cookie-utils";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
const UNKNOWN_PLAYER = {
|
const UNKNOWN_PLAYER = {
|
||||||
title: "ScoreSaber Reloaded - Unknown Player",
|
title: "ScoreSaber Reloaded - Unknown Player",
|
||||||
@ -55,8 +55,7 @@ const getPlayerData = async ({ params }: Props, fetchScores: boolean = true): Pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
const playerToken = await scoresaberService.lookupPlayer(id);
|
const playerToken = await scoresaberService.lookupPlayer(id);
|
||||||
const player =
|
const player = playerToken && (await getScoreSaberPlayerFromToken(playerToken, await getCookieValue("playerId")));
|
||||||
playerToken && (await getScoreSaberPlayerFromToken(playerToken, config.siteApi, await getCookieValue("playerId")));
|
|
||||||
let scores: ScoreSaberPlayerScoresPageToken | undefined;
|
let scores: ScoreSaberPlayerScoresPageToken | undefined;
|
||||||
if (fetchScores) {
|
if (fetchScores) {
|
||||||
scores = await scoresaberService.lookupPlayerScores({
|
scores = await scoresaberService.lookupPlayerScores({
|
||||||
@ -98,7 +97,7 @@ export async function generateMetadata(props: Props): Promise<Metadata> {
|
|||||||
description: `Click here to view the scores for ${player.name}!`,
|
description: `Click here to view the scores for ${player.name}!`,
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: `${config.siteApi}/image/player/${player.id}`,
|
url: `${Config.apiUrl}/image/player/${player.id}`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,7 @@ import { Friend } from "@/common/database/types/friends";
|
|||||||
import ScoreSaberPlayerToken from "@ssr/common/types/token/scoresaber/score-saber-player-token";
|
import ScoreSaberPlayerToken from "@ssr/common/types/token/scoresaber/score-saber-player-token";
|
||||||
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
||||||
import { setCookieValue } from "@ssr/common/utils/cookie-utils";
|
import { setCookieValue } from "@ssr/common/utils/cookie-utils";
|
||||||
|
import { trackPlayer } from "@ssr/common/utils/player-utils";
|
||||||
|
|
||||||
const SETTINGS_ID = "SSR"; // DO NOT CHANGE
|
const SETTINGS_ID = "SSR"; // DO NOT CHANGE
|
||||||
|
|
||||||
@ -114,7 +115,12 @@ export default class Database extends Dexie {
|
|||||||
const friends = await this.friends.toArray();
|
const friends = await this.friends.toArray();
|
||||||
const players = await Promise.all(
|
const players = await Promise.all(
|
||||||
friends.map(async ({ id }) => {
|
friends.map(async ({ id }) => {
|
||||||
return await scoresaberService.lookupPlayer(id, true);
|
const token = await scoresaberService.lookupPlayer(id, true);
|
||||||
|
if (token == undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
await trackPlayer(id); // Track the player
|
||||||
|
return token;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return players.filter(player => player !== undefined) as ScoreSaberPlayerToken[];
|
return players.filter(player => player !== undefined) as ScoreSaberPlayerToken[];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { config } from "../../config";
|
|
||||||
import ky from "ky";
|
import ky from "ky";
|
||||||
import { Colors } from "@/common/colors";
|
import { Colors } from "@/common/colors";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxies all non-localhost images to make them load faster.
|
* Proxies all non-localhost images to make them load faster.
|
||||||
@ -9,7 +9,7 @@ import { Colors } from "@/common/colors";
|
|||||||
* @returns the new image url
|
* @returns the new image url
|
||||||
*/
|
*/
|
||||||
export function getImageUrl(originalUrl: string) {
|
export function getImageUrl(originalUrl: string) {
|
||||||
return `${!config.siteUrl.includes("localhost") ? "https://img.fascinated.cc/upload/q_70/" : ""}${originalUrl}`;
|
return `${!Config.websiteUrl.includes("localhost") ? "https://img.fascinated.cc/upload/q_70/" : ""}${originalUrl}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -20,7 +20,7 @@ export function getImageUrl(originalUrl: string) {
|
|||||||
*/
|
*/
|
||||||
export const getAverageColor = async (src: string) => {
|
export const getAverageColor = async (src: string) => {
|
||||||
try {
|
try {
|
||||||
return await ky.get<{ color: string }>(`${config.siteApi}/image/averagecolor/${encodeURIComponent(src)}`).json();
|
return await ky.get<{ color: string }>(`${Config.apiUrl}/image/averagecolor/${encodeURIComponent(src)}`).json();
|
||||||
} catch {
|
} catch {
|
||||||
return {
|
return {
|
||||||
color: Colors.primary,
|
color: Colors.primary,
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { getApiHealth } from "@ssr/common/utils/api-utils";
|
import { getApiHealth } from "@ssr/common/utils/api-utils";
|
||||||
import { config } from "../../../config";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { useIsFirstRender } from "@uidotdev/usehooks";
|
import { useIsFirstRender } from "@uidotdev/usehooks";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
export function ApiHealth() {
|
export function ApiHealth() {
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@ -16,7 +16,7 @@ export function ApiHealth() {
|
|||||||
useQuery({
|
useQuery({
|
||||||
queryKey: ["api-health"],
|
queryKey: ["api-health"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const status = (await getApiHealth(config.siteApi + "/health")).online;
|
const status = (await getApiHealth(Config.apiUrl + "/health")).online;
|
||||||
setOnline(status);
|
setOnline(status);
|
||||||
return status;
|
return status;
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useLiveQuery } from "dexie-react-hooks";
|
import { useLiveQuery } from "dexie-react-hooks";
|
||||||
import { config } from "../../config";
|
|
||||||
import { getImageUrl } from "@/common/image-utils";
|
import { getImageUrl } from "@/common/image-utils";
|
||||||
import useDatabase from "../hooks/use-database";
|
import useDatabase from "../hooks/use-database";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
export default function BackgroundCover() {
|
export default function BackgroundCover() {
|
||||||
const database = useDatabase();
|
const database = useDatabase();
|
||||||
@ -22,7 +22,7 @@ export default function BackgroundCover() {
|
|||||||
backgroundCover = backgroundCover.substring(1);
|
backgroundCover = backgroundCover.substring(1);
|
||||||
}
|
}
|
||||||
if (prependWebsiteUrl) {
|
if (prependWebsiteUrl) {
|
||||||
backgroundCover = config.siteUrl + "/" + backgroundCover;
|
backgroundCover = Config.websiteUrl + "/" + backgroundCover;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static background color
|
// Static background color
|
||||||
|
@ -7,6 +7,7 @@ import Tooltip from "../tooltip";
|
|||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import { PersonIcon } from "@radix-ui/react-icons";
|
import { PersonIcon } from "@radix-ui/react-icons";
|
||||||
import ScoreSaberPlayer from "@ssr/common/types/player/impl/scoresaber-player";
|
import ScoreSaberPlayer from "@ssr/common/types/player/impl/scoresaber-player";
|
||||||
|
import { trackPlayer } from "@ssr/common/utils/player-utils";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
/**
|
/**
|
||||||
@ -27,6 +28,7 @@ export default function AddFriend({ player }: Props) {
|
|||||||
* Adds this player as a friend
|
* Adds this player as a friend
|
||||||
*/
|
*/
|
||||||
async function addFriend() {
|
async function addFriend() {
|
||||||
|
await trackPlayer(id);
|
||||||
await database.addFriend(id);
|
await database.addFriend(id);
|
||||||
toast({
|
toast({
|
||||||
title: "Friend Added",
|
title: "Friend Added",
|
||||||
|
@ -14,7 +14,6 @@ import ScoreSaberPlayer, { getScoreSaberPlayerFromToken } from "@ssr/common/type
|
|||||||
import ScoreSaberPlayerScoresPageToken from "@ssr/common/types/token/scoresaber/score-saber-player-scores-page-token";
|
import ScoreSaberPlayerScoresPageToken from "@ssr/common/types/token/scoresaber/score-saber-player-scores-page-token";
|
||||||
import { ScoreSort } from "@ssr/common/types/score/score-sort";
|
import { ScoreSort } from "@ssr/common/types/score/score-sort";
|
||||||
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
|
||||||
import { config } from "../../../config";
|
|
||||||
import useDatabase from "@/hooks/use-database";
|
import useDatabase from "@/hooks/use-database";
|
||||||
import { useLiveQuery } from "dexie-react-hooks";
|
import { useLiveQuery } from "dexie-react-hooks";
|
||||||
|
|
||||||
@ -40,16 +39,17 @@ export default function PlayerData({
|
|||||||
const isMiniRankingsVisible = useIsVisible(miniRankingsRef);
|
const isMiniRankingsVisible = useIsVisible(miniRankingsRef);
|
||||||
const database = useDatabase();
|
const database = useDatabase();
|
||||||
const settings = useLiveQuery(() => database.getSettings());
|
const settings = useLiveQuery(() => database.getSettings());
|
||||||
|
const isFriend = useLiveQuery(() => database.isFriend(initialPlayerData.id));
|
||||||
|
|
||||||
let player = initialPlayerData;
|
let player = initialPlayerData;
|
||||||
const { data, isLoading, isError } = useQuery({
|
const { data, isLoading, isError } = useQuery({
|
||||||
queryKey: ["playerData", player.id, settings?.playerId],
|
queryKey: ["playerData", player.id, settings?.playerId, isFriend],
|
||||||
queryFn: async (): Promise<ScoreSaberPlayer | undefined> => {
|
queryFn: async (): Promise<ScoreSaberPlayer | undefined> => {
|
||||||
const playerResponse = await scoresaberService.lookupPlayer(player.id);
|
const playerResponse = await scoresaberService.lookupPlayer(player.id);
|
||||||
if (playerResponse == undefined) {
|
if (playerResponse == undefined) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return await getScoreSaberPlayerFromToken(playerResponse, config.siteApi, settings?.playerId);
|
return await getScoreSaberPlayerFromToken(playerResponse, settings?.playerId);
|
||||||
},
|
},
|
||||||
refetchInterval: REFRESH_INTERVAL,
|
refetchInterval: REFRESH_INTERVAL,
|
||||||
refetchIntervalInBackground: false,
|
refetchIntervalInBackground: false,
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import ky from "ky";
|
import ky from "ky";
|
||||||
import { config } from "../../../config";
|
|
||||||
import Tooltip from "@/components/tooltip";
|
import Tooltip from "@/components/tooltip";
|
||||||
import { InformationCircleIcon } from "@heroicons/react/16/solid";
|
import { InformationCircleIcon } from "@heroicons/react/16/solid";
|
||||||
import { formatNumberWithCommas } from "@ssr/common/utils/number-utils";
|
import { formatNumberWithCommas } from "@ssr/common/utils/number-utils";
|
||||||
import { PlayerTrackedSince } from "@ssr/common/types/player/player-tracked-since";
|
import { PlayerTrackedSince } from "@ssr/common/types/player/player-tracked-since";
|
||||||
import ScoreSaberPlayer from "@ssr/common/types/player/impl/scoresaber-player";
|
import ScoreSaberPlayer from "@ssr/common/types/player/impl/scoresaber-player";
|
||||||
|
import { Config } from "@ssr/common/config";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
player: ScoreSaberPlayer;
|
player: ScoreSaberPlayer;
|
||||||
@ -16,7 +16,7 @@ type Props = {
|
|||||||
export default function PlayerTrackedStatus({ player }: Props) {
|
export default function PlayerTrackedStatus({ player }: Props) {
|
||||||
const { data, isLoading, isError } = useQuery({
|
const { data, isLoading, isError } = useQuery({
|
||||||
queryKey: ["playerIsBeingTracked", player.id],
|
queryKey: ["playerIsBeingTracked", player.id],
|
||||||
queryFn: () => ky.get<PlayerTrackedSince>(`${config.siteApi}/player/tracked/${player.id}`).json(),
|
queryFn: () => ky.get<PlayerTrackedSince>(`${Config.apiUrl}/player/tracked/${player.id}`).json(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isLoading || isError || !data?.tracked) {
|
if (isLoading || isError || !data?.tracked) {
|
||||||
|
Reference in New Issue
Block a user