{
  "name": "Live Tournament Engine (Score \u2192 Telegram Broadcast)",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "match-score-update",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "node-webhook",
      "name": "Webhook \u2014 Score Update",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "cfg-bot-token",
              "name": "telegram_bot_token",
              "value": "YOUR_TELEGRAM_BOT_TOKEN",
              "type": "string"
            },
            {
              "id": "cfg-group-id",
              "name": "group_chat_id",
              "value": "YOUR_TELEGRAM_GROUP_CHAT_ID",
              "type": "string"
            },
            {
              "id": "cfg-tournament-topic",
              "name": "tournament_topic_id",
              "value": "YOUR_TOURNAMENT_TOPIC_ID",
              "type": "string"
            },
            {
              "id": "cfg-secret",
              "name": "webhook_secret",
              "value": "YOUR_WEBHOOK_SECRET",
              "type": "string"
            },
            {
              "id": "cfg-supabase-url",
              "name": "supabase_url",
              "value": "YOUR_SUPABASE_URL",
              "type": "string"
            },
            {
              "id": "cfg-supabase-key",
              "name": "supabase_service_key",
              "value": "YOUR_SUPABASE_SERVICE_KEY",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "node-config",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        224,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const secret = $('Webhook \u2014 Score Update').item.json.headers['x-n8n-webhook-secret'];\nconst expected = $('Config').item.json.webhook_secret;\n\nif (secret !== expected) {\n  throw new Error('Invalid webhook secret');\n}\n\nconst body = $('Webhook \u2014 Score Update').item.json.body;\nconst {\n  matchId,\n  event,        // 'goal', 'card_yellow', 'card_red', 'kickoff', 'halftime', 'fulltime', 'status_change'\n  team,         // 'home' or 'away'\n  homeTeam,\n  awayTeam,\n  homeScore,\n  awayScore,\n  playerName,\n  minute,\n  status\n} = body;\n\nif (!matchId || !event) {\n  throw new Error('Missing required fields: matchId, event');\n}\n\nreturn {\n  json: {\n    matchId,\n    event,\n    team: team || 'home',\n    homeTeam: homeTeam || 'Home',\n    awayTeam: awayTeam || 'Away',\n    homeScore: homeScore ?? 0,\n    awayScore: awayScore ?? 0,\n    playerName: playerName || null,\n    minute: minute || null,\n    status: status || null\n  }\n};"
      },
      "id": "node-parse",
      "name": "Parse Event",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        448,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const e = $('Parse Event').item.json;\n\nconst emoji = {\n  goal: '\u26bd',\n  card_yellow: '\ud83d\udfe8',\n  card_red: '\ud83d\udfe5',\n  kickoff: '\ud83c\udfdf\ufe0f',\n  halftime: '\u23f8\ufe0f',\n  fulltime: '\ud83c\udfc1',\n  status_change: '\ud83d\udce2'\n};\n\nconst icon = emoji[e.event] || '\ud83d\udce2';\nlet message = '';\n\nswitch (e.event) {\n  case 'goal': {\n    const scorer = e.playerName ? ` (${e.playerName})` : '';\n    const min = e.minute ? ` ${e.minute}'` : '';\n    message = `${icon} <b>GOAL!</b>${min}${scorer}\\n\\n`\n      + `<b>${e.homeTeam}</b> [${e.homeScore}] - [${e.awayScore}] <b>${e.awayTeam}</b>`;\n    break;\n  }\n  case 'card_yellow': {\n    const player = e.playerName || 'Unknown';\n    const min = e.minute ? ` ${e.minute}'` : '';\n    message = `${icon} <b>Yellow Card</b>${min} \u2014 ${player} (${e.team === 'home' ? e.homeTeam : e.awayTeam})\\n\\n`\n      + `<b>${e.homeTeam}</b> [${e.homeScore}] - [${e.awayScore}] <b>${e.awayTeam}</b>`;\n    break;\n  }\n  case 'card_red': {\n    const player = e.playerName || 'Unknown';\n    const min = e.minute ? ` ${e.minute}'` : '';\n    message = `${icon} <b>Red Card</b>${min} \u2014 ${player} (${e.team === 'home' ? e.homeTeam : e.awayTeam})\\n\\n`\n      + `<b>${e.homeTeam}</b> [${e.homeScore}] - [${e.awayScore}] <b>${e.awayTeam}</b>`;\n    break;\n  }\n  case 'kickoff':\n    message = `${icon} <b>KICK OFF!</b>\\n\\n<b>${e.homeTeam}</b> vs <b>${e.awayTeam}</b>\\n\\nThe match is underway! \ud83c\udf89`;\n    break;\n  case 'halftime':\n    message = `${icon} <b>HALF TIME</b>\\n\\n<b>${e.homeTeam}</b> [${e.homeScore}] - [${e.awayScore}] <b>${e.awayTeam}</b>`;\n    break;\n  case 'fulltime':\n    message = `${icon} <b>FULL TIME!</b>\\n\\n<b>${e.homeTeam}</b> [${e.homeScore}] - [${e.awayScore}] <b>${e.awayTeam}</b>\\n\\nFinal result confirmed.`;\n    break;\n  default:\n    message = `${icon} <b>Match Update</b>\\n\\n<b>${e.homeTeam}</b> [${e.homeScore}] - [${e.awayScore}] <b>${e.awayTeam}</b>`;\n    if (e.status) message += `\\nStatus: ${e.status}`;\n}\n\nreturn { json: { message, matchId: e.matchId } };"
      },
      "id": "node-format",
      "name": "Format Broadcast",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $('Config').item.json.telegram_bot_token }}/sendMessage",
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "application/json",
        "body": "={{ JSON.stringify({ chat_id: $('Config').item.json.group_chat_id, text: $json.message, parse_mode: 'HTML', message_thread_id: Number($('Config').item.json.tournament_topic_id) || undefined }) }}",
        "options": {
          "response": {
            "response": {
              "neverError": true
            }
          }
        }
      },
      "id": "node-broadcast",
      "name": "Broadcast to Tournament Topic",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        880,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const result = $input.item.json;\nreturn {\n  json: {\n    success: result.ok === true,\n    telegramMessageId: result.ok ? result.result?.message_id : null\n  }\n};"
      },
      "id": "node-response",
      "name": "Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1104,
        0
      ]
    }
  ],
  "connections": {
    "Webhook \u2014 Score Update": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Parse Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Event": {
      "main": [
        [
          {
            "node": "Format Broadcast",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Broadcast": {
      "main": [
        [
          {
            "node": "Broadcast to Tournament Topic",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Broadcast to Tournament Topic": {
      "main": [
        [
          {
            "node": "Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "tags": [
    {
      "name": "Sports"
    },
    {
      "name": "Telegram"
    },
    {
      "name": "Live"
    }
  ]
}