From 22e77bcc8097e75df302f4a9ccc6170853d2a3d4 Mon Sep 17 00:00:00 2001 From: Nova Coder Date: Mon, 25 May 2026 09:42:33 +0000 Subject: [PATCH] feat: ranked/friendly match types + DM buttons voor alle flows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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) --- bot.js | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/bot.js b/bot.js index 3fbe4cf..1bba62d 100644 --- a/bot.js +++ b/bot.js @@ -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) { - sendMsg(p.telegram_id, - 'šŸ”„ **Teams gewisseld!**\n\nNieuwe indeling voor ' + matchInfo.date + ' ' + matchInfo.start + ':\n🟔 ' + t1 + '\nšŸ”µ ' + t2, - { parse_mode: 'Markdown' } + const typeLabelSwap = matchInfo.match_type === 'ranked' ? 'šŸ† Ranked' : '🟢 Friendly'; + sendMsg(p.telegram_id, + 'šŸ”„ **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 }] ] } }