Codex commited on
Commit
8a812eb
·
1 Parent(s): 07c4ad7

Add Circa button pagination and odds sorting

Browse files
Files changed (2) hide show
  1. src/embeds.js +58 -1
  2. src/index.js +56 -16
src/embeds.js CHANGED
@@ -540,7 +540,15 @@ function chunkTextPages(lines, maxLength = 3400) {
540
  }
541
 
542
  export function buildCircaMarketEmbeds(snapshot, marketLabel, entries, options = {}) {
543
- const displayEntries = entries.filter((entry) => entry.side !== 'no');
 
 
 
 
 
 
 
 
544
  const lines = displayEntries.map((entry) => {
545
  const team = entry.team ? ` (${entry.team})` : '';
546
  const side = `${String(entry.side ?? '').toUpperCase()}${entry.lineValue !== null && entry.lineValue !== undefined ? ` ${entry.lineValue}` : ''}`;
@@ -565,6 +573,55 @@ export function buildCircaMarketEmbeds(snapshot, marketLabel, entries, options =
565
  );
566
  }
567
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  export function buildCircaMovementEmbed(movement, snapshot) {
569
  return new EmbedBuilder()
570
  .setColor(PALETTE.blue)
 
540
  }
541
 
542
  export function buildCircaMarketEmbeds(snapshot, marketLabel, entries, options = {}) {
543
+ const displayEntries = [...entries]
544
+ .filter((entry) => entry.side !== 'no')
545
+ .sort((left, right) => {
546
+ const leftOdds = Number(left.oddsInput);
547
+ const rightOdds = Number(right.oddsInput);
548
+ const leftValue = Number.isFinite(leftOdds) ? leftOdds : Number.MAX_SAFE_INTEGER;
549
+ const rightValue = Number.isFinite(rightOdds) ? rightOdds : Number.MAX_SAFE_INTEGER;
550
+ return leftValue - rightValue || left.playerName.localeCompare(right.playerName);
551
+ });
552
  const lines = displayEntries.map((entry) => {
553
  const team = entry.team ? ` (${entry.team})` : '';
554
  const side = `${String(entry.side ?? '').toUpperCase()}${entry.lineValue !== null && entry.lineValue !== undefined ? ` ${entry.lineValue}` : ''}`;
 
573
  );
574
  }
575
 
576
+ export function buildCircaPageId({ userId, marketType, totalPages }, page) {
577
+ return [
578
+ 'circa-page',
579
+ userId,
580
+ marketType,
581
+ page,
582
+ totalPages,
583
+ ].join('|');
584
+ }
585
+
586
+ export function parseCircaPageId(customId) {
587
+ const [prefix, userId, marketType, pageText, totalPagesText] = String(customId ?? '').split('|');
588
+ if (prefix !== 'circa-page' || !userId || !marketType) {
589
+ return null;
590
+ }
591
+
592
+ const page = Number(pageText);
593
+ const totalPages = Number(totalPagesText);
594
+ if (!Number.isInteger(page) || !Number.isInteger(totalPages)) {
595
+ return null;
596
+ }
597
+
598
+ return {
599
+ userId,
600
+ marketType,
601
+ page,
602
+ totalPages,
603
+ };
604
+ }
605
+
606
+ export function buildCircaPaginationRow(state) {
607
+ if (!state || state.totalPages <= 1) {
608
+ return null;
609
+ }
610
+
611
+ return new ActionRowBuilder().addComponents(
612
+ new ButtonBuilder()
613
+ .setCustomId(buildCircaPageId(state, Math.max(1, state.page - 1)))
614
+ .setLabel('Prev')
615
+ .setStyle(ButtonStyle.Secondary)
616
+ .setDisabled(state.page <= 1),
617
+ new ButtonBuilder()
618
+ .setCustomId(buildCircaPageId(state, Math.min(state.totalPages, state.page + 1)))
619
+ .setLabel('Next')
620
+ .setStyle(ButtonStyle.Secondary)
621
+ .setDisabled(state.page >= state.totalPages),
622
+ );
623
+ }
624
+
625
  export function buildCircaMovementEmbed(movement, snapshot) {
626
  return new EmbedBuilder()
627
  .setColor(PALETTE.blue)
src/index.js CHANGED
@@ -36,6 +36,7 @@ import {
36
  buildCircaAlertEmbed,
37
  buildCircaFailureEmbed,
38
  buildCircaMarketEmbeds,
 
39
  buildDeleteBetEmbed,
40
  buildEditBetEmbed,
41
  buildErrorEmbed,
@@ -51,6 +52,7 @@ import {
51
  parseAlertRoleButtonId,
52
  buildBetsPageId,
53
  parseBetsPageId,
 
54
  } from './embeds.js';
55
  import { parseBulkAddInput } from './bulk-add.js';
56
  import { parseBetIdList } from './resolve-bulk.js';
@@ -1002,15 +1004,16 @@ async function handleCircaShortcut(interaction, config, marketType) {
1002
  const embeds = buildCircaMarketEmbeds(market.snapshot, market.marketLabel, market.entries, {
1003
  footerText: `Manual Circa view requested by ${interaction.user.displayName ?? interaction.user.username}`,
1004
  });
 
 
 
 
 
 
1005
  await interaction.editReply({
1006
  embeds: [embeds[0]],
 
1007
  });
1008
-
1009
- for (let index = 1; index < embeds.length; index += 1) {
1010
- await interaction.followUp({
1011
- embeds: [embeds[index]],
1012
- });
1013
- }
1014
  } catch (error) {
1015
  await interaction.editReply({
1016
  embeds: [buildErrorEmbed('Circa market unavailable', error.message || 'The Circa market lookup hit an unexpected error.')],
@@ -1026,25 +1029,62 @@ async function handleButton(interaction, store) {
1026
  }
1027
 
1028
  const pageState = parseBetsPageId(interaction.customId);
1029
- if (!pageState) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1030
  return;
1031
  }
1032
 
1033
- if (pageState.userId !== interaction.user.id) {
 
 
 
 
 
1034
  await interaction.reply({
1035
- embeds: [buildErrorEmbed('Not your pager', 'Only the original user can turn pages on this bet ledger view.')],
1036
  flags: MessageFlags.Ephemeral,
1037
  });
1038
  return;
1039
  }
1040
 
1041
- interaction.__betsFilters = {
1042
- dateWindow: pageState.dateWindow,
1043
- book: pageState.book,
1044
- sport: pageState.sport,
1045
- status: pageState.status,
1046
- };
1047
- await handleBets(interaction, store, pageState.page, true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1048
  }
1049
 
1050
  async function handleAlertRoleToggle(interaction, roleName) {
 
36
  buildCircaAlertEmbed,
37
  buildCircaFailureEmbed,
38
  buildCircaMarketEmbeds,
39
+ buildCircaPaginationRow,
40
  buildDeleteBetEmbed,
41
  buildEditBetEmbed,
42
  buildErrorEmbed,
 
52
  parseAlertRoleButtonId,
53
  buildBetsPageId,
54
  parseBetsPageId,
55
+ parseCircaPageId,
56
  } from './embeds.js';
57
  import { parseBulkAddInput } from './bulk-add.js';
58
  import { parseBetIdList } from './resolve-bulk.js';
 
1004
  const embeds = buildCircaMarketEmbeds(market.snapshot, market.marketLabel, market.entries, {
1005
  footerText: `Manual Circa view requested by ${interaction.user.displayName ?? interaction.user.username}`,
1006
  });
1007
+ const paginationRow = buildCircaPaginationRow({
1008
+ userId: interaction.user.id,
1009
+ marketType,
1010
+ page: 1,
1011
+ totalPages: embeds.length,
1012
+ });
1013
  await interaction.editReply({
1014
  embeds: [embeds[0]],
1015
+ components: paginationRow ? [paginationRow] : [],
1016
  });
 
 
 
 
 
 
1017
  } catch (error) {
1018
  await interaction.editReply({
1019
  embeds: [buildErrorEmbed('Circa market unavailable', error.message || 'The Circa market lookup hit an unexpected error.')],
 
1029
  }
1030
 
1031
  const pageState = parseBetsPageId(interaction.customId);
1032
+ if (pageState) {
1033
+ if (pageState.userId !== interaction.user.id) {
1034
+ await interaction.reply({
1035
+ embeds: [buildErrorEmbed('Not your pager', 'Only the original user can turn pages on this bet ledger view.')],
1036
+ flags: MessageFlags.Ephemeral,
1037
+ });
1038
+ return;
1039
+ }
1040
+
1041
+ interaction.__betsFilters = {
1042
+ dateWindow: pageState.dateWindow,
1043
+ book: pageState.book,
1044
+ sport: pageState.sport,
1045
+ status: pageState.status,
1046
+ };
1047
+ await handleBets(interaction, store, pageState.page, true);
1048
  return;
1049
  }
1050
 
1051
+ const circaPageState = parseCircaPageId(interaction.customId);
1052
+ if (!circaPageState) {
1053
+ return;
1054
+ }
1055
+
1056
+ if (circaPageState.userId !== interaction.user.id) {
1057
  await interaction.reply({
1058
+ embeds: [buildErrorEmbed('Not your pager', 'Only the original user can turn pages on this Circa market view.')],
1059
  flags: MessageFlags.Ephemeral,
1060
  });
1061
  return;
1062
  }
1063
 
1064
+ const scanner = interaction.client.__marketScanner;
1065
+ try {
1066
+ const market = await scanner.getLatestCircaMarket(circaPageState.marketType);
1067
+ const embeds = buildCircaMarketEmbeds(market.snapshot, market.marketLabel, market.entries, {
1068
+ footerText: `Manual Circa view requested by ${interaction.user.displayName ?? interaction.user.username}`,
1069
+ });
1070
+ const safePage = Math.max(1, Math.min(circaPageState.page, embeds.length));
1071
+ const paginationRow = buildCircaPaginationRow({
1072
+ userId: interaction.user.id,
1073
+ marketType: circaPageState.marketType,
1074
+ page: safePage,
1075
+ totalPages: embeds.length,
1076
+ });
1077
+
1078
+ await interaction.update({
1079
+ embeds: [embeds[safePage - 1]],
1080
+ components: paginationRow ? [paginationRow] : [],
1081
+ });
1082
+ } catch (error) {
1083
+ await interaction.reply({
1084
+ embeds: [buildErrorEmbed('Circa market unavailable', error.message || 'The Circa market pager hit an unexpected error.')],
1085
+ flags: MessageFlags.Ephemeral,
1086
+ });
1087
+ }
1088
  }
1089
 
1090
  async function handleAlertRoleToggle(interaction, roleName) {