Jump to content
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

Share this post


Link to post
Share on other 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:

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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ê :)

Share this post


Link to post
Share on other 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 );

 

Share this post


Link to post
Share on other 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 

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other 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/

Share this post


Link to post
Share on other 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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.