Ir para conteúdo
biakelly

Regra para mensagens de BOT Telegram com PHP

Recommended Posts

Oi

 

Criei um bot com algumas regras e estou meia insegura quanto as chamadas desse bot.

 

Bem tenho este trecho no código:

if (strpos($message, "/price") === 0) {
    file_get_contents($path . "/sendmessage?chat_id=" . $chatId . "&text=$price");

} elseif (strpos($message, "/help") === 0) {
    file_get_contents($path . "/sendMessage?chat_id=" . $chatId . "&text=$help");

} elseif (strpos($message, "/contract") === 0) {
    file_get_contents($path . "/sendmessage?chat_id=" . $chatId . "&text=$contract");

Ele funciona bem, mas como ja perceberam inicio com o If e vou adicionando elseif para as demais chamadas total 11. Esta correto desta forma ou estou fazendo muita besteira? Tem alguma forma de melhorar essa quantidade de elseif?

 

Tenho mais 8 regras assim até finalizar as chamadas. Agora pintou a dúvida se realmente estou fazendo corretamente

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá @biakelly.

 

Não há nada de errado em usar vários ifs encadeados, tirando a repetição de código, mas vou lhe apresentar algumas sugestões para melhorar seu código.

 

Uma maneira de otimizar, seria encapsulando a lógica de cada if em uma ou duas funções, mas pensando no todo, acredito que essa abordagem seja melhor:

 

1 - Se $message não tiver mais informações do que /price, /help ou /contract, digo, se não tiver a chance de ser /price/TRX, por exemplo, você pode usar essa varíavel, do contrário, você deve limpá-la para separar as informações relacionadas à rota.

No exemplo acima, a barra inícial (/) é sua raíz, price é o recurso desejado, TRX é um parâmetro que filtra esse recurso, e por isso desmembrar em diferentes variáveis seria um bom ponto de partida.

 

Um primeiro passo seria validar o endpoint (endereço) completo. Isso poderia ser feito com uma expressão regular, por exemplo. Vou pular essa etapa pois desconheço a formatação completa da API que você está criando. Ainda assim podemos prosseguir com o raciocínio.

 

Prosseguindo com o mesmo exemplo, vamos assumir que o endpoint requisitado seja /price/TRX.

1 - Removemos as barras no início e no fim do endpoint:

// "/trim", "trim", "trim/" ou "/trim/" viram ===> "trim"
// No nosso exemplo, $message passará a ser "price/TRX"
$message = trim( $message, '/' );

 

2 - Pegamos apenas o nome do recurso a ser acessado (price / help / contract).

$endpoint_chunks = explode( '/', $message );// dividimos $message por cada "/"
$resource = array_shift( $endpoint_chunks );// "price", que é o primeiro elemento do array

 

3 - Criamos uma lista imutável de rotas conhecidas e permitidas:

define( 'ROUTES', [
    'price',
    'help',
    'contract',
] );

 

4 - Verificamos se a requisição se dá em uma dessas rotas, senão, interrompemos:

if ( !in_array( $resource, ROUTES ) )// "price" existe em ROUTES? Se não, interrompa.
    die( '404 - Impossível continuar. Resource incorreto.' );

 

5 - No seu exemplo, a única coisa que muda entre um file_get_contents e outro é a variável $price / $help, $contract. Isso poderia ser feito utilizando variáveis variáveis:

// Exemplo não relacionado:
// $numero = 5;
// $var = 'numero';
// echo $$var;// Saída: 5

// No caso, se $resource for === string 'price', $text vai ter o mesmo valor da sua var $price
$text = $$resource;

Agora é só rodar o nosso novo file_get_contents genérico:

file_get_contents( $path . "/sendmessage?chat_id=" . $chatId . "&text={$text}" );

 

Ou, ainda: crie um diretório chamado logicas ou resources, por exemplo. Dentro, insira os arquivos price.php, help.php, etc.php.

E agora, faça:

require_once "logicas/{$resource}.php";// no nosso caso vai resultar em: logicas/price.php

 

E dentro de cada arquivo você elabora as instruções de cada resource, mantendo limpo o arquivo principal.

 

Reunindo tudo:

<?php
$message = '/price/TRX';// seu $message original. Pode tirar essa linha

$message = trim( $message, '/' );
$endpoint_chunks = explode( '/', $message );
$resource = array_shift( $endpoint_chunks );

define( 'ROUTES', [
    'price',
    'help',
    'contract',
] );

if ( !in_array( $resource, ROUTES ) )
    die( 'Impossível continuar. Endpoint incorreto.' );

$text = $$resource;

file_get_contents( $path . "/sendmessage?chat_id=" . $chatId . "&text={$text}" );

// Aqui viria o require_once, para adicionar lógicas inerentes a cada resource
// Lembrando que para esse código rodar, $path, $chatId e $price precisam estar definidas.
// Essas variáveis eu assumi que estavam definidas baseado no código que você postou.

 

Onde esse código é melhor que o anterior? No fato de que agora você pode ter 50 endereços diferentes e o código não aumenta em quantidade de linhas. Além disso, com o require, você pode definir comportamentos de cada resource respectivamente em seu próprio arquivo.

 

Os princípios que citei aqui são versões muito simplificadas de micro frameworks robustas voltadas para a crição de APIs, como o Lumen ou Slim, que seria minha sugestão final: considerar utilizar uma delas para facilitar seu trabalho. Por serem micro frameworks (e não frameworks completas), são mais simples e diretas no que se propõem. :smiley:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Nossa @Matheus Tavares eu achei mais simples seu code, posso abusar um pouco?

 

estou fazendo assim:

 

<?php
$path = "https://api.telegram.org/botxxxxxUqg";
$update = json_decode(file_get_contents("php://input"), TRUE);

$chatId = $update["message"]["chat"]["id"];
$message = $update["message"]["text"];

$message = trim( $message, '/' );
$endpoint_chunks = explode( '/', $message );
$resource = array_shift( $endpoint_chunks );

define( 'ROUTES', [
    'prices',
    symbol',
] );

if ( !in_array( $resource, ROUTES ) )
    die( 'Impossível continuar. Endpoint incorreto.' );

$text = $$resource;

file_get_contents( $path . "/sendmessage?chat_id=" . $chatId . "&text={$text}" );

$price = json_decode(file_get_contents("https://apilist.tronscan.org/api/contract?contract=TLRt2GZrfxBsYWjsh7wjmZbXT3WKMoEws9"), TRUE)["trc20_tokens"]["price_trx"];

$symbol = json_decode(file_get_contents("https://apilist.tronscan.org/api/contract?contract=TLRt2GZrfxBsYWjsh7wjmZbXT3WKMoEws9"), TRUE)["trc20_tokens"]["symbol"];


$prices = "<b>" . $price . "</b> TRX";
$prices = "<b>" . $symbol . "</b> TRX";

 

Acho que estou errando alguma coisa, esse danado supply circulante esta me deixando louca

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá @biakelly.

 

Então... precisava saber qual o erro que está dando para ver o que pode estar acontecendo, mas o que consigo ver de antemão é que está faltando um carectere de aspas aqui:

define( 'ROUTES', [
    'prices',
    symbol',  // <---- antes de symbol devia ter um '
] );

 

Se não for esse problema, vou precisar de mais informações pra poder ajudar você :)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tente exibir a string do seu file_get_contents para ver se está correta:

echo $path . "/sendmessage?chat_id=" . $chatId . "&text={$text}";

Com esse echo você vai ver exatamente o que está sendo enviado para dentro do file_get_contents e assim verificar se está coerente com o que você desejava.

 

Ao meu ver é o principal ponto do seu código que poderia apresentar problemas (caso alguma variável esteja incorreta, ela impactaria em toda a função).

 

Se não encontrar nada de errado, faça o mesmo com as demais variáveis.

Utilize print_r ou var_dump nelas. Exemplo:

print_r( $update );

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi @Matheus Tavares :)

 

Descobri o problema em um dos comandos, por algum motivo usar 400 caracteres em texto quando inicio a chamada do comando no Telegram e ele não responde, então reduzi para 200 caracteres e funcionou. Estranho pois ja vi comandos em outros bots que imprimem texto com mais de 400 caracteres. Enfim. rs

 

Um dos comandos esta certinho, usei sua dica para para exibir o resultado da variavel. In loco funciona, mas no Telegram nem sinal de vida kkk ai ai.

 

Bem, como só falta um comando, vou deixa-lo de lado por enquanto 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Buguei buguei e estou nesse carinha aqui:

 

quando rodo este trecho no Bot ele retorna com "Array"

 

O objetivo era mostrar 2 links ao chamar o "/link"

elseif (strpos($message, "/links") === 0) {
    file_get_contents($path . "/sendmessage?chat_id=" . $chatId . "&text=$keyboard");
} 

$keyboard = ['inline_keyboard' => [[
    ['Alunos', 'url' => 'https://www.link.com/admin/alunos/'],
    ['notas', 'url' => 'https://www.link.com/admin/notas/']
]]];

tentei alterar com um var mas da mais erros, preciso de uma luz aqui se possível

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá @biakelly, tudo bem?

 

Estava um pouco indisposto nos últimos dias e não pude dar atenção à sua dúvida antes, mas vamos lá:

 

Pelo que entendi as linhas estão invertidas, certo? $keyboard vem antes do if, mas na hora de colar você trocou a ordem, é isso? Pois do contrário não faria muito sentido.

 

Assumindo que keyboard venha antes, e portanto é um array, quando você joga ele no file_get_contents você está unindo uma string com um array, o que não pode ser feito. String é apenas texto, array é um conjunto de dados de diferentes tipos.

<?php
$keyboard = ['inline_keyboard' => [[
    ['Alunos', 'url' => 'https://www.link.com/admin/alunos/'],
    ['notas', 'url' => 'https://www.link.com/admin/notas/']
]]];

echo "Concatenação de string com array: {$keyboard}";

O exemplo acima retorna isso:

Concatenação de string com array: Array (e uma mensagem de erro, pois essa concatenação está incorreta, mas o PHP se forçou a tentar executá-la mesmo assim).

 

Você precisa portanto formatar esse array para uma string. Mas antes vamos fazer uns pequenos ajustes na construção do array em si:

$keyboard = ['inline_keyboard' => [[// aqui está criando 2 arrays. Apenas 1 seria suficiente
    ['Alunos', 'url' => 'https://www.link.com/admin/alunos/'],
    ['notas', 'url' => 'https://www.link.com/admin/notas/']
]]];

//Portanto:
$keyboard = ['inline_keyboard' => [
    ['Alunos', 'url' => 'https://www.link.com/admin/alunos/'],
    ['notas', 'url' => 'https://www.link.com/admin/notas/']
]];

// Também poderíamos adicionar uma chave para 'alunos' e 'notas', assim como as URLs:
$keyboard = ['inline_keyboard' => [
    [ 'name' => 'Alunos', 'url' => 'https://www.link.com/admin/alunos/'],
    [ 'name' => 'notas', 'url' => 'https://www.link.com/admin/notas/']
]];// agora sim

O próximo passo seria formatar a string.

Isso poderia ser feito com um foreach por exemplo. Veja:

$string = '';
foreach ( $keyboard[ 'inline_keyboard' ] as $values ) {
    $name = $values[ 'name' ];
    $url = $values[ 'url' ];
    
    $string .= "{$name}: {$url}\n";
}

echo $string;

 

Resultado:

Alunos: https://www.link.com/admin/alunos/
notas: https://www.link.com/admin/notas/

Por fim, você só precisaria enviar essa string na URL, mas você não pode simplesmente inserir essa string, pois ela contém caracteres que iriam deformar a requisição do file_get_contents.

 

Você precisa utilizar urlencode. Assim:

file_get_contents($path . "/sendmessage?chat_id=" . $chatId . '&text=' . urlencode( $string ));

O urlencode converte caracteres como espaços, quebras de linha, barras, em suas representações amigáveis para o tráfego na URL :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi @Matheus Tavares :)

 

Como você esta? Espero que esteja tudo bem

 

Bots são novos pra mim e alguns recursos como o Inline_keyboard descobri recentemente

 

Vou adapta-lo por aqui

20 minutos atrás, Matheus Tavares disse:

$string = ''; foreach ( $keyboard[ 'inline_keyboard' ] as $values ) { $name = $values[ 'name' ]; $url = $values[ 'url' ]; $string .= "{$name}: {$url}\n"; } echo $string;

 

Eu tinha esquecido que precisava de uma "urlencode" estava fazendo totalmente errado kk

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi @biakelly, ainda não estou 100%, mas estou melhorando bem rápido.

 

Então, a minha resposta anterior estava se referindo apenas à união de strings com arrays baseado na sua tentativa, mas você disse algo que me chamou atenção:

17 minutos atrás, biakelly disse:

Bots são novos pra mim e alguns recursos como o Inline_keyboard descobri recentemente

Talvez essa (a técnica que estava discutindo) não seja a forma correta de fazer o que você precisa.

Você precisa ver bem a documentação do Telegram e alguns exemplos sobre esse recurso.

 

Veja: https://stackoverflow.com/questions/45894518/how-to-create-inline-buttons-in-php-bot-telegram

https://stackoverflow.com/questions/60529715/telegram-inline-keyboards-php

https://stackoverflow.com/questions/41709382/telegram-bot-inline-keyboard-not-displaying-php

https://github.com/php-telegram-bot/inline-keyboard-pagination

 

Observe que nesses exemplos eles usam um padrão diferente do que mencionei, além de utilizarem json_encode e não urlencode.

 

Talvez esse tutorial possa lhe ajudar nesse sentido:

https://luizmarcus.com/php/utilizando-inline-keyboard-em-um-bot-para-o-telegram/

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi @Matheus Tavares

 

 Se cuida viu, não sei o que se trata mas saúde é prioridade

 

 Ontem eu estava usando json_encode, o bot até responde mas com a mensagem 'array', inline é um pouco difícil de entender kkk mas não desisto

 

Acho que esta mais complexo pela  forma como fiz os outros comandos, estou olhando esses links que passou, agora é questão de honra faze-lo funcionar 

 

Esse bot tornou-se meu inimigo pessoal kkk

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.