Skip to content

Commit

Permalink
Add detection query and trigger count
Browse files Browse the repository at this point in the history
  • Loading branch information
leighmacdonald committed Jan 30, 2025
1 parent 918f2ad commit f574f5a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 24 deletions.
29 changes: 17 additions & 12 deletions frontend/src/api/anticheat.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { transformCreatedOnDate } from '../util/time.ts';
import { apiCall, QueryFilter } from './common.ts';

export type Detection =
| 'unknown'
| 'silent_aim'
| 'aim_snap'
| 'too_many_conn'
| 'interp'
| 'bhop'
| 'cmdnum_spike'
| 'eye_angles'
| 'invalid_user_cmd'
| 'oob_cvar'
| 'cheat_cvar';
export const Detections = [
'unknown',
'silent_aim',
'aim_snap',
'too_many_conn',
'interp',
'bhop',
'cmdnum_spike',
'cmdnum_spike',
'eye_angles',
'invalid_user_cmd',
'oob_cvar',
'cheat_cvar'
] as const;

export type Detection = (typeof Detections)[number];

export type StacEntry = {
anticheat_id: number;
Expand All @@ -24,6 +28,7 @@ export type StacEntry = {
demo_tick: number;
name: string;
detection: Detection;
triggered: number;
summary: string;
raw_log: string;
created_on: Date;
Expand Down
53 changes: 44 additions & 9 deletions frontend/src/routes/_mod.admin.anticheat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { createFileRoute, useLoaderData, useNavigate } from '@tanstack/react-rou
import { createColumnHelper, PaginationState, SortingState } from '@tanstack/react-table';
import { zodValidator } from '@tanstack/zod-form-adapter';
import { z } from 'zod';
import { apiGetAnticheatLogs, apiGetServers, Detection, ServerSimple, StacEntry } from '../api';
import { apiGetAnticheatLogs, apiGetServers, Detection, Detections, ServerSimple, StacEntry } from '../api';
import { ContainerWithHeader } from '../component/ContainerWithHeader.tsx';
import { ContainerWithHeaderAndButtons } from '../component/ContainerWithHeaderAndButtons.tsx';
import { FullTable } from '../component/FullTable.tsx';
Expand Down Expand Up @@ -194,6 +194,11 @@ function AdminAnticheat() {
}),
columnHelper.accessor('detection', {
header: 'Detection',
size: 130,
cell: (info) => <TableCellString>{info.getValue()}</TableCellString>
}),
columnHelper.accessor('triggered', {
header: 'Count',
size: 80,
cell: (info) => <TableCellString>{info.getValue()}</TableCellString>
}),
Expand Down Expand Up @@ -240,14 +245,6 @@ function AdminAnticheat() {
}}
/>
</Grid>
<Grid xs={6} md={3}>
<Field
name={'summary'}
children={(props) => {
return <TextFieldSimple {...props} label={'Message'} />;
}}
/>
</Grid>

<Grid xs={6} md={3}>
<Field
Expand Down Expand Up @@ -279,6 +276,44 @@ function AdminAnticheat() {
}}
/>
</Grid>
<Grid xs={6} md={3}>
<Field
name={'detection'}
children={({ state, handleChange, handleBlur }) => {
return (
<>
<FormControl fullWidth>
<InputLabel id="detection-select-label">Detection</InputLabel>
<Select
fullWidth
value={state.value}
label="Detection"
onChange={(e) => {
handleChange(e.target.value);
}}
onBlur={handleBlur}
>
<MenuItem value={0}>All</MenuItem>
{Detections.map((s) => (
<MenuItem value={s} key={s}>
{s}
</MenuItem>
))}
</Select>
</FormControl>
</>
);
}}
/>
</Grid>
<Grid xs={12}>
<Field
name={'summary'}
children={(props) => {
return <TextFieldSimple {...props} label={'Message'} />;
}}
/>
</Grid>
<Grid xs={12} mdOffset="auto">
<Subscribe
selector={(state) => [state.canSubmit, state.isSubmitting]}
Expand Down
10 changes: 7 additions & 3 deletions internal/anticheat/anticheat_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ type anticheatRepository struct {
func (a anticheatRepository) Query(ctx context.Context, query domain.AnticheatQuery) ([]domain.AnticheatEntry, error) {
builder := a.db.Builder().
Select("a.anticheat_id", "a.steam_id", "a.name", "a.detection", "a.summary", "a.demo_id", "a.demo_tick",
"a.server_id", "a.raw_log", "s.short_name", "p.personaname", "p.avatarhash").
"a.server_id", "a.raw_log", "s.short_name", "p.personaname", "p.avatarhash", "a.created_on",
"RANK () OVER (PARTITION BY a.steam_id, a.detection ORDER BY a.created_on) triggered").
From("anticheat a").
LeftJoin("server s USING(server_id)").
LeftJoin("person p USING(steam_id)")

var filters sq.And
if query.Summary != "" {
filters = append(filters, sq.Like{"a.summary": "%" + strings.ToLower(query.Summary) + "%"})
filters = append(filters, sq.Like{"lower(a.summary)": "%" + strings.ToLower(query.Summary) + "%"})
}
if query.SteamID != "" {
sid := steamid.New(query.SteamID)
Expand All @@ -42,6 +43,9 @@ func (a anticheatRepository) Query(ctx context.Context, query domain.AnticheatQu
if query.Name != "" {
filters = append(filters, sq.Like{"a.name": "%" + strings.ToLower(query.Name) + "%"})
}
if query.Detection != "" {
filters = append(filters, sq.Eq{"a.detection": query.Detection})
}

if len(filters) > 0 {
builder = builder.Where(filters)
Expand All @@ -68,7 +72,7 @@ func (a anticheatRepository) Query(ctx context.Context, query domain.AnticheatQu
var entry domain.AnticheatEntry
if err := rows.Scan(&entry.AnticheatID, &entry.SteamID, &entry.Personaname, &entry.Detection, &entry.Summary,
&entry.DemoID, &entry.DemoTick, &entry.ServerID, &entry.RawLog, &entry.ServerName, &entry.Personaname,
&entry.AvatarHash); err != nil {
&entry.AvatarHash, &entry.CreatedOn, &entry.Triggered); err != nil {
return nil, a.db.DBErr(err)
}

Expand Down
1 change: 1 addition & 0 deletions internal/domain/anticheat.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type AnticheatEntry struct {
logparse.StacEntry
Personaname string `json:"personaname"`
AvatarHash string `json:"avatar_hash"`
Triggered int `json:"triggered"`
}

type AntiCheatRepository interface {
Expand Down

0 comments on commit f574f5a

Please sign in to comment.