Salve galera, tudo certinho?
Refiz a integração do futebol agora com a API da ESPN, com ela e´ possível ver os próximos jogos, pegar dados da partida e a tabela de alguns campeonatos. Também adicionei para aviso de gols da partida ao vivo e melhores momentos, esses só funcionam em ‘grandes’ jogos, pelo menos em campeonato regional não deu certo.
- Baixe através do Hacs o card: HTML Jinja2 Template card
- Use o código abaixo para fazer o card do ultimo jogo.
type: custom:html-template-card
ignore_line_breaks: true
content: >
<div style="display: flex; flex-direction: column; align-items: center;
background-color: none !important; padding: 20px; border-radius: 15px;
box-shadow: none !important; font-family: Arial, sans-serif;">
{% set data = state_attr('sensor.espn_futebol', 'last_match') %}
{% set team = data.team if data and 'team' in data else {} %}
{% set league = data.league %}
{% set opponent = data.opponent if data and 'opponent' in data else {} %}
{% set statistics = data.statistics if data and 'statistics' in data else [] %}
{% set gols = data.Gols if data and 'Gols' in data else [] %}
{%- macro normalize(text) -%}
{{ text | lower | regex_replace("[áàãâä]", "a") | regex_replace("[éèêë]", "e") | regex_replace("[íìîï]", "i")| regex_replace("[óòõôö]", "o")| regex_replace("[úùûü]", "u") | regex_replace("[ç]", "c")| regex_replace("\s*de\s*", " ")| regex_replace("\s+", " ")| trim }}}}
{%- endmacro %}
<p style="font-size: 21px; color: var(--primary-text-color);; margin: 5px 0;">
{{ league or 'Liga não disponível' }}
</p>
<div style="display: flex; justify-content: center; align-items: flex-start; margin: 20px 0; width: 100%;">
<div style="text-align: center; flex: 1;">
<img src="{{ team.Logo or 'https://via.placeholder.com/100' }}" alt="Time da Casa" style="width: 100px; height: 100px; border-radius: 10px;">
<p style="margin: 10px 0 0 0; font-size: 16px; color: var(--primary-text-color);">
{{ team.Name or ' ' }}
</p>
<div style="margin-top: 10px; text-align: center;">
{% for gol in gols if normalize(gol.time) == normalize(team.Name) %}
<p style="font-size: 12px; color: var(--primary-text-color); margin: 2px 0;">
{{ gol.jogador }} - {{ gol.minuto }}
</p>
{% endfor %}
</div>
</div>
<div style="text-align: center; flex: 0.5; font-size: 28px; font-weight: bold; color: var(--primary-text-color); align-self: center;">
{{ team.Placar or 0 }} - {{ opponent.Placar or 0 }}
</div>
<div style="text-align: center; flex: 1;">
<img src="{{ opponent.Logo or 'https://via.placeholder.com/100' }}" alt="Time Visitante" style="width: 100px; height: 100px; border-radius: 10px;">
<p style="margin: 10px 0 0 0; font-size: 16px; color: var(--primary-text-color);">
{{ opponent.Name or ' ' }}
</p>
<div style="margin-top: 10px; text-align: center;">
{% for gol in gols if normalize(gol.time) == normalize(opponent.Name) %}
<p style="font-size: 12px; color: var(--primary-text-color); margin: 2px 0;">
{{ gol.jogador }} - {{ gol.minuto }}
</p>
{% endfor %}
</div>
</div>
</div>
{% set data = state_attr('sensor.espn_futebol', 'last_match') %}
{% set statistics = data.statistics if data and 'statistics' in data else [] %}
{% set teamColor = data.team.Color if data and 'team' in data and 'Color' in data.team else '#007bff' %}
{% set opponentColor = data.opponent.Color if data and 'opponent' in data and 'Color' in data.opponent else '#ff073a' %}
<table style="width: 100%; border-collapse: collapse; font-size: 12px; margin-top: -10px;">
<thead>
<tr>
<th style="text-align: center; padding: 3px; border-bottom: 1px solid #ccc;"></th>
<th style="text-align: center; padding: 3px; border-bottom: 1px solid #ccc;"></th>
<th style="text-align: center; padding: 3px; border-bottom: 1px solid #ccc;"> </th>
<th style="text-align: center; padding: 3px; border-bottom: 1px solid #ccc;"></th>
</tr>
</thead>
<tbody>
{% for stat in statistics %}
<tr style="background-color: {% if loop.index is divisibleby 2 %} var(--divider-color) {% else %} var(--input-background-color) {% endif %};">
<td style="padding: 3px; border-bottom: 1px solid #ccc;">
{% set iconMap = {
"Chances Claras": "⚡",
"Faltas": "🚩",
"Cartões Amarelos": "🟨",
"Cartões Vermelhos": "🟥",
"Impedimentos": "🚫",
"Escanteios": "📐",
"Defesas": "🧤",
"Posse de Bola": "⚽",
"Total de Chutes": "🎯",
"Chutes a Gol": "🥅",
"Passes Certos": "✅",
"Total de Passes": "🔄",
"Cruzamentos": "📤",
"Chutes Bloqueados": "🛡️",
"Desarmes": "🦵",
"Placar": "🪧",
"Gols de Pênalti": "🤷♂️",
} %}
{{ iconMap[stat.stat_name] or '' }} {{ stat.stat_name }}
</td>
<td style="text-align: center; padding: 3px; border-bottom: 1px solid #ccc;">{{ stat.team or '-' }}</td>
<td style="text-align: center; padding: 3px; border-bottom: 1px solid #ccc;">
<div style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 8px;
background: #ddd;
border-radius: 5px;
overflow: hidden;
position: relative;
border: 1px solid #ccc;
">
{% set teamScore = stat.team | float(0) %}
{% set opponentScore = stat.opponent | float(0) %}
{% set totalScore = teamScore + opponentScore %}
{% set teamPercentage = (teamScore / totalScore * 100) if totalScore > 0 else 50 %}
<div style="height: 100%; width: {{ teamPercentage }}%; background-color: {{ teamColor }};"></div>
<div style="height: 100%; width: {{ 100 - teamPercentage }}%; background-color: {{ opponentColor }};"></div>
</div>
</td>
<td style="text-align: center; padding: 3px; border-bottom: 1px solid #ccc;">{{ stat.opponent or '-' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
- Baixe no Hacs o card: Team Tracker
- Use o código abaixo para fazer o card do próximo jogo.
type: custom:teamtracker-card
entity: sensor.espn_futebol
show_league: true
show_rank: true
outline: false
show_timeouts: true
outline_color: blue
home_side: left
debug: false
- Baixe no Hacs o card: Flex Table
- Use o código abaixo para fazer o card da tabela do campeonato.
type: custom:stack-in-card
mode: horizontal
cards:
- type: custom:flex-table-card
entities:
include: sensor.espn_tabela
columns:
- name: "#"
data: entries
modify: "'<div style=\"text-align: center;\">' + x.stats[10].value + '</div>'"
- name: Logo
data: entries
modify: >-
'<div style="text-align: center;"><img src="' + x.team.logos[0].href +
'" style="width: 10%;"></div>'
- name: Equipe
data: entries
modify: "'<div style=\"text-align: center;\">' + x.team.name + '</div>'"
- name: J
data: entries
modify: "'<div style=\"text-align: center;\">' + x.stats[0].value + '</div>'"
- name: V
data: entries
modify: "'<div style=\"text-align: center;\">' + x.stats[7].value + '</div>'"
- name: E
data: entries
modify: "'<div style=\"text-align: center;\">' + x.stats[6].value + '</div>'"
- name: D
data: entries
modify: "'<div style=\"text-align: center;\">' + x.stats[1].value + '</div>'"
- name: SG
data: entries
modify: |-
{
'<div style="text-align: center;">' +
(x.stats[5].value - x.stats[4].value) +
'</div>'
}
- name: Pontos
data: entries
modify: "'<div style=\"text-align: center;\">' + x.stats[3].value + '</div>'"
strict: true
- Para mudar o campeonato voce pode utilizar um input_select.tabela_campeonatos
tabela_campeonatos:
name: Selecionar Campeonato
options:
- "Campeonato Brasileiro (BRA.1)"
- "Brazilian Serie B (BRA.2)"
- "Brazilian Serie C (BRA.3)"
- "Copa do Brasil (BRA.COPA_DO_BRAZIL)"
- "UEFA Champions League (UEFA.CHAMPIONS)"
- "UEFA Europa League (UEFA.EUROPA)"
- "Copa do Mundo (FIFA.WORLD)"
- "CONMEBOL Libertadores (CONMEBOL.LIBERTADORES)"
- "CONMEBOL Sudamericana (CONMEBOL.SUDAMERICANA)"
- "Campeonato Inglês (ENG.1)"
- "Spanish LALIGA (ESP.1)"
- "Campeonato Francês (FRA.1)"
- "Bundesliga - Campeonato Alemão (GER.1)"
- "Campeonato Italiano (ITA.1)"
- "Copa das Nações da África (CAF.NATIONS)"
- "Campeonato Chinês (CHN.1)"
- "Campeonato Português (POR.1)"
- "Mundial Feminino (FIFA.WWC)"
- "Campeonato Paulista (BRA.CAMP.PAULISTA)"
- "Campeonato Carioca (BRA.CAMP.CARIOCA)"
- "Campeonato Gaúcho (BRA.CAMP.GAUCHO)"
- "Campeonato Mineiro (BRA.CAMP.MINEIRO)"
- "Copa do Nordeste (BRA.COPA_DO_NORDESTE)"
- "Supercopa do Brasil (BRA.SUPERCOPA_DO_BRAZIL)"
- "Eliminatórias Eurocopa (UEFA.EUROQ)"
- "Copa São Paulo (BRA.SAOPAULO_YOUTH_CUP)"
- "Copa América (CONMEBOL.AMERICA)"
- "Amistoso (CLUB.FRIENDLY)"
- "Brasileiro - S20 (BRA.BRASILEIRO_U20)"
- "Copa do Brasil - S17 (BRA.COPA_DO_BRAZIL_U17)"
- "Copa do Brasil - S20 (BRA.COPA_DO_BRAZIL_U20)"
- "Panamericano - Futebol Feminino (PANAM.W)"
initial: "Campeonato Brasileiro (BRA.1)"
icon: mdi:trophy
-
Para mudar o nome do time, crie um input_text.espn_team e adicione o nome do time que deseja pegar o status, caso não encontre ou de algum tipo de erro, entre no site da espn e veja se o nome dele não e´ escrito de forma diferente lá e tente novamente.
-
Agora importe o código para o nodered
[{"id":"4b724119114337ed","type":"subflow","name":"Alexa fala","info":"","category":"","in":[{"x":120,"y":360,"wires":[{"id":"96709cccd273c329"},{"id":"da93b5086a8be64c"},{"id":"4f70e525d8f41ff5"},{"id":"5ace3ef7a8f10688"},{"id":"e1d234de24d7091e"},{"id":"259fe40bea0c8187"}]}],"out":[{"x":860,"y":360,"wires":[{"id":"9cfcabd8ce9c2dd0","port":0}]}],"env":[{"name":"escritorio","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"sala","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"quarto","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"suite","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"todas","type":"str","value":"","ui":{"type":"input","opts":{"types":["str"]}}},{"name":"","type":"str","value":"","ui":{"label":{"en-US":"Utilizar msg.alexa como variavel para passar informação"},"type":"none"}},{"name":"msg.alexa","type":"str","value":"","ui":{"type":"select","opts":{"opts":[{"l":{"en-US":"escritorio"},"v":"escritorio"},{"l":{"en-US":"sala"},"v":"sala"},{"l":{"en-US":"quarto"},"v":"quarto"},{"l":{"en-US":"suite"},"v":"suite"},{"l":{"en-US":"todas"},"v":"todas"},{"l":{"en-US":"null"},"v":""}]}}},{"name":"vol_fala","type":"num","value":"100","ui":{"type":"input","opts":{"types":["num"]}}},{"name":"vol_padrao","type":"num","value":"30","ui":{"type":"input","opts":{"types":["num"]}}}],"meta":{},"color":"#3FADB5","inputLabels":["cozinha / quarto / todas"],"icon":"node-red-contrib-alexa-remote2-applestrudel/alexa-remote-icon.png"},{"id":"3c6210e9c37d2c2a","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa escritorio","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"env","value":"escritorio"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G090XG0894371SGN"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G090XG0894371SGN"]}}]}},"x":540,"y":140,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"15b3c32b5643c45a","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa quarto","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"env","value":"quarto"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G0G2DB033146147J"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G0G2DB033146147J"]}}]}},"x":530,"y":180,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"d8289f16a9188f29","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa todas","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"env","value":"todas"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["51891e5ab3744b24b276a8f3d16d09ba"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["51891e5ab3744b24b276a8f3d16d09ba"]}}]}},"x":530,"y":260,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"7e6930f595ba955d","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa sala","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"msg","value":"alexa"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G0G2DB03314509S6"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G0G2DB03314509S6"]}}]}},"x":530,"y":480,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"bbb72289adee2f4a","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa quarto","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"msg","value":"alexa"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G0G2DB033146147J"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G0G2DB033146147J"]}}]}},"x":530,"y":520,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"6481a16bad9295e5","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa todas","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"msg","value":"alexa"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["51891e5ab3744b24b276a8f3d16d09ba"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["51891e5ab3744b24b276a8f3d16d09ba"]}}]}},"x":530,"y":600,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"4f70e525d8f41ff5","type":"switch","z":"4b724119114337ed","name":"escritorio","property":"escritorio","propertyType":"env","rules":[{"t":"nempty"}],"checkall":"true","repair":false,"outputs":1,"x":320,"y":140,"wires":[["3c6210e9c37d2c2a"]]},{"id":"da93b5086a8be64c","type":"switch","z":"4b724119114337ed","name":"quarto","property":"quarto","propertyType":"env","rules":[{"t":"nempty"}],"checkall":"true","repair":false,"outputs":1,"x":310,"y":180,"wires":[["15b3c32b5643c45a"]]},{"id":"96709cccd273c329","type":"switch","z":"4b724119114337ed","name":"todas","property":"todas","propertyType":"env","rules":[{"t":"nempty"}],"checkall":"true","repair":false,"outputs":1,"x":310,"y":260,"wires":[["d8289f16a9188f29"]]},{"id":"5ace3ef7a8f10688","type":"switch","z":"4b724119114337ed","name":"Qual alexa?","property":"msg.alexa","propertyType":"env","rules":[{"t":"eq","v":"escritorio","vt":"str"},{"t":"eq","v":"sala","vt":"str"},{"t":"eq","v":"quarto","vt":"str"},{"t":"eq","v":"suite","vt":"str"},{"t":"eq","v":"todas","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":310,"y":500,"wires":[["31aac769d2291208"],["7e6930f595ba955d"],["bbb72289adee2f4a"],["75b87aaaa1d66010"],["6481a16bad9295e5"]]},{"id":"ed682c3a9cb85bab","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa sala","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"env","value":"sala"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G0G2DB03314509S6"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G0G2DB03314509S6"]}}]}},"x":530,"y":220,"wires":[[]]},{"id":"e1d234de24d7091e","type":"switch","z":"4b724119114337ed","name":"sala","property":"sala","propertyType":"env","rules":[{"t":"nempty"}],"checkall":"true","repair":false,"outputs":1,"x":310,"y":220,"wires":[["ed682c3a9cb85bab"]]},{"id":"31aac769d2291208","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa escritorio","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"msg","value":"alexa"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G090XG0894371SGN"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G090XG0894371SGN"]}}]}},"x":540,"y":440,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"259fe40bea0c8187","type":"switch","z":"4b724119114337ed","name":"suite","property":"suite","propertyType":"env","rules":[{"t":"nempty"}],"checkall":"true","repair":false,"outputs":1,"x":310,"y":100,"wires":[["709a147ef734f02d"]]},{"id":"709a147ef734f02d","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa suite","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"env","value":"suite"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G090XG1220340B5S"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G090XG1220340B5S"]}}]}},"x":530,"y":100,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"75b87aaaa1d66010","type":"alexa-remote-routine","z":"4b724119114337ed","name":"Alexa suite","account":"d2d5e58c12932ab2","routineNode":{"type":"node","payload":{"type":"serial","children":[{"type":"speakAtVolume","payload":{"type":"regular","text":{"type":"msg","value":"alexa"},"volume":{"type":"env","value":"vol_fala"},"mode":"set","devices":["G090XG1220340B5S"]}},{"type":"volume","payload":{"value":{"type":"env","value":"vol_padrao"},"mode":{"type":"str","value":"set"},"devices":["G090XG1220340B5S"]}}]}},"x":530,"y":560,"wires":[["9cfcabd8ce9c2dd0"]]},{"id":"9cfcabd8ce9c2dd0","type":"junction","z":"4b724119114337ed","x":700,"y":360,"wires":[[]]},{"id":"d2d5e58c12932ab2","type":"alexa-remote-account","name":"","authMethod":"proxy","proxyOwnIp":"192.168.0.140","proxyPort":"3456","cookieFile":"/homeassistant/authAlexa","refreshInterval":"3","alexaServiceHost":"pitangui.amazon.com","pushDispatchHost":"","amazonPage":"amazon.com.br","acceptLanguage":"pt-BR","onKeywordInLanguage":"on","userAgent":"","usePushConnection":"on","autoInit":"on"},{"id":"37e033d25f1ace08","type":"tab","label":"-ESPN Futebol","disabled":false,"info":"","env":[]},{"id":"3b857c2ad83f94c0","type":"group","z":"37e033d25f1ace08","name":"Tabelas","style":{"label":true},"nodes":["function","aa18b2787c3ee65b","ef9423f47722fc96","bb3fc3454dbab5d1","http-request","9d3d7f68d5433799","f0c7293a0776767e"],"x":64,"y":39,"w":922,"h":142},{"id":"4f1473862f7c6795","type":"group","z":"37e033d25f1ace08","name":"Times","style":{"label":true},"nodes":["b987a171168b0a1b","fbbb4ecae540e1b8","fdc5d863503d6a55","1b9eec7aa52969d9","dde5f1167944c138","ebbff10205ad6be8","229a28fb3c2ca8df","8e0c8d70c610282e","74041b4270b1926b","1f83095254512b89","59e0b2cf121985f4","5980a92d311f728c","f320b8e357da1dd7","9ed874b6621534e7","9a76d5ae7d7e95f7","d3d82c9553f5208d","d6ea9d94bc6cad5a","91fbbd052bee174d","bf58e8ae47278ecb","e0151e09bd7c242d","2975c186bb2d8314","7154ae351a81c9bb","84e55e786724e195","ba6a5420f05f24c8","2e522e59d89df48d","0bee37d94f1810a8","778e632e07e842af","b72982ef40952e70","0526e3eb265894a8","98cc076ffc24034e","dc1e39d9c8b290f2"],"x":34,"y":259,"w":1652,"h":262},{"id":"be6cfbb1827a395c","type":"group","z":"37e033d25f1ace08","name":"Automações","style":{"label":true},"nodes":["1ff74e92a1d579ad","7c7a66e4d63a5a77","dcdd298101fecbeb","fdd13a61666334d8","1df59ada36d3f556","c51ae48feed0bfdb","c4856b5024f17dde","1ee62e5082c06f8d","95cdfa9eecce0e19","535ce6dd9a08d86a","8189baadf4ab750a","dbe3b8f77ca52e13","8ddfd8a6f41862b8","43b301c6ec80698b","89b5158aaa0e37a2","db91ab1997105d19","f3a6d843c5f9e4dd","f7b5919e868a446b","15c8cbd5f00bb3f9","f125c3cc80cc6236","27f947af362f82e5","3c292a9d23c38303","a926e78d88fe9810","ec8285a21126007c","5e2e8d02cb92eb59","4010e6284a33c629","9d6bc8f7e187f74d","94d83653c7a82417","03fee0dbf228e28e","2318f6a557b38709"],"x":54,"y":599,"w":1292,"h":362},{"id":"91fbbd052bee174d","type":"junction","z":"37e033d25f1ace08","g":"4f1473862f7c6795","x":780,"y":380,"wires":[["fdc5d863503d6a55","f320b8e357da1dd7"]]},{"id":"7154ae351a81c9bb","type":"junction","z":"37e033d25f1ace08","g":"4f1473862f7c6795","x":1260,"y":480,"wires":[["9ed874b6621534e7"]]},{"id":"84e55e786724e195","type":"junction","z":"37e033d25f1ace08","g":"4f1473862f7c6795","x":1220,"y":440,"wires":[["e0151e09bd7c242d"]]},{"id":"ba6a5420f05f24c8","type":"junction","z":"37e033d25f1ace08","g":"4f1473862f7c6795","x":1220,"y":400,"wires":[["9ed874b6621534e7"]]},{"id":"f7b5919e868a446b","type":"junction","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","x":620,"y":660,"wires":[["7c7a66e4d63a5a77","dcdd298101fecbeb"]]},{"id":"15c8cbd5f00bb3f9","type":"junction","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","x":620,"y":700,"wires":[["1df59ada36d3f556"]]},{"id":"f125c3cc80cc6236","type":"junction","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","x":1060,"y":880,"wires":[["27f947af362f82e5"]]},{"id":"27f947af362f82e5","type":"junction","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","x":1100,"y":840,"wires":[["dbe3b8f77ca52e13"]]},{"id":"3c292a9d23c38303","type":"junction","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","x":1060,"y":780,"wires":[["27f947af362f82e5"]]},{"id":"ec8285a21126007c","type":"junction","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","x":100,"y":920,"wires":[["1ee62e5082c06f8d"]]},{"id":"function","type":"function","z":"37e033d25f1ace08","g":"3b857c2ad83f94c0","name":"Preparar Dados","func":"msg.payload = {\n state: new Date().toISOString(),\n attributes: {\n entries: msg.payload.children[0].standings.entries\n }\n};\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":700,"y":120,"wires":[["aa18b2787c3ee65b"]]},{"id":"aa18b2787c3ee65b","type":"ha-sensor","z":"37e033d25f1ace08","g":"3b857c2ad83f94c0","name":"sensor tabela","entityConfig":"7275219dbc3a8c8d","version":0,"state":"on","stateType":"str","attributes":[],"inputOverride":"allow","outputProperties":[],"x":880,"y":120,"wires":[[]]},{"id":"ef9423f47722fc96","type":"server-state-changed","z":"37e033d25f1ace08","g":"3b857c2ad83f94c0","name":"Tabela selecionada","server":"db1ab0af.caa65","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["input_select.tabela_campeonatos"],"substring":[],"regex":[]},"outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"state","propertyType":"msg","value":"","valueType":"entityState"}],"x":190,"y":80,"wires":[["bb3fc3454dbab5d1"]]},{"id":"bb3fc3454dbab5d1","type":"function","z":"37e033d25f1ace08","g":"3b857c2ad83f94c0","name":"function ","func":"\nif (msg.state && msg.state.includes(\"(\")) {\n // Extrai o conteúdo entre os parênteses\n let match = msg.state.match(/\\((.*?)\\)/);\n if (match && match[1]) {\n msg.state = match[1]; \n } else {\n msg.state = \"\"; \n }\n} else {\n msg.state = \"\"; \n}\n\nmsg.url = \"https://site.web.api.espn.com/apis/v2/sports/soccer/\"+msg.state+\"/standings?type=0&level=0\"\nmsg.headers = {\n \"Content-Type\": \"application/json\"\n};\n\nreturn msg;\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":120,"wires":[["http-request"]]},{"id":"http-request","type":"http request","z":"37e033d25f1ace08","g":"3b857c2ad83f94c0","name":"Requisitar API","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"c159a5512ccbc528","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":520,"y":120,"wires":[["function"]]},{"id":"9d3d7f68d5433799","type":"api-current-state","z":"37e033d25f1ace08","g":"3b857c2ad83f94c0","name":"state time","server":"db1ab0af.caa65","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_select.tabela_campeonatos","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"state","propertyType":"msg","value":"","valueType":"entityState"},{"property":"timestamp","propertyType":"msg","value":"","valueType":"date"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":220,"y":140,"wires":[["bb3fc3454dbab5d1"]]},{"id":"f0c7293a0776767e","type":"inject","z":"37e033d25f1ace08","g":"3b857c2ad83f94c0","name":"","props":[],"repeat":"3600","crontab":"","once":true,"onceDelay":"40","topic":"","x":125,"y":140,"wires":[["9d3d7f68d5433799"]],"l":false},{"id":"b987a171168b0a1b","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"url time","func":"msg.url =\"https://site.web.api.espn.com/apis/search/v2?region=br&lang=pt&limit=1&page=1&type=team&dtciVideoSearch=true&query=\"+msg.state\nmsg.headers = {\n \"Content-Type\": \"application/json\"\n};\n\n\nreturn msg;\n ","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":400,"wires":[["229a28fb3c2ca8df"]]},{"id":"fbbb4ecae540e1b8","type":"inject","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","props":[],"repeat":"60","crontab":"","once":true,"onceDelay":"40","topic":"","x":95,"y":400,"wires":[["98cc076ffc24034e"]],"l":false},{"id":"fdc5d863503d6a55","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"url jogos","func":"const content = msg.payload.results[0].contents[0].uid;\nconst result = content.split('t:')[1];\n\nmsg.id = result\n\nmsg.url = \"https://site.web.api.espn.com/apis/site/v2/sports/soccer/all/teams/\"+msg.id+\"/schedule?region=br&lang=pt&fixture=true\"\nmsg.headers = {\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15\"\n};\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":340,"wires":[["8e0c8d70c610282e"]]},{"id":"1b9eec7aa52969d9","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Dados sensor","func":"// Extrai a data do jogo e o timestamp atual\nconst gameDate = new Date(msg.payload.events?.[0]?.competitions?.[0]?.date).getTime() || 0; // Converte para timestamp UTC\nconst currentDate = new Date(msg.timestamp).getTime() || 0; // Já vem no formato timestamp UTC\n\n// Pega dados do flow\nconst liveMatchStats = flow.get('LiveMatchStatistics');\nconst eventos = flow.get('Eventos');\n\n// Calcula a diferença em milissegundos\nconst timeDiff = gameDate - currentDate;\n\n// Define a mensagem para \"Kickoff in\"\nlet kickoffMessage;\nif (timeDiff <= 0) {\n kickoffMessage = \"O jogo já começou!\";\n} else if (timeDiff <= 60 * 1000) { // Menos de 1 minuto\n kickoffMessage = \"em menos de 1 minuto\";\n} else if (timeDiff <= 60 * 60 * 1000) { // Menos de 1 hora\n const minutesToKickoff = Math.ceil(timeDiff / (1000 * 60)); // Converte para minutos\n kickoffMessage = `em ${minutesToKickoff} minuto${minutesToKickoff > 1 ? 's' : ''}`;\n} else if (timeDiff <= 24 * 60 * 60 * 1000) { // Menos de 24 horas\n const hoursToKickoff = Math.ceil(timeDiff / (1000 * 60 * 60)); // Converte para horas\n kickoffMessage = `em ${hoursToKickoff} hora${hoursToKickoff > 1 ? 's' : ''}`;\n} else if (timeDiff <= 7 * 24 * 60 * 60 * 1000) { // Entre 1 e 7 dias\n const daysToKickoff = Math.ceil(timeDiff / (24 * 60 * 60 * 1000)); // Converte para dias\n kickoffMessage = `em ${daysToKickoff} dia${daysToKickoff > 1 ? 's' : ''}`;\n} else if (timeDiff <= 14 * 24 * 60 * 60 * 1000) { // Entre 7 e 14 dias\n kickoffMessage = \"em 1 semana\";\n} else if (timeDiff <= 21 * 24 * 60 * 60 * 1000) { // Entre 14 e 21 dias\n kickoffMessage = \"em 2 semanas\";\n} else {\n kickoffMessage = \" \";\n}\n\nconst gols = flow.get('gols') || []; // Recupera os gols armazenados no fluxo\n\nmsg.payload = {\n state: msg.payload.events?.[0]?.competitions?.[0]?.status?.type?.state?.toUpperCase() || \" \",\n attributes: {\n 'Sport': 'soccer',\n 'League': msg.payload.events?.[0]?.league?.name || \" \",\n 'League logo': 'https://a.espncdn.com/i/leaguelogos/soccer/500/' + (msg.payload.events?.[0]?.league?.alternateId || 'default') + '.png',\n 'Team abbr': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.team?.abbreviation || \" \",\n 'Opponent abbr': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.team?.abbreviation || \" \",\n 'Event name': msg.payload.events?.[0]?.shortName || \" \",\n 'Event url': msg.payload.events?.[0]?.links?.[0]?.href || \" \",\n 'Date': msg.payload.events?.[0]?.competitions?.[0]?.date || \" \",\n 'Kickoff in': kickoffMessage || \" \",\n 'Series summary': \" \",\n 'Venue': msg.payload.events?.[0]?.competitions?.[0]?.venue?.fullName || \" \",\n 'Location': (msg.payload.events?.[0]?.competitions?.[0]?.venue?.address?.city || \" \") + ', ' + (msg.payload.events?.[0]?.competitions?.[0]?.venue?.address?.country || \" \"),\n 'Tv network': \" \",\n 'Odds': \" \",\n 'Overunder': \" \",\n 'Team name': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.team?.displayName || \" \",\n 'Team ID': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.team?.id || \" \",\n 'Team record': msg.payload?.events?.[0]?.competitions?.[0]?.competitors?.[0]?.record?.[0]?.displayValue ?? \" \",\n 'Team rank': \" \",\n 'Team homeaway': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.homeAway || \" \",\n 'Team logo': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.team?.logos?.[0]?.href || 'https://a.espncdn.com/i/teamlogos/soccer/500/default-team-logo-500.png',\n 'Team url': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.team?.links?.[0]?.href || \" \",\n 'Team colors': liveMatchStats?.team?.Color || \"#fff\",\n 'Team score': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.score?.displayValue || \" \",\n 'Team win probability': \" \",\n 'Team winner': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.winner || false,\n 'Team timeouts': \" \",\n 'Team gols': gols\n .filter(gol => gol.idTime === msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[0]?.team?.id)\n .map(gol => ({\n jogador: gol.jogador,\n time: gol.time,\n minuto: gol.minuto,\n descricao: gol.descricao,\n idTime: gol.idTime\n })),\n 'Opponent name': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.team?.displayName || \" \",\n 'Opponent ID': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.team?.id || \" \",\n 'Opponent record': msg.payload?.events?.[0]?.competitions?.[0]?.competitors?.[1]?.record?.[0]?.displayValue ?? \" \",\n 'Opponent rank': \" \",\n 'Opponent homeaway': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.homeAway || \" \",\n 'Opponent logo': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.team?.logos?.[0]?.href || 'https://a.espncdn.com/i/teamlogos/soccer/500/default-team-logo-500.png',\n 'Opponent url': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.team?.links?.[0]?.href || \" \",\n 'Opponent colors': liveMatchStats?.opponent?.Color || \"#fff\",\n 'Opponent score': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.score?.displayValue || \" \",\n 'Opponent win probability': \" \",\n 'Opponent winner': msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.winner || false,\n 'Opponent gols': gols\n .filter(gol => gol.idTime === msg.payload.events?.[0]?.competitions?.[0]?.competitors?.[1]?.team?.id)\n .map(gol => ({\n jogador: gol.jogador,\n time: gol.time,\n minuto: gol.minuto,\n descricao: gol.descricao,\n idTime: gol.idTime\n })),\n 'Quarter': msg.payload.events?.[0]?.competitions?.[0]?.status?.period || \" \",\n 'Clock': msg.payload.events?.[0]?.competitions?.[0]?.status?.type?.detail || \" \",\n 'Possession': \" \",\n 'Last play': eventos?.stringTodosJuntos || \" \",\n 'Down distance text': \" \",\n 'Outs': \" \",\n 'Balls': \" \",\n 'Strikes': \" \",\n 'On first': \" \",\n 'On second': \" \",\n 'On third': \" \",\n 'Team shots on target': liveMatchStats?.team?.ShotsTarget || \" \",\n 'Team total shots': liveMatchStats?.team?.TotalShots || \" \",\n 'Opponent shots on target': liveMatchStats?.opponent?.ShotsTarget || \" \",\n 'Opponent total shots': liveMatchStats?.opponent?.TotalShots || \" \",\n 'Team sets won': \" \",\n 'Opponent sets won': \" \",\n 'Last update': msg.timestamp || \" \",\n 'Eventos' : flow.get(\"Eventos\"),\n\n last_match: msg.payload.events?.[0]?.competitions?.[0]?.status?.type?.state?.toUpperCase() === \"IN\"\n ? flow.get(\"LiveMatchStatistics\")\n : flow.get(\"LastMatchStatistics\")\n\n }\n};\nreturn msg;\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":1140,"y":360,"wires":[["dde5f1167944c138"]]},{"id":"dde5f1167944c138","type":"ha-sensor","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"sensor time","entityConfig":"0ec7baaca4a6d27b","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":1370,"y":360,"wires":[[]]},{"id":"ebbff10205ad6be8","type":"server-state-changed","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Time","server":"db1ab0af.caa65","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["input_text.espn_team"],"substring":[],"regex":[]},"outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"state","propertyType":"msg","value":"","valueType":"entityState"},{"property":"timestamp","propertyType":"msg","value":"","valueType":"date"}],"x":170,"y":320,"wires":[["b987a171168b0a1b","b72982ef40952e70"]]},{"id":"229a28fb3c2ca8df","type":"http request","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Requisitar API","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"c159a5512ccbc528","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":395,"y":400,"wires":[["dc1e39d9c8b290f2"]],"l":false},{"id":"8e0c8d70c610282e","type":"http request","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Requisitar API","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"c159a5512ccbc528","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":965,"y":340,"wires":[["1f83095254512b89","74041b4270b1926b"]],"l":false},{"id":"74041b4270b1926b","type":"delay","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":1025,"y":360,"wires":[["1b9eec7aa52969d9"]],"l":false},{"id":"1f83095254512b89","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"URL Ao vivo","func":"if (msg.payload.events?.[0]?.competitions?.[0]?.status?.type?.state?.toUpperCase() === \"IN\") {\n\n msg.url = \"https://site.web.api.espn.com/apis/site/v2/sports/soccer/all/summary?region=br&lang=pt&contentorigin=deportes&event=\" + msg.payload.events[0].id\n msg.headers = {\n \"Content-Type\": \"application/json\"\n };\n return msg;\n}\n\n\n\n ","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1130,"y":300,"wires":[["59e0b2cf121985f4"]]},{"id":"59e0b2cf121985f4","type":"http request","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"c159a5512ccbc528","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1245,"y":300,"wires":[["5980a92d311f728c"]],"l":false},{"id":"5980a92d311f728c","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Dados ao vivo","func":"const liveMatchStats = flow.get('LiveMatchStatistics');\nfunction normalizeString(str) {\n return str?.normalize(\"NFD\").replace(/[\\u0300-\\u036f]/g, \"\").toLowerCase();\n}\nconst live_match_statistics = {\n league: msg.payload.header.league.name,\n team: {\n Name: msg.payload.header.competitions[0].competitors[0].team.name || \" \",\n Logo: msg.payload.boxscore.teams[0].team.logo || 'https://a.espncdn.com/i/teamlogos/soccer/500/default-team-logo-500.png',\n Color: \"#\" + msg.payload.header.competitions[0].competitors[0].team.color || \" \",\n Abbreviation: msg.payload.header.competitions[0].competitors[0].team.abbreviation || \" \",\n Placar: msg.payload.header.competitions[0].competitors[0].score || \" \",\n HomeAway: msg.payload.header.competitions[0].competitors[0].homeAway || \" \",\n Winner: msg.payload.header.competitions[0].competitors[0].winner || \" \",\n ShotsTarget: msg.payload.boxscore.teams[0].statistics[8].displayValue || \" \",\n TotalShots: msg.payload.boxscore.teams[0].statistics[7].displayValue || \" \",\n },\n opponent: {\n Name: msg.payload.header.competitions[0].competitors[1].team.name || \" \",\n Logo: msg.payload.boxscore.teams[1].team.logo || 'https://a.espncdn.com/i/teamlogos/soccer/500/default-team-logo-500.png',\n Color: \"#\" + msg.payload.header.competitions[0].competitors[1].team.color || \" \",\n Abbreviation: msg.payload.header.competitions[0].competitors[1].team.abbreviation || \" \",\n Placar: msg.payload.header.competitions[0].competitors[1].score || \" \",\n HomeAway: msg.payload.header.competitions[0].competitors[1].homeAway || \" \",\n Winner: msg.payload.header.competitions[0].competitors[1].winner || \" \",\n ShotsTarget: msg.payload.boxscore.teams[1].statistics[8].displayValue || \" \",\n TotalShots: msg.payload.boxscore.teams[1].statistics[7].displayValue || \" \",\n },\n statistics: [\n { stat_name: \"Chances Claras\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[26]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[26]?.displayValue || \" \" },\n { stat_name: \"Faltas\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[0]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[0]?.displayValue || \" \" },\n { stat_name: \"Cartões Amarelos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[1]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[1]?.displayValue || \" \" },\n { stat_name: \"Cartões Vermelhos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[2]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[2]?.displayValue || \" \" },\n { stat_name: \"Impedimentos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[3]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[3]?.displayValue || \" \" },\n { stat_name: \"Escanteios\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[4]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[4]?.displayValue || \" \" },\n { stat_name: \"Defesas\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[5]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[5]?.displayValue || \" \" },\n { stat_name: \"Posse de Bola\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[6]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[6]?.displayValue || \" \" },\n { stat_name: \"Total de Chutes\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[7]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[7]?.displayValue || \" \" },\n { stat_name: \"Chutes a Gol\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[8]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[8]?.displayValue || \" \" },\n { stat_name: \"Gols de Pênalti\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[11]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[11]?.displayValue || \" \" },\n { stat_name: \"Passes Certos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[12]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[12]?.displayValue || \" \" },\n { stat_name: \"Total de Passes\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[13]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[13]?.displayValue || \" \" },\n { stat_name: \"Cruzamentos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[16]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[16]?.displayValue || \" \" },\n { stat_name: \"Chutes Bloqueados\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[21]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[21]?.displayValue || \" \" },\n { stat_name: \"Desarmes\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[23]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[23]?.displayValue || \" \" },\n { stat_name: \"Placar\", team: msg.payload.header?.competitions?.[0]?.competitors?.[0]?.score || \" \", opponent: msg.payload.header?.competitions?.[0]?.competitors?.[1]?.score || \" \" }\n ],\n Gols: []\n};\n\n// Verifica se msg.payload.keyEvents existe e é um array\nif (msg.payload && Array.isArray(msg.payload.keyEvents)) {\n msg.payload.keyEvents.forEach(event => {\n if (event.type && event.type.text && /^Gol|Goal/.test(event.type.text)) {\n const golInfo = {\n jogador: event.participants && event.participants[0]?.athlete?.displayName || \" \",\n time: event.team?.displayName || \" \",\n minuto: event.clock?.displayValue || \" \",\n descricao: event.text || \" \",\n idTime: event.team?.id || \" \"\n };\n\n // Adiciona o gol ao array de gols\n live_match_statistics.Gols.push(golInfo);\n }\n });\n}\n\nflow.set(\"LiveMatchStatistics\", live_match_statistics);\n\nconst keyEvents = Array.isArray(msg.payload.keyEvents) ? msg.payload.keyEvents : null;\n\nlet eventos = [];\nlet arrayClock = [];\nlet arrayType = [];\nlet arrayParticipants = [];\nlet arrayParticipants2 = [];\nlet arrayTeamAbbreviation = [];\n\nif (!keyEvents) {\n const eventosData = {\n arrayClock: [],\n arrayType: [],\n arrayParticipants: [],\n arrayParticipants2: [],\n arrayTeamAbbreviation: [],\n stringTodosJuntos: \"\"\n };\n\n flow.set(\"Eventos\", eventosData);\n} else {\n keyEvents.forEach(event => {\n let eventoStr = \"\";\n\n // Clock\n if (event.clock && event.clock.displayValue) {\n arrayClock.push(event.clock.displayValue);\n eventoStr += event.clock.displayValue + \" \";\n } else {\n arrayClock.push(\"\");\n }\n\n // Type\n if (event.type && event.type.text) {\n arrayType.push(event.type.text);\n eventoStr += event.type.text + \": \";\n } else {\n arrayType.push(\"\");\n }\n\n // Participants\n if (event.participants && Array.isArray(event.participants)) {\n let participantNames = [];\n event.participants.forEach(participant => {\n if (participant.athlete && participant.athlete.displayName) {\n participantNames.push(participant.athlete.displayName);\n } else {\n participantNames.push(\"\"); // Adiciona string vazia se faltar o nome do participante\n }\n });\n arrayParticipants.push(participantNames[0] || \"\"); // Primeiro participante no array original\n arrayParticipants2.push(participantNames.slice(1).join(\", \") || \"\"); // Outros participantes\n eventoStr += participantNames.join(\" → \") + \" \"; // Junta todos os participantes com \"→\" entre eles\n } else {\n arrayParticipants.push(\"\"); // Adiciona string vazia para o primeiro\n arrayParticipants2.push(\"\"); // Adiciona string vazia para os demais\n }\n\n // Team Abbreviation\n if (event.team && event.team.displayName) {\n const normalizedEventTeamName = normalizeString(event.team.displayName);\n const normalizedTeamName = normalizeString(live_match_statistics.team.Name);\n const normalizedOpponentName = normalizeString(live_match_statistics.opponent.Name);\n\n let teamAbbreviation = \"\";\n if (normalizedEventTeamName === normalizedTeamName) {\n teamAbbreviation = live_match_statistics.team.Abbreviation || \"\";\n } else if (normalizedEventTeamName === normalizedOpponentName) {\n teamAbbreviation = live_match_statistics.opponent.Abbreviation || \"\";\n } else if (event.team && event.team.abbreviation) {\n teamAbbreviation = event.team.abbreviation;\n } else {\n teamAbbreviation = event.team.displayName || \"\";\n }\n arrayTeamAbbreviation.push(teamAbbreviation.trim());\n eventoStr += `(${teamAbbreviation.trim()})`;\n } else {\n arrayTeamAbbreviation.push(\"\");\n }\n\n // Add event to array if not empty\n if (eventoStr.trim() !== \"\") {\n eventos.push(eventoStr.trim());\n }\n });\n}\n\n// Estrutura para salvar\nconst eventosData = {\n arrayClock: arrayClock,\n arrayType: arrayType,\n arrayParticipants: arrayParticipants,\n arrayParticipants2: arrayParticipants2,\n arrayTeamAbbreviation: arrayTeamAbbreviation,\n stringTodosJuntos: eventos.join(\" \\n \")\n};\n\n// Salvando no flow\nflow.set(\"Eventos\", eventosData);\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1380,"y":300,"wires":[[]]},{"id":"f320b8e357da1dd7","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"URL ultimo jogo","func":"const content = msg.payload.results[0].contents[0].uid;\nconst result = content.split('t:')[1];\n\nmsg.id = result\n\nmsg.url = \"https://site.web.api.espn.com/apis/site/v2/sports/soccer/all/teams/\" + msg.id +\"/schedule?region=br&lang=pt&season=2025\"\nmsg.headers = {\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15\"\n};\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":900,"y":420,"wires":[["d3d82c9553f5208d"]]},{"id":"9ed874b6621534e7","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"ID evento","func":"msg.url = \"https://site.web.api.espn.com/apis/site/v2/sports/soccer/all/summary?region=br&lang=pt&contentorigin=deportes&event=\" + msg.payload.events[0].id\nmsg.headers = {\n \"Content-Type\": \"application/json\"\n};\n\n\nreturn msg;\n ","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1360,"y":440,"wires":[["9a76d5ae7d7e95f7"]]},{"id":"9a76d5ae7d7e95f7","type":"http request","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"c159a5512ccbc528","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1455,"y":440,"wires":[["d6ea9d94bc6cad5a"]],"l":false},{"id":"d3d82c9553f5208d","type":"http request","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"c159a5512ccbc528","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1025,"y":420,"wires":[["bf58e8ae47278ecb"]],"l":false},{"id":"d6ea9d94bc6cad5a","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Dados ultimo jogo","func":"const last_match_statistics = {\n league: msg.payload.header.league.name,\n team: {\n Name: msg.payload.header.competitions[0].competitors[0].team.displayName || \" \",\n Logo: msg.payload.boxscore.teams[0].team.logo || 'https://a.espncdn.com/i/teamlogos/soccer/500/default-team-logo-500.png',\n Color: \"#\" + msg.payload.header.competitions[0].competitors[0].team.color || \" \",\n Abbreviation: msg.payload.header.competitions[0].competitors[0].team.abbreviation || \" \",\n Placar: msg.payload.header.competitions[0].competitors[0].score || \" \",\n HomeAway: msg.payload.header.competitions[0].competitors[0].homeAway || \" \",\n Winner: msg.payload.header.competitions[0].competitors[0].winner || \" \",\n\n },\n opponent: {\n Name: msg.payload.header.competitions[0].competitors[1].team.displayName || \" \",\n Logo: msg.payload.boxscore.teams[1].team.logo || 'https://a.espncdn.com/i/teamlogos/soccer/500/default-team-logo-500.png',\n Color: \"#\" + msg.payload.header.competitions[0].competitors[1].team.color || \" \",\n Abbreviation: msg.payload.header.competitions[0].competitors[1].team.abbreviation || \" \",\n Placar: msg.payload.header.competitions[0].competitors[1].score || \" \",\n HomeAway: msg.payload.header.competitions[0].competitors[1].homeAway || \" \",\n Winner: msg.payload.header.competitions[0].competitors[1].winner || \" \",\n },\n statistics: [\n { stat_name: \"Chances Claras\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[26]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[26]?.displayValue || \" \" },\n { stat_name: \"Faltas\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[0]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[0]?.displayValue || \" \" },\n { stat_name: \"Cartões Amarelos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[1]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[1]?.displayValue || \" \" },\n { stat_name: \"Cartões Vermelhos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[2]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[2]?.displayValue || \" \" },\n { stat_name: \"Impedimentos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[3]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[3]?.displayValue || \" \" },\n { stat_name: \"Escanteios\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[4]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[4]?.displayValue || \" \" },\n { stat_name: \"Defesas\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[5]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[5]?.displayValue || \" \" },\n { stat_name: \"Posse de Bola\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[6]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[6]?.displayValue || \" \" },\n { stat_name: \"Total de Chutes\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[7]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[7]?.displayValue || \" \" },\n { stat_name: \"Chutes a Gol\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[8]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[8]?.displayValue || \" \" },\n { stat_name: \"Gols de Pênalti\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[11]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[11]?.displayValue || \" \" },\n { stat_name: \"Passes Certos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[12]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[12]?.displayValue || \" \" },\n { stat_name: \"Total de Passes\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[13]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[13]?.displayValue || \" \" },\n { stat_name: \"Cruzamentos\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[16]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[16]?.displayValue || \" \" },\n { stat_name: \"Chutes Bloqueados\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[21]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[21]?.displayValue || \" \" },\n { stat_name: \"Desarmes\", team: msg.payload.boxscore?.teams?.[0]?.statistics?.[23]?.displayValue || \" \", opponent: msg.payload.boxscore?.teams?.[1]?.statistics?.[23]?.displayValue || \" \" },\n { stat_name: \"Placar\", team: msg.payload.header?.competitions?.[0]?.competitors?.[0]?.score || \" \", opponent: msg.payload.header?.competitions?.[0]?.competitors?.[1]?.score || \" \" }\n ], \n Gols: []\n};\n\n// Verifica se msg.payload.keyEvents existe e é um array\nif (msg.payload && Array.isArray(msg.payload.keyEvents)) {\n msg.payload.keyEvents.forEach(event => {\n if (event.type && event.type.text && /^Gol|Goal/.test(event.type.text)) {\n const golInfo = {\n jogador: event.participants && event.participants[0]?.athlete?.displayName || \" \",\n time: event.team?.displayName || \" \",\n minuto: event.clock?.displayValue || \" \",\n descricao: event.text || \" \",\n idTime: event.team?.id || \" \"\n };\n\n // Adiciona o gol ao array de gols\n last_match_statistics.Gols.push(golInfo);\n }\n });\n}\n\n// Armazena tudo no flow\nflow.set(\"LastMatchStatistics\", last_match_statistics);\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1570,"y":440,"wires":[[]]},{"id":"1ff74e92a1d579ad","type":"switch","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Tempo antes da partida para ser avisado","property":"data.new_state.attributes.kickoff_in","propertyType":"msg","rules":[{"t":"eq","v":"em 5 minutos","vt":"str"},{"t":"eq","v":"O jogo já começou!","vt":"str"},{"t":"eq","v":"O pacote foi assinado para","vt":"str"}],"checkall":"true","repair":false,"outputs":3,"x":440,"y":680,"wires":[["f7b5919e868a446b"],["15c8cbd5f00bb3f9"],[]]},{"id":"7c7a66e4d63a5a77","type":"api-current-state","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Em casa?","server":"db1ab0af.caa65","version":3,"outputs":2,"halt_if":"home","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.kelvin_em_casa","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload_state","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":760,"y":640,"wires":[["94d83653c7a82417"],[]]},{"id":"dcdd298101fecbeb","type":"template","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Deseja receber os eventos da partida?","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"O jogo {{data.new_state.attributes.team_name}} contra {{data.new_state.attributes.opponent_name}} \" vai começar. Deseja receber as informações da partida?","output":"str","x":850,"y":720,"wires":[["5e2e8d02cb92eb59"]]},{"id":"fdd13a61666334d8","type":"link out","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Envia pergunta telegram","mode":"link","links":["3dcd30a4d7ef48cc"],"x":1190,"y":720,"wires":[],"l":true},{"id":"1df59ada36d3f556","type":"switch","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Contém a palavra \"O jogo\" na mensagem telegram","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"O jogo","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":645,"y":780,"wires":[["c51ae48feed0bfdb"]],"l":false},{"id":"c51ae48feed0bfdb","type":"change","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"resposta = YES","rules":[{"t":"set","p":"payload","pt":"msg","to":"YES","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":760,"y":780,"wires":[["89b5158aaa0e37a2"]]},{"id":"c4856b5024f17dde","type":"link in","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Resposta YES","links":["9bd24a5d37976115"],"x":520,"y":780,"wires":[["1df59ada36d3f556"]],"icon":"node-red-contrib-telegrambot-home/telegram.png","l":true},{"id":"1ee62e5082c06f8d","type":"trigger","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Valida cada 10s","op1":"","op2":"","op1type":"pay","op2type":"str","duration":"-10","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":220,"y":860,"wires":[["95cdfa9eecce0e19"]]},{"id":"95cdfa9eecce0e19","type":"api-current-state","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Atributos - Last play","server":"db1ab0af.caa65","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.espn_futebol","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":420,"y":860,"wires":[["43b301c6ec80698b"]]},{"id":"535ce6dd9a08d86a","type":"function","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Último evento","func":"const eventosData = msg.data.attributes.eventos;\n\n// Mapeamento de tipos de eventos para emoticons\nconst tipoEventoEmoticons = {\n \"Gol\": \"⚽ \",\n \"Cartão amarelo\": \"🟨 \",\n \"Cartão vermelho\": \"🟥 \",\n \"Gol de pênalti\": \"⚽ \",\n \"substituição\": \"🔄 \",\n \"Gol de falta\": \"⚽ \",\n \"Intervalo\": \"⏸️ \"\n};\n\n// Verifica se os dados existem antes de acessar as propriedades\nif (eventosData) {\n // Últimos elementos de cada array\n const ultimoClock = eventosData.arrayClock[eventosData.arrayClock.length - 1] || \"\";\n const ultimoType = eventosData.arrayType[eventosData.arrayType.length - 1] || \"\";\n const ultimoParticipant = eventosData.arrayParticipants[eventosData.arrayParticipants.length - 1] || \"\";\n const ultimoParticipant2 = eventosData.arrayParticipants2 ? eventosData.arrayParticipants2[eventosData.arrayParticipants2.length - 1] : \"\"; // Verifica se há um segundo participante\n const ultimoTeamAbbreviation = eventosData.arrayTeamAbbreviation[eventosData.arrayTeamAbbreviation.length - 1] || \"\";\n\n // Converte o tipo de evento, se necessário\n let tipoEventoConvertido = ultimoType;\n if (ultimoType === \"Goal - Free-kick\") {\n tipoEventoConvertido = \"Gol de falta\";\n } else if (ultimoType === \"Meio tempo\") {\n tipoEventoConvertido = \"Intervalo\";\n }\n\n // Adiciona os últimos valores ao objeto msg\n msg.ultimoClock = ultimoClock;\n msg.ultimoType = tipoEventoConvertido;\n msg.ultimoParticipant = ultimoParticipant;\n msg.ultimoParticipant2 = ultimoParticipant2;\n msg.ultimoTeamAbbreviation = ultimoTeamAbbreviation;\n\n // Obtém o emoticon correspondente ao tipo de evento\n const emoticon = tipoEventoEmoticons[tipoEventoConvertido] || \"📋 \"; // Padrão: ponto de interrogação\n\n // Combina os últimos elementos para formar o último evento\n if (tipoEventoConvertido.toLowerCase() === \"substituição\") {\n // Se for substituição, inclui o segundo participante\n msg.ultimoEvento = `🕔 ${msg.ultimoClock}\\n${emoticon} ${tipoEventoConvertido}\\n\\n${msg.ultimoParticipant} → ${msg.ultimoParticipant2} (${msg.ultimoTeamAbbreviation})`.trim();\n } else {\n // Para outros eventos, mantém o formato padrão\n msg.ultimoEvento = `🕔 ${msg.ultimoClock}\\n${emoticon} ${tipoEventoConvertido}\\n\\n${msg.ultimoParticipant} (${msg.ultimoTeamAbbreviation})`.trim();\n }\n\n // Compara o último evento com o evento armazenado no fluxo\n const ultimoEventoAnterior = flow.get(\"UltimoEvento\") || \"\";\n if (ultimoEventoAnterior !== msg.ultimoEvento) {\n // Atualiza o evento no fluxo\n flow.set(\"UltimoEvento\", msg.ultimoEvento);\n\n // Retorna a mensagem se o último evento mudou\n return [msg, null];\n }\n}\n\n\nconst eventosGols = msg.data.attributes.eventos;\nconst gols = msg.data.attributes.last_match.Gols;\n\n// Verifica se há dados de eventos e gols antes de acessar as propriedades\nif (eventosGols && gols) {\n // Último gol do array de gols\n const ultimoGol = gols[gols.length - 1] || null;\n\n if (ultimoGol) {\n // Extrai informações relevantes do último gol\n const minuto = ultimoGol.minuto || \"\";\n const jogador = ultimoGol.jogador || \"\";\n const time = ultimoGol.time || \"\";\n const descricao = ultimoGol.descricao || \"\";\n\n // Combina as informações do último gol\n msg.ultimoGol = `🕔 ${minuto}\\n⚽ ${jogador} (${time})\\n\\n${descricao}`.trim();\n\n // Compara o último gol com o gol armazenado no fluxo\n const ultimoGolAnterior = flow.get(\"UltimoGol\") || \"\";\n if (ultimoGolAnterior !== msg.ultimoGol) {\n // Atualiza o último gol no fluxo\n flow.set(\"UltimoGol\", msg.ultimoGol);\n\n // Retorna a mensagem se o último gol mudou\n return [null, msg];\n }\n }\n}\n","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":860,"wires":[["8189baadf4ab750a"],["a926e78d88fe9810"]]},{"id":"8189baadf4ab750a","type":"template","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Evento","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"👟 EVENTO FUTEBOL 👟\n\n\n{{{flow.LiveMatchStatistics.team.Name}}} {{{flow.LiveMatchStatistics.team.Placar}}} - {{{flow.LiveMatchStatistics.opponent.Placar}}} {{{flow.LiveMatchStatistics.opponent.Name}}}\n\n{{{ultimoEvento}}}\n\n","output":"str","x":920,"y":840,"wires":[["27f947af362f82e5"]]},{"id":"dbe3b8f77ca52e13","type":"link out","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Envia msg telegram","mode":"link","links":["0d20d93e76ce11d7"],"x":1220,"y":840,"wires":[],"l":true},{"id":"8ddfd8a6f41862b8","type":"change","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"reset","rules":[{"t":"set","p":"reset","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":920,"wires":[["ec8285a21126007c","2318f6a557b38709"]]},{"id":"43b301c6ec80698b","type":"switch","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Ao vivo?","property":"data.attributes.kickoff_in","propertyType":"msg","rules":[{"t":"eq","v":"O jogo já começou!","vt":"str"},{"t":"neq","v":"O jogo já começou!","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":600,"y":860,"wires":[["535ce6dd9a08d86a"],["8ddfd8a6f41862b8"]]},{"id":"89b5158aaa0e37a2","type":"template","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Aviso ","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"👟 EVENTO FUTEBOL 👟\n\n⚠️ ⚠️ ⚠️ ⚠️ ⚠️ ⚠️\n\nAssim que tiver eventos nessa partida você será notificado!! \n\n","output":"str","x":910,"y":780,"wires":[["1ee62e5082c06f8d","3c292a9d23c38303"]]},{"id":"db91ab1997105d19","type":"server-state-changed","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Entidade - Atributos","server":"db1ab0af.caa65","version":6,"outputs":1,"exposeAsEntityConfig":"","entities":{"entity":["sensor.espn_futebol"],"substring":[],"regex":[]},"outputInitially":false,"stateType":"str","ifState":"","ifStateType":"str","ifStateOperator":"is","outputOnlyOnStateChange":false,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":170,"y":680,"wires":[["1ff74e92a1d579ad"]]},{"id":"f3a6d843c5f9e4dd","type":"template","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Fim de jogo","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"👟 EVENTO FUTEBOL - FIM DE JOGO 👟\n\n\n {{{flow.LiveMatchStatistics.team.Name}}} {{{flow.LiveMatchStatistics.team.Placar}}} - {{{flow.LiveMatchStatistics.opponent.Placar}}} {{{flow.LiveMatchStatistics.opponent.Name}}}\n\nResumo da partinda:\n\n👇👇👇👇👇\n\n{{{flow.Eventos.stringTodosJuntos}}}\n","output":"str","x":930,"y":920,"wires":[["f125c3cc80cc6236","ec8285a21126007c"]]},{"id":"bf58e8ae47278ecb","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"24 ou 25?","func":"// CAMPEONATOS 2025\nif (msg.payload.events.length != 0) {\n return [msg,null]\n} \n// CAMPEONATOS 2024\nelse {\n msg.url = \"https://site.web.api.espn.com/apis/site/v2/sports/soccer/all/teams/\" + msg.id + \"/schedule?region=br&lang=pt&season=2024\"\n msg.headers = {\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15\"\n };\n return [null,msg]\n}\n","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1120,"y":420,"wires":[["ba6a5420f05f24c8"],["84e55e786724e195"]]},{"id":"e0151e09bd7c242d","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"URL ultimo jogo","func":"msg.url = \"https://site.web.api.espn.com/apis/site/v2/sports/soccer/all/teams/\" + msg.id +\"/schedule?region=br&lang=pt&season=2024\"\nmsg.headers = {\n \"User-Agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15\"\n};\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":900,"y":480,"wires":[["2975c186bb2d8314"]]},{"id":"2975c186bb2d8314","type":"http request","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"c159a5512ccbc528","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":1025,"y":480,"wires":[["7154ae351a81c9bb"]],"l":false},{"id":"a926e78d88fe9810","type":"template","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Gol","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"👟 EVENTO FUTEBOL - GOOOOOOL 👟\n\n {{{flow.LiveMatchStatistics.team.Name}}} {{{flow.LiveMatchStatistics.team.Placar}}} - {{{flow.LiveMatchStatistics.opponent.Placar}}} {{{flow.LiveMatchStatistics.opponent.Name}}}\n\n👇👇👇👇👇\n\n{{{ultimoGol}}}\n","output":"str","x":910,"y":880,"wires":[["f125c3cc80cc6236"]]},{"id":"5e2e8d02cb92eb59","type":"delay","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"hour","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":1045,"y":720,"wires":[["fdd13a61666334d8"]],"l":false},{"id":"4010e6284a33c629","type":"subflow:4b724119114337ed","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"","env":[{"name":"msg.alexa","value":"sala","type":"str"},{"name":"vol_fala","value":"70","type":"num"},{"name":"vol_padrao","value":"50","type":"num"}],"x":1060,"y":640,"wires":[[]]},{"id":"9d6bc8f7e187f74d","type":"function","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"MSG","func":"msg.alexa = \"O jogo \" + msg.data.new_state.attributes.team_name + \" contra \" + msg.data.new_state.attributes.opponent_name + \"vai começar.\"\n\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":930,"y":640,"wires":[["4010e6284a33c629"]]},{"id":"94d83653c7a82417","type":"delay","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"hour","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":855,"y":640,"wires":[["9d6bc8f7e187f74d"]],"l":false},{"id":"03fee0dbf228e28e","type":"link in","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"link in 1","links":["778e632e07e842af"],"x":95,"y":860,"wires":[["1ee62e5082c06f8d"]]},{"id":"2e522e59d89df48d","type":"api-current-state","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Sensor","server":"db1ab0af.caa65","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.espn_futebol","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":500,"y":320,"wires":[["0bee37d94f1810a8"]]},{"id":"0bee37d94f1810a8","type":"switch","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Ao vivo?","property":"data.attributes.kickoff_in","propertyType":"msg","rules":[{"t":"eq","v":"O jogo já começou!","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":640,"y":320,"wires":[["778e632e07e842af"]]},{"id":"778e632e07e842af","type":"link out","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"link out 1","mode":"link","links":["03fee0dbf228e28e"],"x":735,"y":320,"wires":[]},{"id":"b72982ef40952e70","type":"function","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"zerar flow","func":"if (msg.state != \"Time não encontrado, tente novamente\") {\n\n flow.set(\"Eventos\", \" \")\n flow.set(\"UltimoEvento\", \" \")\n flow.set(\"UltimoGol\", \" \")\n\n return msg\n}\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":300,"y":320,"wires":[["0526e3eb265894a8"]]},{"id":"0526e3eb265894a8","type":"delay","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","pauseType":"delay","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":395,"y":320,"wires":[["2e522e59d89df48d"]],"l":false},{"id":"2318f6a557b38709","type":"switch","z":"37e033d25f1ace08","g":"be6cfbb1827a395c","name":"Contém a palavra \"O jogo\" na mensagem telegram","property":"Eventos","propertyType":"flow","rules":[{"t":"neq","v":" ","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":825,"y":920,"wires":[["f3a6d843c5f9e4dd"]],"l":false},{"id":"98cc076ffc24034e","type":"api-current-state","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"Time","server":"db1ab0af.caa65","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_text.espn_team","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"state","propertyType":"msg","value":"","valueType":"entityState"},{"property":"timestamp","propertyType":"msg","value":"iso","valueType":"date"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":170,"y":400,"wires":[["b987a171168b0a1b"]]},{"id":"dc1e39d9c8b290f2","type":"switch","z":"37e033d25f1ace08","g":"4f1473862f7c6795","name":"","property":"payload.results[0].type","propertyType":"msg","rules":[{"t":"eq","v":"team","vt":"str"},{"t":"neq","v":"team","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":455,"y":400,"wires":[["91fbbd052bee174d"],[]],"l":false},{"id":"7275219dbc3a8c8d","type":"ha-entity-config","server":"db1ab0af.caa65","deviceConfig":"","name":"espn_tabela","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"espn_tabela"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false},{"id":"db1ab0af.caa65","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"c159a5512ccbc528","type":"tls-config","name":"","cert":"","key":"","ca":"","certname":"","keyname":"","caname":"","servername":"","verifyservercert":false,"alpnprotocol":""},{"id":"0ec7baaca4a6d27b","type":"ha-entity-config","server":"db1ab0af.caa65","deviceConfig":"","name":"espn_futebol","version":6,"entityType":"sensor","haConfig":[{"property":"name","value":"espn_futebol"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false}]
OBS IMPORTANTE: o nome dos sensores tem que ser iguais aos que eu fiz, caso mude, altere em todos os lugares para não ter erros.
- sensor.espn_futebol
- sensor.espn_tabela
A parte de automações me avisem se esta ok para vocês, testem com times e jogos grandes pois nem todos os jogos estão dando dados ao vivo, talvez quando começar o brasileirão funcione bem.
Qualquer coisa postem ai. Abraço