gambling-bot-shared 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/casino/index.d.ts +1 -0
- package/dist/casino/index.js +1 -0
- package/dist/casino/utils/calculateRouletteWin.d.ts +9 -0
- package/dist/casino/utils/calculateRouletteWin.js +45 -0
- package/dist/dev/bonusStressTest.d.ts +18 -0
- package/dist/dev/bonusStressTest.js +66 -0
- package/dist/dev/casinoMonteCarlo.d.ts +16 -0
- package/dist/dev/casinoMonteCarlo.js +200 -0
- package/dist/dev/devAccess.d.ts +5 -0
- package/dist/dev/devAccess.js +14 -0
- package/dist/dev/index.d.ts +4 -0
- package/dist/dev/index.js +20 -0
- package/dist/dev/yieldToEventLoop.d.ts +1 -0
- package/dist/dev/yieldToEventLoop.js +7 -0
- package/dist/guild/guildConfiguration.mongoose.d.ts +9 -0
- package/dist/guild/guildConfiguration.mongoose.js +4 -0
- package/dist/guild/schemas/guild.forms.d.ts +1 -0
- package/dist/guild/schemas/guild.forms.js +2 -1
- package/dist/guild/types/guildConfiguration.d.ts +1 -0
- package/dist/transactions/constants/staffAudit.d.ts +4 -1
- package/dist/transactions/constants/staffAudit.js +6 -2
- package/dist/user/index.d.ts +1 -0
- package/dist/user/index.js +1 -0
- package/dist/user/types/user.d.ts +17 -0
- package/dist/user/user.mongoose.d.ts +45 -0
- package/dist/user/user.mongoose.js +18 -1
- package/dist/user/utils/userModeration.d.ts +16 -0
- package/dist/user/utils/userModeration.js +44 -0
- package/package.json +5 -1
package/dist/casino/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './constants';
|
|
|
2
2
|
export * from './types/casinoSettings';
|
|
3
3
|
export * from './types/blackjackGame';
|
|
4
4
|
export * from './utils/calculateRTP';
|
|
5
|
+
export * from './utils/calculateRouletteWin';
|
|
5
6
|
export * from './utils/validateBetAmount';
|
|
6
7
|
export * from './utils/normalizeCasinoSettings';
|
|
7
8
|
export * from './utils/winAnnouncements';
|
package/dist/casino/index.js
CHANGED
|
@@ -18,6 +18,7 @@ __exportStar(require("./constants"), exports);
|
|
|
18
18
|
__exportStar(require("./types/casinoSettings"), exports);
|
|
19
19
|
__exportStar(require("./types/blackjackGame"), exports);
|
|
20
20
|
__exportStar(require("./utils/calculateRTP"), exports);
|
|
21
|
+
__exportStar(require("./utils/calculateRouletteWin"), exports);
|
|
21
22
|
__exportStar(require("./utils/validateBetAmount"), exports);
|
|
22
23
|
__exportStar(require("./utils/normalizeCasinoSettings"), exports);
|
|
23
24
|
__exportStar(require("./utils/winAnnouncements"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { TCasinoSettings } from '../types/casinoSettings';
|
|
2
|
+
export type RouletteBetType = keyof TCasinoSettings['roulette']['winMultipliers'];
|
|
3
|
+
export type RouletteBet = {
|
|
4
|
+
type: RouletteBetType;
|
|
5
|
+
value: string;
|
|
6
|
+
amount: number;
|
|
7
|
+
};
|
|
8
|
+
export type RouletteWinMultipliers = TCasinoSettings['roulette']['winMultipliers'];
|
|
9
|
+
export declare function calculateRouletteWin(bet: RouletteBet, result: string, payouts: RouletteWinMultipliers): number;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateRouletteWin = calculateRouletteWin;
|
|
4
|
+
const rouletteConfig_1 = require("../constants/rouletteConfig");
|
|
5
|
+
function calculateRouletteWin(bet, result, payouts) {
|
|
6
|
+
const amount = bet.amount;
|
|
7
|
+
const numResult = Number(result);
|
|
8
|
+
switch (bet.type) {
|
|
9
|
+
case 'number':
|
|
10
|
+
return bet.value === result ? amount * payouts.number : 0;
|
|
11
|
+
case 'color':
|
|
12
|
+
if (result === '0')
|
|
13
|
+
return 0;
|
|
14
|
+
return rouletteConfig_1.MINI_NUMBERS[result] === bet.value.toLowerCase()
|
|
15
|
+
? amount * payouts.color
|
|
16
|
+
: 0;
|
|
17
|
+
case 'parity':
|
|
18
|
+
if (result === '0')
|
|
19
|
+
return 0;
|
|
20
|
+
return bet.value.toLowerCase() === (numResult % 2 === 0 ? 'even' : 'odd')
|
|
21
|
+
? amount * payouts.parity
|
|
22
|
+
: 0;
|
|
23
|
+
case 'range':
|
|
24
|
+
if (result === '0')
|
|
25
|
+
return 0;
|
|
26
|
+
return bet.value.toLowerCase() ===
|
|
27
|
+
(numResult >= 1 && numResult <= 9 ? 'low' : 'high')
|
|
28
|
+
? amount * payouts.range
|
|
29
|
+
: 0;
|
|
30
|
+
case 'dozen':
|
|
31
|
+
if (result === '0')
|
|
32
|
+
return 0;
|
|
33
|
+
return Number(bet.value) === Math.ceil(numResult / 6)
|
|
34
|
+
? amount * payouts.dozen
|
|
35
|
+
: 0;
|
|
36
|
+
case 'column':
|
|
37
|
+
if (result === '0')
|
|
38
|
+
return 0;
|
|
39
|
+
return Number(bet.value) === ((numResult - 1) % 3) + 1
|
|
40
|
+
? amount * payouts.column
|
|
41
|
+
: 0;
|
|
42
|
+
default:
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { BonusSettings } from '../bonus/types/bonus';
|
|
2
|
+
import type { PreviewDay } from '../bonus/utils/generateBonusPreview';
|
|
3
|
+
export type BonusStressSummary = {
|
|
4
|
+
days: number;
|
|
5
|
+
totalReward: number;
|
|
6
|
+
avgReward: number;
|
|
7
|
+
maxReward: number;
|
|
8
|
+
maxDay: number;
|
|
9
|
+
resetCount: number;
|
|
10
|
+
weeklyBonuses: number;
|
|
11
|
+
monthlyBonuses: number;
|
|
12
|
+
cycleLength: number;
|
|
13
|
+
elapsedMs: number;
|
|
14
|
+
};
|
|
15
|
+
export type BonusStressResult = BonusStressSummary & {
|
|
16
|
+
preview: PreviewDay[];
|
|
17
|
+
};
|
|
18
|
+
export declare function runBonusStressTest(settings: BonusSettings, days: number, onProgress?: (completed: number, total: number) => void, chunkSize?: number): Promise<BonusStressResult>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runBonusStressTest = runBonusStressTest;
|
|
4
|
+
const calculateBonusReward_1 = require("../bonus/utils/calculateBonusReward");
|
|
5
|
+
const yieldToEventLoop_1 = require("./yieldToEventLoop");
|
|
6
|
+
const summarizePreview = (preview, settings, elapsedMs) => {
|
|
7
|
+
let totalReward = 0;
|
|
8
|
+
let maxReward = 0;
|
|
9
|
+
let maxDay = 1;
|
|
10
|
+
let resetCount = 0;
|
|
11
|
+
let weeklyBonuses = 0;
|
|
12
|
+
let monthlyBonuses = 0;
|
|
13
|
+
for (const day of preview) {
|
|
14
|
+
totalReward += day.reward;
|
|
15
|
+
if (day.reward > maxReward) {
|
|
16
|
+
maxReward = day.reward;
|
|
17
|
+
maxDay = day.day;
|
|
18
|
+
}
|
|
19
|
+
if (day.isReset)
|
|
20
|
+
resetCount++;
|
|
21
|
+
if (day.weekly > 0)
|
|
22
|
+
weeklyBonuses++;
|
|
23
|
+
if (day.monthly > 0)
|
|
24
|
+
monthlyBonuses++;
|
|
25
|
+
}
|
|
26
|
+
const cycleLength = (0, calculateBonusReward_1.getBonusCycleLength)(settings.rewardMode, settings.baseReward, settings.maxReward, settings.streakIncrement ?? 0, settings.streakMultiplier ?? 1);
|
|
27
|
+
return {
|
|
28
|
+
days: preview.length,
|
|
29
|
+
totalReward: Number(totalReward.toFixed(2)),
|
|
30
|
+
avgReward: preview.length
|
|
31
|
+
? Number((totalReward / preview.length).toFixed(2))
|
|
32
|
+
: 0,
|
|
33
|
+
maxReward,
|
|
34
|
+
maxDay,
|
|
35
|
+
resetCount,
|
|
36
|
+
weeklyBonuses,
|
|
37
|
+
monthlyBonuses,
|
|
38
|
+
cycleLength,
|
|
39
|
+
elapsedMs,
|
|
40
|
+
preview
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
async function runBonusStressTest(settings, days, onProgress, chunkSize = 5000) {
|
|
44
|
+
const started = performance.now();
|
|
45
|
+
const preview = [];
|
|
46
|
+
let completed = 0;
|
|
47
|
+
while (completed < days) {
|
|
48
|
+
const batch = Math.min(chunkSize, days - completed);
|
|
49
|
+
for (let i = 0; i < batch; i++) {
|
|
50
|
+
const day = completed + i + 1;
|
|
51
|
+
const reward = (0, calculateBonusReward_1.calculateBonusReward)({ streak: day, settings });
|
|
52
|
+
preview.push({
|
|
53
|
+
day,
|
|
54
|
+
reward: reward.reward,
|
|
55
|
+
base: reward.base,
|
|
56
|
+
weekly: reward.weekly,
|
|
57
|
+
monthly: reward.monthly,
|
|
58
|
+
isReset: reward.isReset
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
completed += batch;
|
|
62
|
+
onProgress?.(completed, days);
|
|
63
|
+
await (0, yieldToEventLoop_1.yieldToEventLoop)();
|
|
64
|
+
}
|
|
65
|
+
return summarizePreview(preview, settings, Math.round(performance.now() - started));
|
|
66
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TCasinoSettings } from '../casino/types/casinoSettings';
|
|
2
|
+
import { type RouletteBetType } from '../casino/utils/calculateRouletteWin';
|
|
3
|
+
export type MonteCarloTarget = 'dice' | 'coinflip' | 'slots' | 'lottery' | 'plinko' | 'goldenJackpot' | `roulette:${RouletteBetType}`;
|
|
4
|
+
export declare const MONTE_CARLO_TARGETS: MonteCarloTarget[];
|
|
5
|
+
export type MonteCarloResult = {
|
|
6
|
+
target: MonteCarloTarget;
|
|
7
|
+
label: string;
|
|
8
|
+
iterations: number;
|
|
9
|
+
theoreticalRtp: number | null;
|
|
10
|
+
empiricalRtp: number;
|
|
11
|
+
delta: number | null;
|
|
12
|
+
elapsedMs: number;
|
|
13
|
+
distribution?: Record<string, number>;
|
|
14
|
+
};
|
|
15
|
+
export declare function runMonteCarloSimulation(target: MonteCarloTarget, settings: TCasinoSettings, iterations: number, onProgress?: (completed: number, total: number) => void, chunkSize?: number): Promise<MonteCarloResult>;
|
|
16
|
+
export declare function runAllMonteCarloSimulations(settings: TCasinoSettings, iterations: number, onProgress?: (completed: number, total: number) => void): Promise<MonteCarloResult[]>;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MONTE_CARLO_TARGETS = void 0;
|
|
4
|
+
exports.runMonteCarloSimulation = runMonteCarloSimulation;
|
|
5
|
+
exports.runAllMonteCarloSimulations = runAllMonteCarloSimulations;
|
|
6
|
+
const lotteryConfig_1 = require("../casino/constants/lotteryConfig");
|
|
7
|
+
const plinkoConfig_1 = require("../casino/constants/plinkoConfig");
|
|
8
|
+
const plinkoConfig_2 = require("../casino/constants/plinkoConfig");
|
|
9
|
+
const rouletteConfig_1 = require("../casino/constants/rouletteConfig");
|
|
10
|
+
const calculateRTP_1 = require("../casino/utils/calculateRTP");
|
|
11
|
+
const calculateRouletteWin_1 = require("../casino/utils/calculateRouletteWin");
|
|
12
|
+
const yieldToEventLoop_1 = require("./yieldToEventLoop");
|
|
13
|
+
const toNumber = (val) => {
|
|
14
|
+
if (typeof val === 'string')
|
|
15
|
+
return parseFloat(val) || 0;
|
|
16
|
+
if (typeof val === 'number')
|
|
17
|
+
return val;
|
|
18
|
+
return 0;
|
|
19
|
+
};
|
|
20
|
+
const ROULETTE_NUMBERS = Object.keys(rouletteConfig_1.MINI_NUMBERS);
|
|
21
|
+
const ROULETTE_BET_TYPES = [
|
|
22
|
+
'number',
|
|
23
|
+
'color',
|
|
24
|
+
'parity',
|
|
25
|
+
'range',
|
|
26
|
+
'dozen',
|
|
27
|
+
'column'
|
|
28
|
+
];
|
|
29
|
+
const ROULETTE_REP_BETS = {
|
|
30
|
+
number: { type: 'number', value: '1', amount: 1 },
|
|
31
|
+
color: { type: 'color', value: 'red', amount: 1 },
|
|
32
|
+
parity: { type: 'parity', value: 'even', amount: 1 },
|
|
33
|
+
range: { type: 'range', value: 'low', amount: 1 },
|
|
34
|
+
dozen: { type: 'dozen', value: '1', amount: 1 },
|
|
35
|
+
column: { type: 'column', value: '2', amount: 1 }
|
|
36
|
+
};
|
|
37
|
+
exports.MONTE_CARLO_TARGETS = [
|
|
38
|
+
'dice',
|
|
39
|
+
'coinflip',
|
|
40
|
+
'slots',
|
|
41
|
+
'lottery',
|
|
42
|
+
'plinko',
|
|
43
|
+
'goldenJackpot',
|
|
44
|
+
...ROULETTE_BET_TYPES.map((type) => `roulette:${type}`)
|
|
45
|
+
];
|
|
46
|
+
const drawUnique = (count, max) => {
|
|
47
|
+
const pool = Array.from({ length: max }, (_, index) => index + 1);
|
|
48
|
+
const picks = [];
|
|
49
|
+
for (let i = 0; i < count; i++) {
|
|
50
|
+
const index = Math.floor(Math.random() * pool.length);
|
|
51
|
+
picks.push(pool[index]);
|
|
52
|
+
pool.splice(index, 1);
|
|
53
|
+
}
|
|
54
|
+
return picks;
|
|
55
|
+
};
|
|
56
|
+
const pickWeightedSymbol = (weights) => {
|
|
57
|
+
const entries = Object.entries(weights);
|
|
58
|
+
const total = entries.reduce((sum, [, weight]) => sum + toNumber(weight), 0);
|
|
59
|
+
let roll = Math.random() * total;
|
|
60
|
+
let selected = entries[entries.length - 1]?.[0] ?? '';
|
|
61
|
+
for (const [symbol, weight] of entries) {
|
|
62
|
+
roll -= toNumber(weight);
|
|
63
|
+
if (roll <= 0) {
|
|
64
|
+
selected = symbol;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return selected;
|
|
69
|
+
};
|
|
70
|
+
const spinSlots = (settings) => {
|
|
71
|
+
const combo = Array.from({ length: 3 }, () => pickWeightedSymbol(settings.symbolWeights)).join('');
|
|
72
|
+
return toNumber(settings.winMultipliers[combo] ?? 0);
|
|
73
|
+
};
|
|
74
|
+
const spinRoulette = () => ROULETTE_NUMBERS[Math.floor(Math.random() * ROULETTE_NUMBERS.length)];
|
|
75
|
+
const simulateRound = (target, settings) => {
|
|
76
|
+
switch (target) {
|
|
77
|
+
case 'dice': {
|
|
78
|
+
const rolled = Math.floor(Math.random() * 6) + 1;
|
|
79
|
+
const guessed = Math.floor(Math.random() * 6) + 1;
|
|
80
|
+
return {
|
|
81
|
+
multiplier: rolled === guessed ? toNumber(settings.dice.winMultiplier) : 0
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
case 'coinflip': {
|
|
85
|
+
const flipped = Math.random() < 0.5 ? 'heads' : 'tails';
|
|
86
|
+
const picked = Math.random() < 0.5 ? 'heads' : 'tails';
|
|
87
|
+
return {
|
|
88
|
+
multiplier: flipped === picked ? toNumber(settings.coinflip.winMultiplier) : 0
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
case 'slots':
|
|
92
|
+
return { multiplier: spinSlots(settings.slots) };
|
|
93
|
+
case 'lottery': {
|
|
94
|
+
const picks = drawUnique(lotteryConfig_1.LOTTERY_NUM_TO_DRAW, lotteryConfig_1.LOTTERY_TOTAL_NUMBERS);
|
|
95
|
+
const drawn = drawUnique(lotteryConfig_1.LOTTERY_NUM_TO_DRAW, lotteryConfig_1.LOTTERY_TOTAL_NUMBERS);
|
|
96
|
+
const matched = picks.filter((pick) => drawn.includes(pick)).length;
|
|
97
|
+
return {
|
|
98
|
+
multiplier: toNumber(settings.lottery.winMultipliers[matched] ?? 0),
|
|
99
|
+
bucket: String(matched)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
case 'plinko': {
|
|
103
|
+
let rights = 0;
|
|
104
|
+
for (let row = 0; row < plinkoConfig_1.PLINKO_ROW_COUNT; row++) {
|
|
105
|
+
if (Math.random() < 0.5)
|
|
106
|
+
rights++;
|
|
107
|
+
}
|
|
108
|
+
const multipliers = (0, plinkoConfig_2.normalizePlinkoBinMultipliers)(settings.plinko.binMultipliers);
|
|
109
|
+
return {
|
|
110
|
+
multiplier: (0, plinkoConfig_2.getPlinkoMultiplierAtPathIndex)(multipliers, rights),
|
|
111
|
+
bucket: String(rights)
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
case 'goldenJackpot': {
|
|
115
|
+
const chance = Math.max(1, toNumber(settings.goldenJackpot.oneInChance));
|
|
116
|
+
const won = Math.floor(Math.random() * chance) === 0;
|
|
117
|
+
return {
|
|
118
|
+
multiplier: won ? toNumber(settings.goldenJackpot.winMultiplier) : 0
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
default: {
|
|
122
|
+
const betType = target.replace('roulette:', '');
|
|
123
|
+
const result = spinRoulette();
|
|
124
|
+
return {
|
|
125
|
+
multiplier: (0, calculateRouletteWin_1.calculateRouletteWin)(ROULETTE_REP_BETS[betType], result, settings.roulette.winMultipliers)
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const getTheoreticalRtp = (target, settings) => {
|
|
131
|
+
if (target.startsWith('roulette:')) {
|
|
132
|
+
const betType = target.replace('roulette:', '');
|
|
133
|
+
const rtp = (0, calculateRTP_1.calculateRTP)('roulette', settings.roulette);
|
|
134
|
+
if (typeof rtp !== 'object')
|
|
135
|
+
return null;
|
|
136
|
+
return rtp[betType] ?? null;
|
|
137
|
+
}
|
|
138
|
+
const game = target;
|
|
139
|
+
const rtp = (0, calculateRTP_1.calculateRTP)(game, settings[game]);
|
|
140
|
+
return typeof rtp === 'number' ? rtp : null;
|
|
141
|
+
};
|
|
142
|
+
const targetLabel = (target) => {
|
|
143
|
+
if (target.startsWith('roulette:')) {
|
|
144
|
+
return `Roulette · ${target.replace('roulette:', '')}`;
|
|
145
|
+
}
|
|
146
|
+
const labels = {
|
|
147
|
+
dice: 'Dice',
|
|
148
|
+
coinflip: 'Coin flip',
|
|
149
|
+
slots: 'Slots',
|
|
150
|
+
lottery: 'Lottery',
|
|
151
|
+
plinko: 'Plinko',
|
|
152
|
+
goldenJackpot: 'Golden jackpot'
|
|
153
|
+
};
|
|
154
|
+
return labels[target];
|
|
155
|
+
};
|
|
156
|
+
async function runMonteCarloSimulation(target, settings, iterations, onProgress, chunkSize = 25000) {
|
|
157
|
+
const started = performance.now();
|
|
158
|
+
let totalMultiplier = 0;
|
|
159
|
+
const distribution = {};
|
|
160
|
+
let completed = 0;
|
|
161
|
+
while (completed < iterations) {
|
|
162
|
+
const batch = Math.min(chunkSize, iterations - completed);
|
|
163
|
+
for (let i = 0; i < batch; i++) {
|
|
164
|
+
const round = simulateRound(target, settings);
|
|
165
|
+
totalMultiplier += round.multiplier;
|
|
166
|
+
if (round.bucket) {
|
|
167
|
+
distribution[round.bucket] = (distribution[round.bucket] ?? 0) + 1;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
completed += batch;
|
|
171
|
+
onProgress?.(completed, iterations);
|
|
172
|
+
await (0, yieldToEventLoop_1.yieldToEventLoop)();
|
|
173
|
+
}
|
|
174
|
+
const empiricalRtp = (totalMultiplier / iterations) * 100;
|
|
175
|
+
const theoreticalRtp = getTheoreticalRtp(target, settings);
|
|
176
|
+
const delta = theoreticalRtp == null ? null : empiricalRtp - theoreticalRtp;
|
|
177
|
+
return {
|
|
178
|
+
target,
|
|
179
|
+
label: targetLabel(target),
|
|
180
|
+
iterations,
|
|
181
|
+
theoreticalRtp,
|
|
182
|
+
empiricalRtp,
|
|
183
|
+
delta,
|
|
184
|
+
elapsedMs: Math.round(performance.now() - started),
|
|
185
|
+
distribution: Object.keys(distribution).length > 0 ? distribution : undefined
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
async function runAllMonteCarloSimulations(settings, iterations, onProgress) {
|
|
189
|
+
const results = [];
|
|
190
|
+
const total = exports.MONTE_CARLO_TARGETS.length;
|
|
191
|
+
for (let index = 0; index < exports.MONTE_CARLO_TARGETS.length; index++) {
|
|
192
|
+
const target = exports.MONTE_CARLO_TARGETS[index];
|
|
193
|
+
const result = await runMonteCarloSimulation(target, settings, iterations, (completed, targetIterations) => {
|
|
194
|
+
onProgress?.(index + completed / targetIterations, total);
|
|
195
|
+
});
|
|
196
|
+
results.push(result);
|
|
197
|
+
}
|
|
198
|
+
onProgress?.(total, total);
|
|
199
|
+
return results;
|
|
200
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Discord guild IDs where dev tooling is enabled for all guild members. */
|
|
2
|
+
export declare const DEV_GUILDS: string[];
|
|
3
|
+
/** Discord user IDs allowed to use dev tooling outside dev guilds. */
|
|
4
|
+
export declare const DEV_USERS: string[];
|
|
5
|
+
export declare function hasDevAccess(userId: string, guildId: string | null | undefined): boolean;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEV_USERS = exports.DEV_GUILDS = void 0;
|
|
4
|
+
exports.hasDevAccess = hasDevAccess;
|
|
5
|
+
/** Discord guild IDs where dev tooling is enabled for all guild members. */
|
|
6
|
+
exports.DEV_GUILDS = ['1298805664654561340'];
|
|
7
|
+
/** Discord user IDs allowed to use dev tooling outside dev guilds. */
|
|
8
|
+
exports.DEV_USERS = [];
|
|
9
|
+
function hasDevAccess(userId, guildId) {
|
|
10
|
+
if (guildId && exports.DEV_GUILDS.includes(guildId)) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return exports.DEV_USERS.includes(userId);
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./devAccess"), exports);
|
|
18
|
+
__exportStar(require("./bonusStressTest"), exports);
|
|
19
|
+
__exportStar(require("./casinoMonteCarlo"), exports);
|
|
20
|
+
__exportStar(require("./yieldToEventLoop"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const yieldToEventLoop: () => Promise<void>;
|
|
@@ -81,6 +81,15 @@ export declare const GuildConfigurationSchema: Schema<TGuildConfiguration, impor
|
|
|
81
81
|
}, "id"> & {
|
|
82
82
|
id: string;
|
|
83
83
|
}> | undefined;
|
|
84
|
+
bannedRoleId?: import("mongoose").SchemaDefinitionProperty<string, TGuildConfiguration, import("mongoose").Document<unknown, {}, TGuildConfiguration, {
|
|
85
|
+
id: string;
|
|
86
|
+
}, import("mongoose").DefaultSchemaOptions> & Omit<TGuildConfiguration & {
|
|
87
|
+
_id: import("mongoose").Types.ObjectId;
|
|
88
|
+
} & {
|
|
89
|
+
__v: number;
|
|
90
|
+
}, "id"> & {
|
|
91
|
+
id: string;
|
|
92
|
+
}> | undefined;
|
|
84
93
|
casinoSettings?: import("mongoose").SchemaDefinitionProperty<{
|
|
85
94
|
dice: {
|
|
86
95
|
winMultiplier: number;
|
|
@@ -53,6 +53,10 @@ exports.GuildConfigurationSchema = new mongoose_1.Schema({
|
|
|
53
53
|
type: String,
|
|
54
54
|
default: ''
|
|
55
55
|
},
|
|
56
|
+
bannedRoleId: {
|
|
57
|
+
type: String,
|
|
58
|
+
default: ''
|
|
59
|
+
},
|
|
56
60
|
casinoSettings: {
|
|
57
61
|
type: mongoose_1.Schema.Types.Mixed,
|
|
58
62
|
default: defaultConfig_1.defaultCasinoSettings
|
|
@@ -19,6 +19,7 @@ export declare const channelsFormSchema: z.ZodObject<{
|
|
|
19
19
|
}, z.core.$strip>;
|
|
20
20
|
export declare const managerRoleFormSchema: z.ZodObject<{
|
|
21
21
|
managerRoleId: z.ZodString;
|
|
22
|
+
bannedRoleId: z.ZodString;
|
|
22
23
|
}, z.core.$strip>;
|
|
23
24
|
export declare const globalSettingsFormSchema: z.ZodObject<{
|
|
24
25
|
disableRegistrations: z.ZodBoolean;
|
|
@@ -17,7 +17,8 @@ exports.channelsFormSchema = zod_1.default.object({
|
|
|
17
17
|
raffle: raffle_forms_1.raffleChannelsFormSchema
|
|
18
18
|
});
|
|
19
19
|
exports.managerRoleFormSchema = zod_1.default.object({
|
|
20
|
-
managerRoleId: zod_1.default.string()
|
|
20
|
+
managerRoleId: zod_1.default.string(),
|
|
21
|
+
bannedRoleId: zod_1.default.string()
|
|
21
22
|
});
|
|
22
23
|
exports.globalSettingsFormSchema = zod_1.default.object({
|
|
23
24
|
disableRegistrations: zod_1.default.boolean(),
|
|
@@ -8,7 +8,10 @@ export declare const STAFF_ADMIN_ACTIONS: {
|
|
|
8
8
|
readonly PREDICTION_PAYOUT: "prediction-payout";
|
|
9
9
|
readonly PREDICTION_CANCEL: "prediction-cancel";
|
|
10
10
|
readonly ATM_REJECT: "atm-reject";
|
|
11
|
+
readonly USER_BAN: "user-ban";
|
|
12
|
+
readonly USER_UNBAN: "user-unban";
|
|
13
|
+
readonly USER_NOTE: "user-note";
|
|
11
14
|
};
|
|
12
15
|
export type StaffAdminAction = (typeof STAFF_ADMIN_ACTIONS)[keyof typeof STAFF_ADMIN_ACTIONS];
|
|
13
|
-
export declare const STAFF_ACTION_CATEGORIES: readonly ["balance", "atm", "vip", "raffle", "prediction"];
|
|
16
|
+
export declare const STAFF_ACTION_CATEGORIES: readonly ["balance", "atm", "vip", "raffle", "prediction", "user"];
|
|
14
17
|
export type StaffActionCategory = (typeof STAFF_ACTION_CATEGORIES)[number];
|
|
@@ -10,12 +10,16 @@ exports.STAFF_ADMIN_ACTIONS = {
|
|
|
10
10
|
PREDICTION_END: 'prediction-end',
|
|
11
11
|
PREDICTION_PAYOUT: 'prediction-payout',
|
|
12
12
|
PREDICTION_CANCEL: 'prediction-cancel',
|
|
13
|
-
ATM_REJECT: 'atm-reject'
|
|
13
|
+
ATM_REJECT: 'atm-reject',
|
|
14
|
+
USER_BAN: 'user-ban',
|
|
15
|
+
USER_UNBAN: 'user-unban',
|
|
16
|
+
USER_NOTE: 'user-note'
|
|
14
17
|
};
|
|
15
18
|
exports.STAFF_ACTION_CATEGORIES = [
|
|
16
19
|
'balance',
|
|
17
20
|
'atm',
|
|
18
21
|
'vip',
|
|
19
22
|
'raffle',
|
|
20
|
-
'prediction'
|
|
23
|
+
'prediction',
|
|
24
|
+
'user'
|
|
21
25
|
];
|
package/dist/user/index.d.ts
CHANGED
package/dist/user/index.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
export type TUserStaffNote = {
|
|
2
|
+
text: string;
|
|
3
|
+
authorId: string;
|
|
4
|
+
createdAt: Date;
|
|
5
|
+
};
|
|
6
|
+
export type TUserBanHistoryEntry = {
|
|
7
|
+
bannedAt: Date;
|
|
8
|
+
bannedBy: string;
|
|
9
|
+
unbannedAt: Date | null;
|
|
10
|
+
unbannedBy: string | null;
|
|
11
|
+
reason?: string;
|
|
12
|
+
};
|
|
1
13
|
export type TUser = {
|
|
2
14
|
userId: string;
|
|
3
15
|
guildId: string;
|
|
@@ -6,6 +18,11 @@ export type TUser = {
|
|
|
6
18
|
lockedBalance: number;
|
|
7
19
|
lastDailyClaim: Date | null;
|
|
8
20
|
dailyStreak: number;
|
|
21
|
+
banned: boolean;
|
|
22
|
+
bannedAt: Date | null;
|
|
23
|
+
bannedBy: string | null;
|
|
24
|
+
banHistory: TUserBanHistoryEntry[];
|
|
25
|
+
staffNotes: TUserStaffNote[];
|
|
9
26
|
createdAt: Date;
|
|
10
27
|
updatedAt: Date;
|
|
11
28
|
};
|
|
@@ -72,6 +72,51 @@ export declare const UserSchema: Schema<TUser, import("mongoose").Model<TUser, a
|
|
|
72
72
|
}, "id"> & {
|
|
73
73
|
id: string;
|
|
74
74
|
}> | undefined;
|
|
75
|
+
banned?: import("mongoose").SchemaDefinitionProperty<boolean, TUser, import("mongoose").Document<unknown, {}, TUser, {
|
|
76
|
+
id: string;
|
|
77
|
+
}, import("mongoose").DefaultSchemaOptions> & Omit<TUser & {
|
|
78
|
+
_id: import("mongoose").Types.ObjectId;
|
|
79
|
+
} & {
|
|
80
|
+
__v: number;
|
|
81
|
+
}, "id"> & {
|
|
82
|
+
id: string;
|
|
83
|
+
}> | undefined;
|
|
84
|
+
bannedAt?: import("mongoose").SchemaDefinitionProperty<Date | null, TUser, import("mongoose").Document<unknown, {}, TUser, {
|
|
85
|
+
id: string;
|
|
86
|
+
}, import("mongoose").DefaultSchemaOptions> & Omit<TUser & {
|
|
87
|
+
_id: import("mongoose").Types.ObjectId;
|
|
88
|
+
} & {
|
|
89
|
+
__v: number;
|
|
90
|
+
}, "id"> & {
|
|
91
|
+
id: string;
|
|
92
|
+
}> | undefined;
|
|
93
|
+
bannedBy?: import("mongoose").SchemaDefinitionProperty<string | null, TUser, import("mongoose").Document<unknown, {}, TUser, {
|
|
94
|
+
id: string;
|
|
95
|
+
}, import("mongoose").DefaultSchemaOptions> & Omit<TUser & {
|
|
96
|
+
_id: import("mongoose").Types.ObjectId;
|
|
97
|
+
} & {
|
|
98
|
+
__v: number;
|
|
99
|
+
}, "id"> & {
|
|
100
|
+
id: string;
|
|
101
|
+
}> | undefined;
|
|
102
|
+
banHistory?: import("mongoose").SchemaDefinitionProperty<import("./types/user").TUserBanHistoryEntry[], TUser, import("mongoose").Document<unknown, {}, TUser, {
|
|
103
|
+
id: string;
|
|
104
|
+
}, import("mongoose").DefaultSchemaOptions> & Omit<TUser & {
|
|
105
|
+
_id: import("mongoose").Types.ObjectId;
|
|
106
|
+
} & {
|
|
107
|
+
__v: number;
|
|
108
|
+
}, "id"> & {
|
|
109
|
+
id: string;
|
|
110
|
+
}> | undefined;
|
|
111
|
+
staffNotes?: import("mongoose").SchemaDefinitionProperty<import("./types/user").TUserStaffNote[], TUser, import("mongoose").Document<unknown, {}, TUser, {
|
|
112
|
+
id: string;
|
|
113
|
+
}, import("mongoose").DefaultSchemaOptions> & Omit<TUser & {
|
|
114
|
+
_id: import("mongoose").Types.ObjectId;
|
|
115
|
+
} & {
|
|
116
|
+
__v: number;
|
|
117
|
+
}, "id"> & {
|
|
118
|
+
id: string;
|
|
119
|
+
}> | undefined;
|
|
75
120
|
createdAt?: import("mongoose").SchemaDefinitionProperty<Date, TUser, import("mongoose").Document<unknown, {}, TUser, {
|
|
76
121
|
id: string;
|
|
77
122
|
}, import("mongoose").DefaultSchemaOptions> & Omit<TUser & {
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UserSchema = void 0;
|
|
4
4
|
const mongoose_1 = require("mongoose");
|
|
5
|
+
const UserStaffNoteSchema = new mongoose_1.Schema({
|
|
6
|
+
text: { type: String, required: true },
|
|
7
|
+
authorId: { type: String, required: true },
|
|
8
|
+
createdAt: { type: Date, required: true }
|
|
9
|
+
}, { _id: false });
|
|
10
|
+
const UserBanHistoryEntrySchema = new mongoose_1.Schema({
|
|
11
|
+
bannedAt: { type: Date, required: true },
|
|
12
|
+
bannedBy: { type: String, required: true },
|
|
13
|
+
unbannedAt: { type: Date, default: null },
|
|
14
|
+
unbannedBy: { type: String, default: null },
|
|
15
|
+
reason: { type: String }
|
|
16
|
+
}, { _id: false });
|
|
5
17
|
exports.UserSchema = new mongoose_1.Schema({
|
|
6
18
|
userId: { type: String, required: true },
|
|
7
19
|
guildId: { type: String, required: true },
|
|
@@ -9,6 +21,11 @@ exports.UserSchema = new mongoose_1.Schema({
|
|
|
9
21
|
bonusBalance: { type: Number, default: 0 }, // BONUS (non-withdrawable)
|
|
10
22
|
lockedBalance: { type: Number, default: 0 }, // ONLY for in-flight bets
|
|
11
23
|
lastDailyClaim: { type: Date, default: null },
|
|
12
|
-
dailyStreak: { type: Number, default: 0 }
|
|
24
|
+
dailyStreak: { type: Number, default: 0 },
|
|
25
|
+
banned: { type: Boolean, default: false },
|
|
26
|
+
bannedAt: { type: Date, default: null },
|
|
27
|
+
bannedBy: { type: String, default: null },
|
|
28
|
+
banHistory: { type: [UserBanHistoryEntrySchema], default: [] },
|
|
29
|
+
staffNotes: { type: [UserStaffNoteSchema], default: [] }
|
|
13
30
|
}, { timestamps: true });
|
|
14
31
|
exports.UserSchema.index({ userId: 1, guildId: 1 }, { unique: true });
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TUser, TUserBanHistoryEntry, TUserStaffNote } from '../types/user';
|
|
2
|
+
export declare const USER_BANNED_ERROR = "USER_BANNED";
|
|
3
|
+
export declare const USER_BANNED_MESSAGE = "Your account is restricted. Contact server staff.";
|
|
4
|
+
export declare function isUserBanned(user: Pick<TUser, 'banned'>): boolean;
|
|
5
|
+
export declare function normalizeStaffNote(text: string): string | null;
|
|
6
|
+
export declare function appendStaffNote(notes: TUserStaffNote[], entry: TUserStaffNote, maxNotes?: number): TUserStaffNote[];
|
|
7
|
+
export declare function startBanHistoryEntry({ history, bannedBy, reason, maxEntries }: {
|
|
8
|
+
history: TUserBanHistoryEntry[];
|
|
9
|
+
bannedBy: string;
|
|
10
|
+
reason?: string;
|
|
11
|
+
maxEntries?: number;
|
|
12
|
+
}): TUserBanHistoryEntry[];
|
|
13
|
+
export declare function closeLatestBanHistoryEntry({ history, unbannedBy }: {
|
|
14
|
+
history: TUserBanHistoryEntry[];
|
|
15
|
+
unbannedBy: string;
|
|
16
|
+
}): TUserBanHistoryEntry[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.USER_BANNED_MESSAGE = exports.USER_BANNED_ERROR = void 0;
|
|
4
|
+
exports.isUserBanned = isUserBanned;
|
|
5
|
+
exports.normalizeStaffNote = normalizeStaffNote;
|
|
6
|
+
exports.appendStaffNote = appendStaffNote;
|
|
7
|
+
exports.startBanHistoryEntry = startBanHistoryEntry;
|
|
8
|
+
exports.closeLatestBanHistoryEntry = closeLatestBanHistoryEntry;
|
|
9
|
+
exports.USER_BANNED_ERROR = 'USER_BANNED';
|
|
10
|
+
exports.USER_BANNED_MESSAGE = 'Your account is restricted. Contact server staff.';
|
|
11
|
+
function isUserBanned(user) {
|
|
12
|
+
return Boolean(user.banned);
|
|
13
|
+
}
|
|
14
|
+
function normalizeStaffNote(text) {
|
|
15
|
+
const trimmed = text.trim();
|
|
16
|
+
if (!trimmed)
|
|
17
|
+
return null;
|
|
18
|
+
return trimmed.slice(0, 500);
|
|
19
|
+
}
|
|
20
|
+
function appendStaffNote(notes, entry, maxNotes = 50) {
|
|
21
|
+
return [entry, ...notes].slice(0, maxNotes);
|
|
22
|
+
}
|
|
23
|
+
function startBanHistoryEntry({ history, bannedBy, reason, maxEntries = 50 }) {
|
|
24
|
+
const entry = {
|
|
25
|
+
bannedAt: new Date(),
|
|
26
|
+
bannedBy,
|
|
27
|
+
unbannedAt: null,
|
|
28
|
+
unbannedBy: null,
|
|
29
|
+
...(reason ? { reason } : {})
|
|
30
|
+
};
|
|
31
|
+
return [entry, ...history].slice(0, maxEntries);
|
|
32
|
+
}
|
|
33
|
+
function closeLatestBanHistoryEntry({ history, unbannedBy }) {
|
|
34
|
+
const openIndex = history.findIndex((entry) => entry.unbannedAt === null);
|
|
35
|
+
if (openIndex === -1)
|
|
36
|
+
return history;
|
|
37
|
+
const updated = [...history];
|
|
38
|
+
updated[openIndex] = {
|
|
39
|
+
...updated[openIndex],
|
|
40
|
+
unbannedAt: new Date(),
|
|
41
|
+
unbannedBy
|
|
42
|
+
};
|
|
43
|
+
return updated;
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gambling-bot-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"repository": {
|
|
@@ -58,6 +58,10 @@
|
|
|
58
58
|
"./mongoose": {
|
|
59
59
|
"types": "./dist/mongoose/index.d.ts",
|
|
60
60
|
"default": "./dist/mongoose/index.js"
|
|
61
|
+
},
|
|
62
|
+
"./dev": {
|
|
63
|
+
"types": "./dist/dev/index.d.ts",
|
|
64
|
+
"default": "./dist/dev/index.js"
|
|
61
65
|
}
|
|
62
66
|
},
|
|
63
67
|
"scripts": {
|