updated Nav-Search + removed string-sanitizer + added csgo-sharecode
Some checks failed
CSGOWTF/csgowtf/pipeline/head There was a failure building this commit
Some checks failed
CSGOWTF/csgowtf/pipeline/head There was a failure building this commit
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
"axios": "^0.26.1",
|
||||
"bootstrap": "^5.1.3",
|
||||
"bootstrap-icons": "^1.8.1",
|
||||
"csgo-sharecode": "^3.0.1",
|
||||
"echarts": "^5.3.1",
|
||||
"fork-awesome": "^1.2.0",
|
||||
"http-status-codes": "^2.2.0",
|
||||
@@ -21,7 +22,6 @@
|
||||
"jquery": "^3.6.0",
|
||||
"luxon": "^2.3.1",
|
||||
"pinia": "^2.0.12",
|
||||
"string-sanitizer": "^2.0.2",
|
||||
"vue": "^3.2.31",
|
||||
"vue-matomo": "^4.1.0",
|
||||
"vue-router": "^4.0.14",
|
||||
|
@@ -32,7 +32,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
<form
|
||||
id="searchform"
|
||||
id="search-form"
|
||||
class="d-flex"
|
||||
@keydown.enter.prevent="parseSearch"
|
||||
@submit.prevent="parseSearch"
|
||||
@@ -47,8 +47,8 @@
|
||||
aria-label="Search"
|
||||
autocomplete="off"
|
||||
class="form-control bg-transparent border-0"
|
||||
placeholder="SteamID64, Profile Link or Custom URL"
|
||||
title="SteamID64, Profile Link or Custom URL"
|
||||
placeholder="SteamID, Profile Link or ShareCode"
|
||||
title="SteamID, Profile Link or ShareCode"
|
||||
type="search"
|
||||
/>
|
||||
<button
|
||||
@@ -67,11 +67,24 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive } from "vue";
|
||||
import { closeNav, closeNavEventListener, GetUser, GoToPlayer } from "@/utils";
|
||||
import {
|
||||
CUSTOM_URL_PATTERN,
|
||||
closeNav,
|
||||
closeNavEventListener,
|
||||
GetMatchDetails,
|
||||
GetUser,
|
||||
GoToMatch,
|
||||
GoToPlayer,
|
||||
ParseMatch,
|
||||
parseShareCode,
|
||||
sleep,
|
||||
stringSanitizer,
|
||||
} from "@/utils";
|
||||
import {
|
||||
CUSTOM_URL_BASE,
|
||||
ID64_PATTERN,
|
||||
PROFILE_URL_PATTERN,
|
||||
MATCH_SHARE_URL_BASE,
|
||||
PROFILE_URL_BASE,
|
||||
SHARECODE_REGEX,
|
||||
VANITY_PATTERN,
|
||||
} from "@/constants";
|
||||
import { StatusCodes as STATUS } from "http-status-codes";
|
||||
@@ -89,46 +102,57 @@ const data = reactive({
|
||||
});
|
||||
|
||||
const parseSearch = async () => {
|
||||
const input = data.searchInput;
|
||||
let input = data.searchInput;
|
||||
|
||||
searchParamsStore.vanity_url = "";
|
||||
searchParamsStore.id64 = "";
|
||||
searchParamsStore.$reset();
|
||||
|
||||
if (data.searchInput !== "") {
|
||||
if (ID64_PATTERN.test(input)) {
|
||||
searchParamsStore.id64 = input;
|
||||
} else if (input.match(CUSTOM_URL_PATTERN)) {
|
||||
searchParamsStore.vanity_url = input.split("/")[4].split("?")[0];
|
||||
} else if (input.match(PROFILE_URL_PATTERN)) {
|
||||
const tmp = input.split("/")[4].split("?")[0];
|
||||
if (ID64_PATTERN.test(tmp)) {
|
||||
searchParamsStore.id64 = tmp;
|
||||
// remove various base-urls + cut excess parameters
|
||||
input = input
|
||||
.replace(MATCH_SHARE_URL_BASE, "")
|
||||
.replace(CUSTOM_URL_BASE, "")
|
||||
.replace(PROFILE_URL_BASE, "")
|
||||
.split("/")[0]
|
||||
.split("?")[0];
|
||||
|
||||
// process shareCode
|
||||
const tmpShareCode = Array.from(input.matchAll(SHARECODE_REGEX));
|
||||
const inputShareCode = tmpShareCode.length > 0 ? tmpShareCode[0][0] : "";
|
||||
searchParamsStore.shareCode = SHARECODE_REGEX.test(inputShareCode)
|
||||
? inputShareCode
|
||||
: "";
|
||||
|
||||
// process id64
|
||||
const tmpId64 = Array.from(input.matchAll(ID64_PATTERN));
|
||||
const inputId64 = tmpId64.length > 0 ? tmpId64[0][0] : "";
|
||||
searchParamsStore.id64 = ID64_PATTERN.test(inputId64) ? inputId64 : "";
|
||||
|
||||
// process vanityUrl
|
||||
if (searchParamsStore.shareCode === "" && searchParamsStore.id64 === "") {
|
||||
if (input.includes(CUSTOM_URL_BASE)) {
|
||||
input = input.replace(CUSTOM_URL_BASE, "");
|
||||
}
|
||||
|
||||
if (VANITY_PATTERN.test(input)) {
|
||||
searchParamsStore.vanityUrl = stringSanitizer(input);
|
||||
} else {
|
||||
const info: infoState = {
|
||||
statusCode: STATUS.NOT_ACCEPTABLE,
|
||||
message:
|
||||
'Only alphanumeric symbols, "_", and "-", between 3-32 characters',
|
||||
type: "warning",
|
||||
};
|
||||
infoStateStore.addInfo(info);
|
||||
}
|
||||
} else {
|
||||
searchParamsStore.vanity_url = input;
|
||||
}
|
||||
|
||||
if (
|
||||
searchParamsStore.vanity_url !== "" &&
|
||||
!VANITY_PATTERN.test(searchParamsStore.vanity_url)
|
||||
) {
|
||||
const info: infoState = {
|
||||
statusCode: STATUS.NOT_ACCEPTABLE,
|
||||
message:
|
||||
'Only alphanumeric symbols, "_", and "-", between 3-32 characters',
|
||||
type: "warning",
|
||||
};
|
||||
infoStateStore.addInfo(info);
|
||||
searchParamsStore.vanity_url = "";
|
||||
data.searchInput = "";
|
||||
}
|
||||
|
||||
if (searchParamsStore.id64 !== "" || searchParamsStore.vanity_url !== "") {
|
||||
const resData = await GetUser(
|
||||
playerDetailsStore,
|
||||
searchParamsStore.vanity_url || searchParamsStore.id64
|
||||
// GetUser
|
||||
if (searchParamsStore.id64 !== "" || searchParamsStore.vanityUrl !== "") {
|
||||
const [resData, info] = await GetUser(
|
||||
searchParamsStore.vanityUrl || searchParamsStore.id64
|
||||
);
|
||||
|
||||
if (info.message !== "") infoStateStore.addInfo(info);
|
||||
if (resData !== null) {
|
||||
data.searchInput = "";
|
||||
const activeElem = document.activeElement as HTMLInputElement;
|
||||
@@ -136,15 +160,38 @@ const parseSearch = async () => {
|
||||
|
||||
playerDetailsStore.playerDetails = resData;
|
||||
|
||||
if (searchParamsStore.vanity_url) {
|
||||
if (searchParamsStore.vanityUrl) {
|
||||
closeNav("mainNav");
|
||||
GoToPlayer(searchParamsStore.vanity_url);
|
||||
GoToPlayer(searchParamsStore.vanityUrl);
|
||||
} else if (searchParamsStore.id64) {
|
||||
closeNav("mainNav");
|
||||
GoToPlayer(searchParamsStore.id64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ParseMatch
|
||||
if (searchParamsStore.shareCode !== "") {
|
||||
data.searchInput = "";
|
||||
|
||||
const matchId = parseShareCode(searchParamsStore.shareCode);
|
||||
let info = await ParseMatch(searchParamsStore.shareCode);
|
||||
|
||||
if (info.message !== "") infoStateStore.addInfo(info);
|
||||
if (info.statusCode === STATUS.OK) GoToMatch(matchId);
|
||||
|
||||
if (info.statusCode === STATUS.ACCEPTED) {
|
||||
let [res, info] = await GetMatchDetails(matchId);
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (res !== null && res.parsed) break;
|
||||
[res, info] = await GetMatchDetails(matchId);
|
||||
|
||||
sleep(2000);
|
||||
}
|
||||
GoToMatch(matchId);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,13 +1,15 @@
|
||||
export const SHARECODE_REGEX =
|
||||
/^CSGO(?:-?[ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789]{5}){5}$/;
|
||||
/^CSGO(?:-?[ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789]{5}){5}$/g;
|
||||
export const AUTHCODE_REGEX =
|
||||
/^[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{4}-[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{5}-[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{4}$/;
|
||||
/^[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{4}-[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{5}-[ABCDEFGHJKLMNOPQRSTUVWXYZ23456789]{4}$/g;
|
||||
|
||||
export const ID64_PATTERN = /^\d{17}$/;
|
||||
export const VANITY_PATTERN = /^[A-Za-z0-9-_]{3,32}$/;
|
||||
export const ID64_PATTERN = /^\d{17}$/g;
|
||||
export const VANITY_PATTERN = /^[A-Za-z0-9-_]{3,32}$/g;
|
||||
|
||||
export const CUSTOM_URL_PATTERN = "https://steamcommunity.com/id/";
|
||||
export const PROFILE_URL_PATTERN = "https://steamcommunity.com/profiles/";
|
||||
export const CUSTOM_URL_BASE = "https://steamcommunity.com/id/";
|
||||
export const PROFILE_URL_BASE = "https://steamcommunity.com/profiles/";
|
||||
export const MATCH_SHARE_URL_BASE =
|
||||
"steam://rungame/730/76561202255233023/+csgo_download_match%20";
|
||||
|
||||
export const NAV_HEIGHT = 70;
|
||||
export const FOOTER_HEIGHT = 200;
|
||||
|
@@ -2,7 +2,8 @@ import { defineStore } from "pinia";
|
||||
|
||||
export type RootState = {
|
||||
id64: string;
|
||||
vanity_url: string;
|
||||
vanityUrl: string;
|
||||
shareCode: string;
|
||||
};
|
||||
|
||||
export const useSearchParamsStore = defineStore({
|
||||
@@ -10,7 +11,8 @@ export const useSearchParamsStore = defineStore({
|
||||
state: () =>
|
||||
({
|
||||
id64: "",
|
||||
vanity_url: "",
|
||||
vanityUrl: "",
|
||||
shareCode: "",
|
||||
} as RootState),
|
||||
actions: {},
|
||||
getters: {},
|
||||
|
@@ -443,3 +443,43 @@ export const LoadMoreMatchesExplore = async (
|
||||
|
||||
return [response, info];
|
||||
};
|
||||
|
||||
// /match/parse/<shareCode>
|
||||
export const ParseMatch = async (shareCode: string): Promise<infoState> => {
|
||||
const info = reactive<infoState>({
|
||||
statusCode: 0,
|
||||
message: "",
|
||||
type: "success",
|
||||
});
|
||||
|
||||
await axios
|
||||
.get(`${API_URL}/match/parse/${shareCode}`)
|
||||
.then((res) => {
|
||||
switch (res.status) {
|
||||
case STATUS.OK:
|
||||
info.statusCode = STATUS.OK;
|
||||
info.message = "";
|
||||
break;
|
||||
case STATUS.ACCEPTED:
|
||||
info.statusCode = STATUS.ACCEPTED;
|
||||
info.message = "Match will be parsed";
|
||||
break;
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
switch (err.response.status) {
|
||||
case STATUS.BAD_REQUEST:
|
||||
info.message = "Bad request";
|
||||
break;
|
||||
case STATUS.SERVICE_UNAVAILABLE:
|
||||
info.message = "Unable to parse match";
|
||||
break;
|
||||
default:
|
||||
info.message = "An unknown error occurred";
|
||||
}
|
||||
info.statusCode = err.response.status;
|
||||
info.type = "error";
|
||||
});
|
||||
|
||||
return info;
|
||||
};
|
||||
|
@@ -1,10 +1,12 @@
|
||||
import { GoToError } from "@/utils/GoTo";
|
||||
import type { MatchStats, Player } from "@/types";
|
||||
import { decodeMatchShareCode } from "csgo-sharecode";
|
||||
|
||||
enum ErrorPage {
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
BAD_GATEWAY = 502,
|
||||
}
|
||||
|
||||
export const errorHandling = (code: number): void => {
|
||||
if (code === ErrorPage.INTERNAL_SERVER_ERROR) {
|
||||
GoToError("500");
|
||||
@@ -41,6 +43,7 @@ enum WLD {
|
||||
LOSS = "loss",
|
||||
DRAW = "draw",
|
||||
}
|
||||
|
||||
export const GetWinLoss = (matchResult: number, teamId: number): WLD => {
|
||||
if (matchResult === teamId) {
|
||||
return WLD.WIN;
|
||||
@@ -168,3 +171,20 @@ export const setAppDivBackground = (value: string, type: any): void => {
|
||||
const appDiv = document.getElementById("app") as typeof type;
|
||||
appDiv.style.background = value;
|
||||
};
|
||||
|
||||
export const stringSanitizer = (input: string): string => {
|
||||
return input
|
||||
.replaceAll(/[^a-zA-Z0-9;=-\\\\/]/g, "")
|
||||
.replaceAll(/\s{2,}/g, "")
|
||||
.replaceAll(/\r/g, "")
|
||||
.replaceAll(/\n/g, "");
|
||||
};
|
||||
|
||||
export const parseShareCode = (shareCode: string): string => {
|
||||
return decodeMatchShareCode(shareCode).matchId.toString();
|
||||
};
|
||||
|
||||
export const sleep = (delay: number) => {
|
||||
const start = new Date().getTime();
|
||||
while (new Date().getTime() < start + delay);
|
||||
};
|
||||
|
16
yarn.lock
16
yarn.lock
@@ -907,6 +907,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"csgo-sharecode@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "csgo-sharecode@npm:3.0.1"
|
||||
checksum: b0b7929e258f4e323641ffc527e6e4e34ad7ac722ea02a1a5b4414bc3e880891488b8f17e4ff9e105becc66899dc238d6c0935ea01ae4a1663310334867e1b42
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"csgowtf@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "csgowtf@workspace:."
|
||||
@@ -923,6 +930,7 @@ __metadata:
|
||||
axios: ^0.26.1
|
||||
bootstrap: ^5.1.3
|
||||
bootstrap-icons: ^1.8.1
|
||||
csgo-sharecode: ^3.0.1
|
||||
echarts: ^5.3.1
|
||||
eslint: ^8.11.0
|
||||
eslint-plugin-vue: ^8.5.0
|
||||
@@ -934,7 +942,6 @@ __metadata:
|
||||
pinia: ^2.0.12
|
||||
prettier: ^2.6.0
|
||||
sass: ^1.49.9
|
||||
string-sanitizer: ^2.0.2
|
||||
typescript: ~4.6.2
|
||||
vite: ^2.8.6
|
||||
vue: ^3.2.31
|
||||
@@ -2695,13 +2702,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"string-sanitizer@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "string-sanitizer@npm:2.0.2"
|
||||
checksum: 978be8325ee29c6ca97b97e86a578eea637db3da35fe6f1b260f917e984a8520c3f58bc4c83c0c2000da3cd5d6405117ef3e20af3feae5be44f90d7d1a12fe42
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.2.3":
|
||||
version: 4.2.3
|
||||
resolution: "string-width@npm:4.2.3"
|
||||
|
Reference in New Issue
Block a user