Commit 45aa5f7a authored by Armando Lüscher's avatar Armando Lüscher Committed by GitHub

Merge pull request #543 from noplanman/bot_api_3.0

Bot api 3.0
parents b58500f0 c1af4b91
......@@ -5,6 +5,7 @@ Exclamation symbols (:exclamation:) note something of importance e.g. breaking c
## [Unreleased]
### Added
- New entities, methods, update types and inline keyboard button for Payments (Bot API 3.0).
### Changed
- [:exclamation:][unreleased-correct-printerror] Corrected `ServerResponse->printError` method to print by default and return by setting `$return` parameter.
### Deprecated
......
......@@ -22,12 +22,14 @@ use Longman\TelegramBot\Exception\TelegramException;
* @method string getCallbackData() Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes
* @method string getSwitchInlineQuery() Optional. If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. Can be empty, in which case just the bot’s username will be inserted.
* @method string getSwitchInlineQueryCurrentChat() Optional. If set, pressing the button will insert the bot‘s username and the specified inline query in the current chat's input field. Can be empty, in which case only the bot’s username will be inserted.
* @method string getPay() Optional. Specify True, to send a Pay button.
*
* @method $this setText(string $text) Label text on the button
* @method $this setUrl(string $url) Optional. HTTP url to be opened when button is pressed
* @method $this setCallbackData(string $callback_data) Optional. Data to be sent in a callback query to the bot when button is pressed, 1-64 bytes
* @method $this setSwitchInlineQuery(string $switch_inline_query) Optional. If set, pressing the button will prompt the user to select one of their chats, open that chat and insert the bot's username and the specified inline query in the input field. Can be empty, in which case just the bot’s username will be inserted.
* @method $this setSwitchInlineQueryCurrentChat(string $switch_inline_query_current_chat) Optional. If set, pressing the button will insert the bot‘s username and the specified inline query in the current chat's input field. Can be empty, in which case only the bot’s username will be inserted.
* @method $this setPay(bool $pay) Optional. Specify True, to send a Pay button.
*/
class InlineKeyboardButton extends KeyboardButton
{
......@@ -45,7 +47,8 @@ class InlineKeyboardButton extends KeyboardButton
array_key_exists('url', $data) ||
array_key_exists('callback_data', $data) ||
array_key_exists('switch_inline_query', $data) ||
array_key_exists('switch_inline_query_current_chat', $data)
array_key_exists('switch_inline_query_current_chat', $data) ||
array_key_exists('pay', $data)
);
}
......@@ -60,14 +63,14 @@ class InlineKeyboardButton extends KeyboardButton
$num_params = 0;
foreach (['url', 'callback_data', 'switch_inline_query', 'switch_inline_query_current_chat'] as $param) {
foreach (['url', 'callback_data', 'switch_inline_query', 'switch_inline_query_current_chat', 'pay'] as $param) {
if (!empty($this->getProperty($param))) {
$num_params++;
}
}
if ($num_params !== 1) {
throw new TelegramException('You must use only one of these fields: url, callback_data, switch_inline_query, switch_inline_query_current_chat!');
throw new TelegramException('You must use only one of these fields: url, callback_data, switch_inline_query, switch_inline_query_current_chat, pay!');
}
}
......@@ -77,8 +80,8 @@ class InlineKeyboardButton extends KeyboardButton
public function __call($method, $args)
{
// Only 1 of these can be set, so clear the others when setting a new one.
if (in_array($method, ['setUrl', 'setCallbackData', 'setSwitchInlineQuery', 'setSwitchInlineQueryCurrentChat'], true)) {
unset($this->url, $this->callback_data, $this->switch_inline_query, $this->switch_inline_query_current_chat);
if (in_array($method, ['setUrl', 'setCallbackData', 'setSwitchInlineQuery', 'setSwitchInlineQueryCurrentChat', 'setPay'], true)) {
unset($this->url, $this->callback_data, $this->switch_inline_query, $this->switch_inline_query_current_chat, $this->pay);
}
return parent::__call($method, $args);
......
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
/**
* Class Invoice
*
* This object contains basic information about an invoice.
*
* @link https://core.telegram.org/bots/api#invoice
*
* @method string getTitle() Product name
* @method string getDescription() Product description
* @method string getStartParameter() Unique bot deep-linking parameter that can be used to generate this invoice
* @method string getCurrency() Three-letter ISO 4217 currency code
* @method int getTotalAmount() Total price in the smallest units of the currency (integer, not float/double).
**/
class Invoice extends Entity
{
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
/**
* Class LabeledPrice
*
* This object represents a portion of the price for goods or services.
*
* @link https://core.telegram.org/bots/api#labeledprice
*
* @method string getLabel() Portion label
* @method int getAmount() Price of the product in the smallest units of the currency (integer, not float/double).
**/
class LabeledPrice extends Entity
{
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
/**
* Class OrderInfo
*
* This object represents information about an order.
*
* @link https://core.telegram.org/bots/api#orderinfo
*
* @method string getName() Optional. User name
* @method string getPhoneNumber() Optional. User's phone number
* @method string getEmail() Optional. User email
* @method ShippingAddress getShippingAddress() Optional. User shipping address
**/
class OrderInfo extends Entity
{
/**
* {@inheritdoc}
*/
public function subEntities()
{
return [
'shipping_address' => ShippingAddress::class,
];
}
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
use Longman\TelegramBot\Entities\User;
/**
* Class PreCheckoutQuery
*
* This object contains information about an incoming pre-checkout query.
*
* @link https://core.telegram.org/bots/api#precheckoutquery
*
* @method string getId() Unique query identifier
* @method User getFrom() User who sent the query
* @method string getCurrency() Three-letter ISO 4217 currency code
* @method int getTotalAmount() Total price in the smallest units of the currency (integer, not float/double).
* @method string getInvoicePayload() Bot specified invoice payload
* @method string getShippingOptionId() Optional. Identifier of the shipping option chosen by the user
* @method OrderInfo getOrderInfo() Optional. Order info provided by the user
**/
class PreCheckoutQuery extends Entity
{
/**
* {@inheritdoc}
*/
public function subEntities()
{
return [
'user' => User::class,
'order_info' => OrderInfo::class,
];
}
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
/**
* Class ShippingAddress
*
* This object represents a shipping address.
*
* @link https://core.telegram.org/bots/api#shippingaddress
*
* @method string getCountryCode() ISO 3166-1 alpha-2 country code
* @method string getState() State, if applicable
* @method string getCity() City
* @method string getStreetLine1() First line for the address
* @method string getStreetLine2() Second line for the address
* @method string getPostCode() Address post code
**/
class ShippingAddress extends Entity
{
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
/**
* Class ShippingOption
*
* This object represents one shipping option.
*
* @link https://core.telegram.org/bots/api#shippingoption
*
* @method string getId() Shipping option identifier
* @method string getTitle() Option title
**/
class ShippingOption extends Entity
{
/**
* {@inheritdoc}
*/
protected function subEntities()
{
return [
'prices' => LabeledPrice::class,
];
}
/**
* List of price portions
*
* This method overrides the default getPrices method and returns a nice array
*
* @return LabeledPrice[]
*/
public function getPrices()
{
$all_prices = [];
if ($these_prices = $this->getProperty('prices')) {
foreach ($these_prices as $prices) {
$new_prices = [];
foreach ($prices as $price) {
$new_prices[] = new LabeledPrice($price);
}
$all_prices[] = $new_prices;
}
}
return $all_prices;
}
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
use Longman\TelegramBot\Entities\User;
/**
* Class ShippingQuery
*
* This object contains information about an incoming shipping query.
*
* @link https://core.telegram.org/bots/api#shippingquery
*
* @method string getId() Unique query identifier
* @method User getFrom() User who sent the query
* @method string getInvoicePayload() Bot specified invoice payload
* @method ShippingAddress getShippingAddress() User specified shipping address
**/
class ShippingQuery extends Entity
{
/**
* {@inheritdoc}
*/
public function subEntities()
{
return [
'user' => User::class,
'shipping_address' => ShippingAddress::class,
];
}
}
<?php
/**
* This file is part of the TelegramBot package.
*
* (c) Avtandil Kikabidze aka LONGMAN <akalongman@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Longman\TelegramBot\Entities\Payments;
use Longman\TelegramBot\Entities\Entity;
/**
* Class SuccessfulPayment
*
* This object contains basic information about a successful payment.
*
* @link https://core.telegram.org/bots/api#successfulpayment
*
* @method string getCurrency() Three-letter ISO 4217 currency code
* @method int getTotalAmount() Total price in the smallest units of the currency (integer, not float/double).
* @method string getInvoicePayload() Bot specified invoice payload
* @method string getShippingOptionId() Optional. Identifier of the shipping option chosen by the user
* @method OrderInfo getOrderInfo() Optional. Order info provided by the user
* @method string getTelegramPaymentChargeId() Telegram payment identifier
* @method string getProviderPaymentChargeId() Provider payment identifier
**/
class SuccessfulPayment extends Entity
{
/**
* {@inheritdoc}
*/
public function subEntities()
{
return [
'order_info' => OrderInfo::class,
];
}
}
......@@ -10,6 +10,9 @@
namespace Longman\TelegramBot\Entities;
use Longman\TelegramBot\Entities\Payments\PreCheckoutQuery;
use Longman\TelegramBot\Entities\Payments\ShippingQuery;
/**
* Class Update
*
......@@ -23,6 +26,8 @@ namespace Longman\TelegramBot\Entities;
* @method InlineQuery getInlineQuery() Optional. New incoming inline query
* @method ChosenInlineResult getChosenInlineResult() Optional. The result of an inline query that was chosen by a user and sent to their chat partner.
* @method CallbackQuery getCallbackQuery() Optional. New incoming callback query
* @method ShippingQuery getShippingQuery() Optional. New incoming shipping query. Only for invoices with flexible price
* @method PreCheckoutQuery getPreCheckoutQuery() Optional. New incoming pre-checkout query. Contains full information about checkout
*/
class Update extends Entity
{
......@@ -39,6 +44,8 @@ class Update extends Entity
'inline_query' => InlineQuery::class,
'chosen_inline_result' => ChosenInlineResult::class,
'callback_query' => CallbackQuery::class,
'shipping_query' => ShippingQuery::class,
'pre_checkout_query' => PreCheckoutQuery::class,
];
}
......@@ -57,6 +64,8 @@ class Update extends Entity
'inline_query',
'chosen_inline_result',
'callback_query',
'shipping_query',
'pre_checkout_query',
];
foreach ($types as $type) {
if ($this->getProperty($type)) {
......
......@@ -132,6 +132,7 @@ class Request
'sendLocation',
'sendVenue',
'sendContact',
'sendInvoice',
'sendChatAction',
'getUserProfilePhotos',
'getFile',
......@@ -153,6 +154,8 @@ class Request
'getChatMember',
'answerCallbackQuery',
'answerInlineQuery',
'answerShippingQuery',
'answerPreCheckoutQuery',
'editMessageText',
'editMessageCaption',
'editMessageReplyMarkup',
......@@ -527,6 +530,7 @@ class Request
// Make sure to add the action being called as the first parameter to be passed.
array_unshift($data, $action);
// @todo Use splat operator for unpacking when we move to PHP 5.6+
return call_user_func_array('static::send', $data);
}
......@@ -559,8 +563,7 @@ class Request
array $data,
array $select_chats_params
) {
$callback_path = __NAMESPACE__ . '\Request';
if (!method_exists($callback_path, $callback_function)) {
if (!method_exists(Request::class, $callback_function)) {
throw new TelegramException('Method "' . $callback_function . '" not found in class Request.');
}
......@@ -570,7 +573,7 @@ class Request
if (is_array($chats)) {
foreach ($chats as $row) {
$data['chat_id'] = $row['chat_id'];
$results[] = call_user_func($callback_path . '::' . $callback_function, $data);
$results[] = call_user_func(Request::class . '::' . $callback_function, $data);
}
}
......@@ -630,6 +633,7 @@ class Request
'sendLocation',
'sendVenue',
'sendContact',
'sendInvoice',
'editMessageText',
'editMessageCaption',
'editMessageReplyMarkup',
......
......@@ -32,7 +32,7 @@ class InlineKeyboardButtonTest extends TestCase
/**
* @expectedException \Longman\TelegramBot\Exception\TelegramException
* @expectedExceptionMessage You must use only one of these fields: url, callback_data, switch_inline_query, switch_inline_query_current_chat!
* @expectedExceptionMessage You must use only one of these fields: url, callback_data, switch_inline_query, switch_inline_query_current_chat, pay!
*/
public function testInlineKeyboardButtonNoParameterFail()
{
......@@ -41,7 +41,7 @@ class InlineKeyboardButtonTest extends TestCase
/**
* @expectedException \Longman\TelegramBot\Exception\TelegramException
* @expectedExceptionMessage You must use only one of these fields: url, callback_data, switch_inline_query, switch_inline_query_current_chat!
* @expectedExceptionMessage You must use only one of these fields: url, callback_data, switch_inline_query, switch_inline_query_current_chat, pay!
*/
public function testInlineKeyboardButtonTooManyParametersFail()
{
......@@ -74,6 +74,13 @@ class InlineKeyboardButtonTest extends TestCase
'switch_inline_query_current_chat' => 'switch_inline_query_current_chat_value',
]);
},
function () {
new InlineKeyboardButton([
'text' => 'message',
'callback_data' => 'callback_data_value',
'pay' => true,
]);
},
];
$test_funcs[array_rand($test_funcs)]();
......@@ -85,6 +92,7 @@ class InlineKeyboardButtonTest extends TestCase
new InlineKeyboardButton(['text' => 'message', 'callback_data' => 'callback_data_value']);
new InlineKeyboardButton(['text' => 'message', 'switch_inline_query' => 'switch_inline_query_value']);
new InlineKeyboardButton(['text' => 'message', 'switch_inline_query_current_chat' => 'switch_inline_query_current_chat_value']);
new InlineKeyboardButton(['text' => 'message', 'pay' => true]);
}
public function testInlineKeyboardButtonCouldBe()
......@@ -101,6 +109,9 @@ class InlineKeyboardButtonTest extends TestCase
self::assertTrue(InlineKeyboardButton::couldBe(
['text' => 'message', 'switch_inline_query_current_chat' => 'switch_inline_query_current_chat_value']
));
self::assertTrue(InlineKeyboardButton::couldBe(
['text' => 'message', 'pay' => true]
));
self::assertFalse(InlineKeyboardButton::couldBe(['no_text' => 'message']));
self::assertFalse(InlineKeyboardButton::couldBe(['text' => 'message']));
......@@ -111,11 +122,14 @@ class InlineKeyboardButtonTest extends TestCase
self::assertFalse(InlineKeyboardButton::couldBe(
['switch_inline_query' => 'switch_inline_query_value']
));
self::assertFalse(InlineKeyboardButton::couldBe(['pay' => true]));
self::assertFalse(InlineKeyboardButton::couldBe([
'url' => 'url_value',
'callback_data' => 'callback_data_value',
'switch_inline_query' => 'switch_inline_query_value',
'switch_inline_query_current_chat' => 'switch_inline_query_current_chat_value',
'pay' => true,
]));
}
......@@ -126,23 +140,34 @@ class InlineKeyboardButtonTest extends TestCase
self::assertEmpty($button->getCallbackData());
self::assertEmpty($button->getSwitchInlineQuery());
self::assertEmpty($button->getSwitchInlineQueryCurrentChat());
self::assertEmpty($button->getPay());
$button->setCallbackData('callback_data_value');
self::assertEmpty($button->getUrl());
self::assertSame('callback_data_value', $button->getCallbackData());
self::assertEmpty($button->getSwitchInlineQuery());
self::assertEmpty($button->getSwitchInlineQueryCurrentChat());
self::assertEmpty($button->getPay());
$button->setSwitchInlineQuery('switch_inline_query_value');
self::assertEmpty($button->getUrl());
self::assertEmpty($button->getCallbackData());
self::assertSame('switch_inline_query_value', $button->getSwitchInlineQuery());
self::assertEmpty($button->getSwitchInlineQueryCurrentChat());
self::assertEmpty($button->getPay());
$button->setSwitchInlineQueryCurrentChat('switch_inline_query_current_chat_value');
self::assertEmpty($button->getUrl());
self::assertEmpty($button->getCallbackData());
self::assertEmpty($button->getSwitchInlineQuery());
self::assertSame('switch_inline_query_current_chat_value', $button->getSwitchInlineQueryCurrentChat());
self::assertEmpty($button->getPay());
$button->setPay(true);
self::assertEmpty($button->getUrl());
self::assertEmpty($button->getCallbackData());
self::assertEmpty($button->getSwitchInlineQuery());
self::assertEmpty($button->getSwitchInlineQueryCurrentChat());
self::assertSame(true, $button->getPay());
}
}
......@@ -24,7 +24,7 @@ class InlineKeyboardTest extends TestCase
{
private function getRandomButton($text)
{
$random_params = ['url', 'callback_data', 'switch_inline_query', 'switch_inline_query_current_chat'];
$random_params = ['url', 'callback_data', 'switch_inline_query', 'switch_inline_query_current_chat', 'pay'];
$param = $random_params[array_rand($random_params, 1)];
$data = [
'text' => $text,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment