Codex commited on
Commit ·
8a812eb
1
Parent(s): 07c4ad7
Add Circa button pagination and odds sorting
Browse files- src/embeds.js +58 -1
- 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 =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1030 |
return;
|
| 1031 |
}
|
| 1032 |
|
| 1033 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1034 |
await interaction.reply({
|
| 1035 |
-
embeds: [buildErrorEmbed('Not your pager', 'Only the original user can turn pages on this
|
| 1036 |
flags: MessageFlags.Ephemeral,
|
| 1037 |
});
|
| 1038 |
return;
|
| 1039 |
}
|
| 1040 |
|
| 1041 |
-
|
| 1042 |
-
|
| 1043 |
-
|
| 1044 |
-
|
| 1045 |
-
|
| 1046 |
-
|
| 1047 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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) {
|