feat: ranked/friendly match types + DM buttons voor alle flows

- match_type veld (friendly/ranked) via /matches POST + /type endpoint
- 🟢 Friendly default bij match creatie
- 🏆 Ranked callback: match_ranked_ zet type, update bericht, DM naar alle spelers
- DM buttons: alle 4 knoppen (  🔄 🏆) beschikbaar in DM voor snelle actie
- Reminder: alleen voor ranked matches
- Score stats: alleen bij ranked matches (wins/games)
This commit is contained in:
Nova Coder
2026-05-25 09:42:33 +00:00
parent a88d931aab
commit 22e77bcc80
+81 -10
View File
@@ -1476,8 +1476,8 @@ bot.on('callback_query', async (query) => {
}
}
// Plan score reminder na eindtijd + 5 min
if (updated.date && updated.end) {
// Plan score reminder na eindtijd + 5 min (alleen ranked)
if (m.match_type === 'ranked' && updated.date && updated.end) {
const now = new Date();
const [endH, endM] = updated.end.split(':').map(Number);
const matchEnd = new Date(now.getFullYear(), now.getMonth(), now.getDate(), endH, endM);
@@ -1529,9 +1529,18 @@ bot.on('callback_query', async (query) => {
for (const pid of matchInfo.players) {
const p = players.find(x => x.id === pid);
if (p && p.telegram_id) {
const typeLabelSwap = matchInfo.match_type === 'ranked' ? '🏆 Ranked' : '🟢 Friendly';
sendMsg(p.telegram_id,
'🔄 **Teams gewisseld!**\n\nNieuwe indeling voor ' + matchInfo.date + ' ' + matchInfo.start + ':\n🟡 ' + t1 + '\n🔵 ' + t2,
{ parse_mode: 'Markdown' }
'🔄 **Teams gewisseld!**\n\n' + typeLabelSwap + '\n\nNieuwe indeling voor ' + matchInfo.date + ' ' + matchInfo.start + ':\n🟡 ' + t1 + '\n🔵 ' + t2,
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '✅ Ja, ik kan!', callback_data: 'match_accept_' + matchId },
{ text: '❌ Nee', callback_data: 'match_reject_' + matchId }]
]
}
}
);
}
}
@@ -1559,6 +1568,57 @@ bot.on('callback_query', async (query) => {
logError('team_swap error:', e.message);
bot.answerCallbackQuery(query.id, { text: 'Fout bij wisselen' }).catch(() => {});
}
} else if (data.startsWith('match_ranked_')) {
const matchId = data.split('_')[2];
try {
await api('/matches/' + matchId + '/type', 'POST', { match_type: 'ranked' });
// Haal spelers en match-info op
const players = await api('/players');
const matchInfo = await api('/matches/' + matchId);
if (!matchInfo) throw new Error('Match not found');
const getName = id => { const p = players.find(x => x.id == id); return p ? p.name : '?'; };
const t1names = (matchInfo.proposed_teams?.team1 || []).map(getName).join(' + ');
const t2names = (matchInfo.proposed_teams?.team2 || []).map(getName).join(' + ');
// Update het originele bericht
try {
bot.editMessageText(
'\ud83c\udfbe **Match gevonden!**\n\n\ud83d\udcc5 ' + matchInfo.date + ' ' + matchInfo.start + '\n\n\ud83c\udfc6 **Teams:**\n\ud83d\udfe1 ' + t1names + '\n\ud83d\udf35 ' + t2names + '\n\n\ud83d\udccd ' + (matchInfo.location || '?') + '\n\nType: \ud83d\udfdf **Ranked** — score telt mee voor competitie!',
{
chat_id: query.message.chat.id,
message_id: query.message.message_id,
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '✅ Ja, ik kan!', callback_data: 'match_accept_' + matchId },
{ text: '❌ Nee', callback_data: 'match_reject_' + matchId }],
[{ text: '🔄 Andere teams', callback_data: 'team_swap_' + matchId }]
]
}
}
).catch(() => {});
} catch(e) { /* ignore edit error */ }
// Stuur DM naar alle spelers
if (matchInfo && Array.isArray(matchInfo.players)) {
for (const pid of matchInfo.players) {
const p = players.find(x => x.id == pid);
if (p && p.telegram_id) {
sendMsg(p.telegram_id,
'\ud83c\udfc6 **Deze match is nu Ranked!**\n\n' + matchInfo.date + ' ' + matchInfo.start + '\n\n' + t1names + ' vs ' + t2names + '\n\nScore telt mee voor de competitie.\nVergeet niet /score in te voeren na de wedstrijd.',
{ parse_mode: 'Markdown' }
);
}
}
}
bot.answerCallbackQuery(query.id, { text: 'Ranked!' }).catch(() => {});
} catch (e) {
logError('match_ranked error:', e.message);
bot.answerCallbackQuery(query.id, { text: 'Fout' }).catch(() => {});
}
}
});
@@ -1802,7 +1862,8 @@ async function runMatching() {
const match = await api('/matches', 'POST', {
day, start, end, date: matchDateStr,
players: best4.map(p => p.id),
telegram_ids: best4.filter(p => p.telegram_id).map(p => p.telegram_id)
telegram_ids: best4.filter(p => p.telegram_id).map(p => p.telegram_id),
match_type: 'friendly'
});
// Sla voorgestelde teams op
@@ -1816,10 +1877,19 @@ async function runMatching() {
for (const p of best4) {
if (p.telegram_id) {
const levels = best4.map(x => x.name + ' (Lv.' + (x.level || '?') + ')').join(', ');
sendMsg(p.telegram_id,
'🎾 **Match voorgesteld!**\n\n📅 ' + day + ' ' + matchDateStr + '\n⏰ ' + start + '-' + end + '\n\n🏆 **Teams:**\n🟡 ' + t1names + '\n🔵 ' + t2names + '\n\n📍 ' + peakzLocation + ' — baan vrij!\nStuur /matches om te reageren.',
{ parse_mode: 'Markdown' }
'🎾 **Match voorgesteld!**\n\n📅 ' + day + ' ' + matchDateStr + '\n⏰ ' + start + '-' + end + '\n\n🏆 **Teams:**\n🟡 ' + t1names + '\n🔵 ' + t2names + '\n\n📍 ' + peakzLocation + '\n\nType: 🟢 Friendly — 1 speler kan deze ranked maken',
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '✅ Ja, ik kan!', callback_data: 'match_accept_' + match.id },
{ text: '❌ Nee', callback_data: 'match_reject_' + match.id }],
[{ text: '🔄 Andere teams', callback_data: 'team_swap_' + match.id }],
[{ text: '🏆 Maak ranked', callback_data: 'match_ranked_' + match.id }]
]
}
}
);
}
}
@@ -1827,14 +1897,15 @@ async function runMatching() {
// Ook naar groeps-chat met team indeling
if (targetChat) {
sendMsg(targetChat,
'🎾 **Match gevonden!**\n\n📅 ' + day + ' ' + matchDateStr + '\n⏰ ' + start + '-' + end + '\n\n🏆 **Teams:**\n🟡 ' + t1names + '\n🔵 ' + t2names + '\n\n📍 ' + peakzLocation + '\n\nReageer met ✅ of ❌',
'🎾 **Match gevonden!**\n\n📅 ' + day + ' ' + matchDateStr + '\n⏰ ' + start + '-' + end + '\n\n🏆 **Teams:**\n🟡 ' + t1names + '\n🔵 ' + t2names + '\n\n📍 ' + peakzLocation + '\n\nType: 🟢 Friendly — 1 speler kan deze ranked maken',
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[{ text: '✅ Ja, ik kan!', callback_data: 'match_accept_' + match.id },
{ text: '❌ Nee', callback_data: 'match_reject_' + match.id }],
[{ text: '🔄 Andere teams', callback_data: 'team_swap_' + match.id }]
[{ text: '🔄 Andere teams', callback_data: 'team_swap_' + match.id }],
[{ text: '🏆 Maak ranked', callback_data: 'match_ranked_' + match.id }]
]
}
}