updated Nav-Search + removed string-sanitizer + added csgo-sharecode
Some checks failed
CSGOWTF/csgowtf/pipeline/head There was a failure building this commit

This commit is contained in:
2022-03-27 21:11:18 +02:00
parent 9ac3228f5d
commit afed42de49
7 changed files with 168 additions and 57 deletions

View File

@@ -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",

View File

@@ -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);
}
}
}
};

View File

@@ -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;

View File

@@ -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: {},

View File

@@ -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;
};

View File

@@ -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);
};

View File

@@ -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"