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", "axios": "^0.26.1",
"bootstrap": "^5.1.3", "bootstrap": "^5.1.3",
"bootstrap-icons": "^1.8.1", "bootstrap-icons": "^1.8.1",
"csgo-sharecode": "^3.0.1",
"echarts": "^5.3.1", "echarts": "^5.3.1",
"fork-awesome": "^1.2.0", "fork-awesome": "^1.2.0",
"http-status-codes": "^2.2.0", "http-status-codes": "^2.2.0",
@@ -21,7 +22,6 @@
"jquery": "^3.6.0", "jquery": "^3.6.0",
"luxon": "^2.3.1", "luxon": "^2.3.1",
"pinia": "^2.0.12", "pinia": "^2.0.12",
"string-sanitizer": "^2.0.2",
"vue": "^3.2.31", "vue": "^3.2.31",
"vue-matomo": "^4.1.0", "vue-matomo": "^4.1.0",
"vue-router": "^4.0.14", "vue-router": "^4.0.14",

View File

@@ -32,7 +32,7 @@
</li> </li>
</ul> </ul>
<form <form
id="searchform" id="search-form"
class="d-flex" class="d-flex"
@keydown.enter.prevent="parseSearch" @keydown.enter.prevent="parseSearch"
@submit.prevent="parseSearch" @submit.prevent="parseSearch"
@@ -47,8 +47,8 @@
aria-label="Search" aria-label="Search"
autocomplete="off" autocomplete="off"
class="form-control bg-transparent border-0" class="form-control bg-transparent border-0"
placeholder="SteamID64, Profile Link or Custom URL" placeholder="SteamID, Profile Link or ShareCode"
title="SteamID64, Profile Link or Custom URL" title="SteamID, Profile Link or ShareCode"
type="search" type="search"
/> />
<button <button
@@ -67,11 +67,24 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from "vue"; import { reactive } from "vue";
import { closeNav, closeNavEventListener, GetUser, GoToPlayer } from "@/utils";
import { import {
CUSTOM_URL_PATTERN, closeNav,
closeNavEventListener,
GetMatchDetails,
GetUser,
GoToMatch,
GoToPlayer,
ParseMatch,
parseShareCode,
sleep,
stringSanitizer,
} from "@/utils";
import {
CUSTOM_URL_BASE,
ID64_PATTERN, ID64_PATTERN,
PROFILE_URL_PATTERN, MATCH_SHARE_URL_BASE,
PROFILE_URL_BASE,
SHARECODE_REGEX,
VANITY_PATTERN, VANITY_PATTERN,
} from "@/constants"; } from "@/constants";
import { StatusCodes as STATUS } from "http-status-codes"; import { StatusCodes as STATUS } from "http-status-codes";
@@ -89,46 +102,57 @@ const data = reactive({
}); });
const parseSearch = async () => { const parseSearch = async () => {
const input = data.searchInput; let input = data.searchInput;
searchParamsStore.vanity_url = ""; searchParamsStore.$reset();
searchParamsStore.id64 = "";
if (data.searchInput !== "") { if (data.searchInput !== "") {
if (ID64_PATTERN.test(input)) { // remove various base-urls + cut excess parameters
searchParamsStore.id64 = input; input = input
} else if (input.match(CUSTOM_URL_PATTERN)) { .replace(MATCH_SHARE_URL_BASE, "")
searchParamsStore.vanity_url = input.split("/")[4].split("?")[0]; .replace(CUSTOM_URL_BASE, "")
} else if (input.match(PROFILE_URL_PATTERN)) { .replace(PROFILE_URL_BASE, "")
const tmp = input.split("/")[4].split("?")[0]; .split("/")[0]
if (ID64_PATTERN.test(tmp)) { .split("?")[0];
searchParamsStore.id64 = tmp;
// 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 ( // GetUser
searchParamsStore.vanity_url !== "" && if (searchParamsStore.id64 !== "" || searchParamsStore.vanityUrl !== "") {
!VANITY_PATTERN.test(searchParamsStore.vanity_url) const [resData, info] = await GetUser(
) { searchParamsStore.vanityUrl || searchParamsStore.id64
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
); );
if (info.message !== "") infoStateStore.addInfo(info);
if (resData !== null) { if (resData !== null) {
data.searchInput = ""; data.searchInput = "";
const activeElem = document.activeElement as HTMLInputElement; const activeElem = document.activeElement as HTMLInputElement;
@@ -136,15 +160,38 @@ const parseSearch = async () => {
playerDetailsStore.playerDetails = resData; playerDetailsStore.playerDetails = resData;
if (searchParamsStore.vanity_url) { if (searchParamsStore.vanityUrl) {
closeNav("mainNav"); closeNav("mainNav");
GoToPlayer(searchParamsStore.vanity_url); GoToPlayer(searchParamsStore.vanityUrl);
} else if (searchParamsStore.id64) { } else if (searchParamsStore.id64) {
closeNav("mainNav"); closeNav("mainNav");
GoToPlayer(searchParamsStore.id64); 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 = export const SHARECODE_REGEX =
/^CSGO(?:-?[ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789]{5}){5}$/; /^CSGO(?:-?[ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789]{5}){5}$/g;
export const AUTHCODE_REGEX = 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 ID64_PATTERN = /^\d{17}$/g;
export const VANITY_PATTERN = /^[A-Za-z0-9-_]{3,32}$/; export const VANITY_PATTERN = /^[A-Za-z0-9-_]{3,32}$/g;
export const CUSTOM_URL_PATTERN = "https://steamcommunity.com/id/"; export const CUSTOM_URL_BASE = "https://steamcommunity.com/id/";
export const PROFILE_URL_PATTERN = "https://steamcommunity.com/profiles/"; 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 NAV_HEIGHT = 70;
export const FOOTER_HEIGHT = 200; export const FOOTER_HEIGHT = 200;

View File

@@ -2,7 +2,8 @@ import { defineStore } from "pinia";
export type RootState = { export type RootState = {
id64: string; id64: string;
vanity_url: string; vanityUrl: string;
shareCode: string;
}; };
export const useSearchParamsStore = defineStore({ export const useSearchParamsStore = defineStore({
@@ -10,7 +11,8 @@ export const useSearchParamsStore = defineStore({
state: () => state: () =>
({ ({
id64: "", id64: "",
vanity_url: "", vanityUrl: "",
shareCode: "",
} as RootState), } as RootState),
actions: {}, actions: {},
getters: {}, getters: {},

View File

@@ -443,3 +443,43 @@ export const LoadMoreMatchesExplore = async (
return [response, info]; 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 { GoToError } from "@/utils/GoTo";
import type { MatchStats, Player } from "@/types"; import type { MatchStats, Player } from "@/types";
import { decodeMatchShareCode } from "csgo-sharecode";
enum ErrorPage { enum ErrorPage {
INTERNAL_SERVER_ERROR = 500, INTERNAL_SERVER_ERROR = 500,
BAD_GATEWAY = 502, BAD_GATEWAY = 502,
} }
export const errorHandling = (code: number): void => { export const errorHandling = (code: number): void => {
if (code === ErrorPage.INTERNAL_SERVER_ERROR) { if (code === ErrorPage.INTERNAL_SERVER_ERROR) {
GoToError("500"); GoToError("500");
@@ -41,6 +43,7 @@ enum WLD {
LOSS = "loss", LOSS = "loss",
DRAW = "draw", DRAW = "draw",
} }
export const GetWinLoss = (matchResult: number, teamId: number): WLD => { export const GetWinLoss = (matchResult: number, teamId: number): WLD => {
if (matchResult === teamId) { if (matchResult === teamId) {
return WLD.WIN; return WLD.WIN;
@@ -168,3 +171,20 @@ export const setAppDivBackground = (value: string, type: any): void => {
const appDiv = document.getElementById("app") as typeof type; const appDiv = document.getElementById("app") as typeof type;
appDiv.style.background = value; 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 languageName: node
linkType: hard 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:.": "csgowtf@workspace:.":
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "csgowtf@workspace:." resolution: "csgowtf@workspace:."
@@ -923,6 +930,7 @@ __metadata:
axios: ^0.26.1 axios: ^0.26.1
bootstrap: ^5.1.3 bootstrap: ^5.1.3
bootstrap-icons: ^1.8.1 bootstrap-icons: ^1.8.1
csgo-sharecode: ^3.0.1
echarts: ^5.3.1 echarts: ^5.3.1
eslint: ^8.11.0 eslint: ^8.11.0
eslint-plugin-vue: ^8.5.0 eslint-plugin-vue: ^8.5.0
@@ -934,7 +942,6 @@ __metadata:
pinia: ^2.0.12 pinia: ^2.0.12
prettier: ^2.6.0 prettier: ^2.6.0
sass: ^1.49.9 sass: ^1.49.9
string-sanitizer: ^2.0.2
typescript: ~4.6.2 typescript: ~4.6.2
vite: ^2.8.6 vite: ^2.8.6
vue: ^3.2.31 vue: ^3.2.31
@@ -2695,13 +2702,6 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.2.3":
version: 4.2.3 version: 4.2.3
resolution: "string-width@npm:4.2.3" resolution: "string-width@npm:4.2.3"