Codex commited on
Commit
84c1610
·
1 Parent(s): 646b326

Add Cockroach schema backfill

Browse files
Files changed (2) hide show
  1. src/db.js +72 -0
  2. src/index.js +18 -17
src/db.js CHANGED
@@ -42,6 +42,26 @@ export class BetStore {
42
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
43
  );
44
  `);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  await this.pool.query(`
47
  CREATE TABLE IF NOT EXISTS bets (
@@ -61,6 +81,58 @@ export class BetStore {
61
  CONSTRAINT bets_user_bet_number_unique UNIQUE (discord_user_id, bet_number)
62
  );
63
  `);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
 
66
  async createBet(user, bet) {
 
42
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
43
  );
44
  `);
45
+ await this.pool.query(`
46
+ ALTER TABLE users
47
+ ADD COLUMN IF NOT EXISTS username TEXT NOT NULL DEFAULT '';
48
+ `);
49
+ await this.pool.query(`
50
+ ALTER TABLE users
51
+ ADD COLUMN IF NOT EXISTS display_name TEXT NOT NULL DEFAULT '';
52
+ `);
53
+ await this.pool.query(`
54
+ ALTER TABLE users
55
+ ADD COLUMN IF NOT EXISTS next_bet_number INT NOT NULL DEFAULT 1;
56
+ `);
57
+ await this.pool.query(`
58
+ ALTER TABLE users
59
+ ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT NOW();
60
+ `);
61
+ await this.pool.query(`
62
+ ALTER TABLE users
63
+ ADD COLUMN IF NOT EXISTS updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW();
64
+ `);
65
 
66
  await this.pool.query(`
67
  CREATE TABLE IF NOT EXISTS bets (
 
81
  CONSTRAINT bets_user_bet_number_unique UNIQUE (discord_user_id, bet_number)
82
  );
83
  `);
84
+ await this.pool.query(`
85
+ ALTER TABLE bets
86
+ ADD COLUMN IF NOT EXISTS discord_user_id TEXT;
87
+ `);
88
+ await this.pool.query(`
89
+ ALTER TABLE bets
90
+ ADD COLUMN IF NOT EXISTS bet_number INT;
91
+ `);
92
+ await this.pool.query(`
93
+ ALTER TABLE bets
94
+ ADD COLUMN IF NOT EXISTS book TEXT;
95
+ `);
96
+ await this.pool.query(`
97
+ ALTER TABLE bets
98
+ ADD COLUMN IF NOT EXISTS odds_input TEXT;
99
+ `);
100
+ await this.pool.query(`
101
+ ALTER TABLE bets
102
+ ADD COLUMN IF NOT EXISTS normalized_decimal_odds DOUBLE PRECISION;
103
+ `);
104
+ await this.pool.query(`
105
+ ALTER TABLE bets
106
+ ADD COLUMN IF NOT EXISTS prop TEXT;
107
+ `);
108
+ await this.pool.query(`
109
+ ALTER TABLE bets
110
+ ADD COLUMN IF NOT EXISTS stake DOUBLE PRECISION;
111
+ `);
112
+ await this.pool.query(`
113
+ ALTER TABLE bets
114
+ ADD COLUMN IF NOT EXISTS status TEXT NOT NULL DEFAULT 'open';
115
+ `);
116
+ await this.pool.query(`
117
+ ALTER TABLE bets
118
+ ADD COLUMN IF NOT EXISTS profit_loss DOUBLE PRECISION;
119
+ `);
120
+ await this.pool.query(`
121
+ ALTER TABLE bets
122
+ ADD COLUMN IF NOT EXISTS raw_input TEXT;
123
+ `);
124
+ await this.pool.query(`
125
+ ALTER TABLE bets
126
+ ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT NOW();
127
+ `);
128
+ await this.pool.query(`
129
+ ALTER TABLE bets
130
+ ADD COLUMN IF NOT EXISTS resolved_at TIMESTAMPTZ;
131
+ `);
132
+ await this.pool.query(`
133
+ CREATE UNIQUE INDEX IF NOT EXISTS bets_user_bet_number_unique
134
+ ON bets (discord_user_id, bet_number);
135
+ `);
136
  }
137
 
138
  async createBet(user, bet) {
src/index.js CHANGED
@@ -4,6 +4,7 @@ import {
4
  Client,
5
  Events,
6
  GatewayIntentBits,
 
7
  ModalBuilder,
8
  TextInputBuilder,
9
  TextInputStyle,
@@ -75,13 +76,13 @@ async function main() {
75
  console.error(error);
76
  const payload = {
77
  embeds: [
78
- buildErrorEmbed(
79
- 'Something went wrong',
80
- 'The bot hit an unexpected error while handling that request.'
81
- ),
82
- ],
83
- ephemeral: true,
84
- };
85
 
86
  if (interaction.replied || interaction.deferred) {
87
  await interaction.followUp(payload).catch(() => null);
@@ -201,7 +202,7 @@ async function handleBetModal(interaction, store) {
201
  `I still need valid values for: **${parsed.missingFields.join(', ')}**.\n\nAccepted odds: \`-110\`, \`+150\`, or decimal like \`1.91\`.\nAccepted stake examples: \`25\` or \`$25\`.`
202
  ),
203
  ],
204
- ephemeral: true,
205
  });
206
  return;
207
  }
@@ -210,7 +211,7 @@ async function handleBetModal(interaction, store) {
210
  const savedBet = await store.createBet(interaction.user, parsed.bet);
211
  await interaction.reply({
212
  embeds: [buildBetSavedEmbed(savedBet)],
213
- ephemeral: true,
214
  });
215
  } catch (error) {
216
  console.error('Failed to create bet', {
@@ -227,7 +228,7 @@ async function handleBetModal(interaction, store) {
227
  'The bet looked valid, but the database rejected it. Check the Space logs for the detailed error and try again.'
228
  ),
229
  ],
230
- ephemeral: true,
231
  });
232
  }
233
  }
@@ -240,7 +241,7 @@ async function handleResolve(interaction, store) {
240
  if (resolution.type === 'missing') {
241
  await interaction.reply({
242
  embeds: [buildErrorEmbed('Bet not found', `I could not find your bet #${betId}.`)],
243
- ephemeral: true,
244
  });
245
  return;
246
  }
@@ -253,14 +254,14 @@ async function handleResolve(interaction, store) {
253
  `Bet #${betId} is already marked as **${resolution.bet.status}**.`
254
  ),
255
  ],
256
- ephemeral: true,
257
  });
258
  return;
259
  }
260
 
261
  await interaction.reply({
262
  embeds: [buildResolveEmbed(resolution.bet)],
263
- ephemeral: true,
264
  });
265
  }
266
 
@@ -275,7 +276,7 @@ async function handleRoi(interaction, store) {
275
  await interaction.reply({
276
  embeds: [embed],
277
  files: [chart],
278
- ephemeral: true,
279
  });
280
  }
281
 
@@ -285,7 +286,7 @@ async function handleBets(interaction, store) {
285
 
286
  await interaction.reply({
287
  embeds: [buildBetsEmbed(summary, bets)],
288
- ephemeral: true,
289
  });
290
  }
291
 
@@ -300,7 +301,7 @@ async function handleSummary(interaction, store) {
300
  await interaction.reply({
301
  embeds: [embed],
302
  files: [chart],
303
- ephemeral: true,
304
  });
305
  }
306
 
@@ -313,7 +314,7 @@ async function handleWelcome(interaction, config) {
313
  'Only the configured welcome manager can use this command.'
314
  ),
315
  ],
316
- ephemeral: true,
317
  });
318
  return;
319
  }
 
4
  Client,
5
  Events,
6
  GatewayIntentBits,
7
+ MessageFlags,
8
  ModalBuilder,
9
  TextInputBuilder,
10
  TextInputStyle,
 
76
  console.error(error);
77
  const payload = {
78
  embeds: [
79
+ buildErrorEmbed(
80
+ 'Something went wrong',
81
+ 'The bot hit an unexpected error while handling that request.'
82
+ ),
83
+ ],
84
+ flags: MessageFlags.Ephemeral,
85
+ };
86
 
87
  if (interaction.replied || interaction.deferred) {
88
  await interaction.followUp(payload).catch(() => null);
 
202
  `I still need valid values for: **${parsed.missingFields.join(', ')}**.\n\nAccepted odds: \`-110\`, \`+150\`, or decimal like \`1.91\`.\nAccepted stake examples: \`25\` or \`$25\`.`
203
  ),
204
  ],
205
+ flags: MessageFlags.Ephemeral,
206
  });
207
  return;
208
  }
 
211
  const savedBet = await store.createBet(interaction.user, parsed.bet);
212
  await interaction.reply({
213
  embeds: [buildBetSavedEmbed(savedBet)],
214
+ flags: MessageFlags.Ephemeral,
215
  });
216
  } catch (error) {
217
  console.error('Failed to create bet', {
 
228
  'The bet looked valid, but the database rejected it. Check the Space logs for the detailed error and try again.'
229
  ),
230
  ],
231
+ flags: MessageFlags.Ephemeral,
232
  });
233
  }
234
  }
 
241
  if (resolution.type === 'missing') {
242
  await interaction.reply({
243
  embeds: [buildErrorEmbed('Bet not found', `I could not find your bet #${betId}.`)],
244
+ flags: MessageFlags.Ephemeral,
245
  });
246
  return;
247
  }
 
254
  `Bet #${betId} is already marked as **${resolution.bet.status}**.`
255
  ),
256
  ],
257
+ flags: MessageFlags.Ephemeral,
258
  });
259
  return;
260
  }
261
 
262
  await interaction.reply({
263
  embeds: [buildResolveEmbed(resolution.bet)],
264
+ flags: MessageFlags.Ephemeral,
265
  });
266
  }
267
 
 
276
  await interaction.reply({
277
  embeds: [embed],
278
  files: [chart],
279
+ flags: MessageFlags.Ephemeral,
280
  });
281
  }
282
 
 
286
 
287
  await interaction.reply({
288
  embeds: [buildBetsEmbed(summary, bets)],
289
+ flags: MessageFlags.Ephemeral,
290
  });
291
  }
292
 
 
301
  await interaction.reply({
302
  embeds: [embed],
303
  files: [chart],
304
+ flags: MessageFlags.Ephemeral,
305
  });
306
  }
307
 
 
314
  'Only the configured welcome manager can use this command.'
315
  ),
316
  ],
317
+ flags: MessageFlags.Ephemeral,
318
  });
319
  return;
320
  }