Skip to content

Commit 09f1500

Browse files
authored
Merge pull request #58 from nutgram/exceptions
Add "handling exceptions" page
2 parents ade0daf + 81b7a6f commit 09f1500

File tree

3 files changed

+231
-118
lines changed

3 files changed

+231
-118
lines changed

docs/usage/exceptions.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# Handling Exceptions
2+
3+
Exceptions are a common part of programming.
4+
Normally, when an exception is raised, the program will crash.
5+
6+
In Nutgram, exceptions can be categorized into two main types:
7+
- **Exceptions**: These are exceptions that originate from your code.
8+
- **Telegram API Errors**: These are errors that come from the Telegram Bot API.
9+
10+
## Software Exceptions
11+
12+
Software exceptions are errors that occur within your own code.
13+
14+
To handle these exceptions, you can use a try/catch block or Nutgram's onException handler.
15+
16+
### `onException` handler (generic)
17+
18+
The `onException` handler can be used to catch any exceptions that are not handled elsewhere in your code.
19+
If defined, this handler will be triggered when an exception occurs within any other handler,
20+
passing the $exception as the second argument.
21+
22+
```php
23+
use SergiX44\Nutgram\Nutgram;
24+
use Throwable;
25+
26+
$bot = new Nutgram($_ENV['TOKEN']);
27+
28+
// define some handlers ...
29+
30+
// and exception is thrown...
31+
$bot->onMessage(function (Nutgram $bot) {
32+
// do stuff
33+
throw new Exception('Oh no!');
34+
});
35+
36+
// ... and passed to the exception handler
37+
$bot->onException(function (Nutgram $bot, Throwable $exception) {
38+
echo $exception->getMessage(); // Oh no!
39+
$bot->sendMessage('Whoops!');
40+
});
41+
42+
$bot->run();
43+
```
44+
45+
### `onException` handler (explicit)
46+
47+
The `onException` handler also allows you to specify different callbacks based on the type of exception being thrown:
48+
49+
```php
50+
use SergiX44\Nutgram\Nutgram;
51+
use Exception;
52+
use InvalidArgumentException;
53+
54+
$bot = new Nutgram($_ENV['TOKEN']);
55+
56+
// and exception is thrown...
57+
$bot->onMessage(function (Nutgram $bot) {
58+
if (random_int(0, 1)) {
59+
throw new InvalidArgumentException();
60+
}
61+
throw new Exception('Oh no!');
62+
});
63+
64+
$bot->onException(InvalidArgumentException::class, function (Nutgram $bot, InvalidArgumentException $exception) {
65+
// your code here
66+
});
67+
68+
$bot->onException(Exception::class, function (Nutgram $bot, Exception $exception) {
69+
// your code here
70+
});
71+
72+
$bot->run();
73+
```
74+
75+
## Telegram API Errors
76+
77+
A Telegram API error occur when the Telegram Bot API returns an error.
78+
79+
These errors can be handled using `try/catch` blocks or the `onApiError` handler.
80+
81+
### `try/catch`
82+
83+
You can also use a `try/catch` block to catch Telegram API errors.
84+
85+
```php showLineNumbers
86+
$bot = new Nutgram('token');
87+
88+
$bot->onCommand('start', function (Nutgram $bot) {
89+
try {
90+
$post = $bot->sendMessage('Hello', chat_id: 123456);
91+
echo gettype($post).PHP_EOL;
92+
} catch (Throwable $e){
93+
echo '[try] '.$e::class. ' => ' . $e->getMessage().PHP_EOL;
94+
}
95+
});
96+
97+
$bot->run();
98+
```
99+
100+
**Example Output:**
101+
> line 8: [try] SergiX44\Nutgram\Telegram\Exceptions\TelegramException => Forbidden: bot was blocked by the user
102+
103+
### `try/catch` + `registerApiException`
104+
105+
You can register a custom exception class to be thrown when a specific pattern is detected in the error message:
106+
107+
```php
108+
class BotBlocked extends ApiException
109+
{
110+
public static ?string $pattern = '.*bot was blocked.*';
111+
}
112+
```
113+
114+
```php showLineNumbers
115+
$bot = new Nutgram('token');
116+
117+
$bot->onCommand('start', function (Nutgram $bot) {
118+
try {
119+
$post = $bot->sendMessage('Hello', chat_id: 123456);
120+
echo gettype($post).PHP_EOL;
121+
} catch (Throwable $e){
122+
echo '[try] '.$e::class. ' => ' . $e->getMessage().PHP_EOL;
123+
}
124+
});
125+
126+
$bot->registerApiException(BotBlocked::class);
127+
128+
$bot->run();
129+
```
130+
131+
**Example Output:**
132+
> line 8: [try] App\BotBlocked => Forbidden: bot was blocked by the user
133+
134+
As default, the ApiException class will throw when invoked, but you can also override this behaviour:
135+
136+
```php
137+
class UserDeactivatedException extends ApiException
138+
{
139+
public static ?string $pattern = '.*deactivated.*';
140+
141+
public function __invoke(Nutgram $bot, TelegramException $e)
142+
{
143+
// override this method to change the default behaviour:
144+
throw new static($e->getMessage(), $e->getCode(), $e);
145+
}
146+
}
147+
```
148+
149+
### `onApiError` handler
150+
151+
The `onApiError` handler allows you to handle Telegram API errors globally.
152+
153+
```php showLineNumbers
154+
$bot = new Nutgram('token');
155+
156+
$bot->onCommand('start', function (Nutgram $bot) {
157+
$post = $bot->sendMessage('Hello', chat_id: 123456);
158+
echo gettype($post).PHP_EOL;
159+
});
160+
161+
$bot->onApiError(function (Nutgram $bot, TelegramException $e) {
162+
echo '[onApiError] '.$e::class. ' => ' . $e->getMessage().PHP_EOL;
163+
});
164+
165+
$bot->run();
166+
```
167+
168+
**Example Output:**
169+
> line 9: [onApiError] SergiX44\Nutgram\Telegram\Exceptions\TelegramException => Forbidden: bot was blocked by the user<br/>
170+
> line 5: NULL
171+
172+
Like the onException, the handler support a regex matching the text returned by the telegram api:
173+
174+
```php
175+
use SergiX44\Nutgram\Nutgram;
176+
use SergiX44\Nutgram\Telegram\Exceptions\TelegramException;
177+
178+
$bot = new Nutgram($_ENV['TOKEN']);
179+
180+
$bot->onMessage(function (Nutgram $bot) {
181+
$bot->sendMessage(
182+
text: 'Invalid call!',
183+
chat_id: null,
184+
);
185+
});
186+
187+
$bot->onApiError('chat not found', function (Nutgram $bot, TelegramException $exception) {
188+
//
189+
});
190+
191+
192+
$bot->onApiError('user(.*)deactivated', function (Nutgram $bot, TelegramException $exception) {
193+
//
194+
});
195+
196+
$bot->run();
197+
```
198+
199+
### `TelegramException` methods
200+
201+
The `TelegramException` class has some useful methods to get more information about the error:
202+
203+
```php
204+
use SergiX44\Nutgram\Nutgram;
205+
use SergiX44\Nutgram\Telegram\Exceptions\TelegramException;
206+
207+
$bot = new Nutgram($_ENV['TOKEN']);
208+
209+
$bot->onMessage(function (Nutgram $bot) {
210+
foreach(range(1,200) as $i){
211+
$bot->sendMessage('Too many calls!');
212+
}
213+
});
214+
215+
$bot->onApiError(function (Nutgram $bot, TelegramException $exception) {
216+
echo $exception->getMessage(); // Too Many Requests: retry after 14
217+
echo $exception->getCode(); // 429
218+
echo $exception->getParameters(); // ['retry_after' => 14]
219+
echo $exception->getParameter('retry_after'); // 14
220+
echo $exception->hasParameter('retry_after'); // true
221+
});
222+
223+
$bot->run();
224+
```

docs/usage/handlers.mdx

Lines changed: 6 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -629,47 +629,20 @@ $bot->onMessage(function (Nutgram $bot) {
629629
// ... and passed to the exception handler
630630
$bot->onException(function (Nutgram $bot, \Throwable $exception) {
631631
echo $exception->getMessage(); // Oh no!
632-
error_log($exception);
633632
$bot->sendMessage('Whoops!');
634633
});
635634

636635
$bot->run();
637636
```
638637

639-
The `onException` handler supports also different callbacks based on the exception instance:
640-
641-
```php
642-
use SergiX44\Nutgram\Nutgram;
643-
644-
$bot = new Nutgram($_ENV['TOKEN']);
645-
646-
// and exception is thrown...
647-
$bot->onMessage(function (Nutgram $bot) {
648-
if (random_int(0, 1)) {
649-
throw new InvalidArgumentException();
650-
}
651-
throw new Exception('Oh no!');
652-
});
653-
654-
$bot->onException(InvalidArgumentException::class, function (Nutgram $bot, InvalidArgumentException $exception) {
655-
//
656-
});
657-
658-
$bot->onException(Exception::class, function (Nutgram $bot, Exception $exception) {
659-
//
660-
});
661-
662-
$bot->run();
663-
```
664-
638+
:::tip
639+
For a more specific exception handling, you can visit the [Handling Exceptions](exceptions#onexception-handler-explicit) section.
640+
:::
665641

666642
### `onApiError`
667643

668644
The same concept of the `onException`, but for outgoing requests:
669645

670-
<Tabs>
671-
<TabItem value="chat_not_found" label="Chat not found" default>
672-
673646
```php
674647
use SergiX44\Nutgram\Nutgram;
675648
use SergiX44\Nutgram\Telegram\Exceptions\TelegramException;
@@ -686,99 +659,14 @@ $bot->onMessage(function (Nutgram $bot) {
686659
$bot->onApiError(function (Nutgram $bot, TelegramException $exception) {
687660
echo $exception->getMessage(); // Bad Request: chat not found
688661
echo $exception->getCode(); // 400
689-
error_log($exception);
690-
});
691-
692-
$bot->run();
693-
```
694-
695-
</TabItem>
696-
<TabItem value="too_many_requests" label="Too many requests">
697-
698-
```php
699-
use SergiX44\Nutgram\Nutgram;
700-
use SergiX44\Nutgram\Telegram\Exceptions\TelegramException;
701-
702-
$bot = new Nutgram($_ENV['TOKEN']);
703-
704-
$bot->onMessage(function (Nutgram $bot) {
705-
foreach(range(1,200) as $i){
706-
$bot->sendMessage('Too many calls!');
707-
}
708-
});
709-
710-
$bot->onApiError(function (Nutgram $bot, TelegramException $exception) {
711-
echo $exception->getMessage(); // Too Many Requests: retry after 14
712-
echo $exception->getCode(); // 429
713-
echo $exception->getParameters(); // ['retry_after' => 14]
714-
echo $exception->getParameter('retry_after'); // 14
715-
echo $exception->hasParameter('retry_after'); // true
716-
error_log($exception);
717-
});
718-
719-
$bot->run();
720-
```
721-
722-
</TabItem>
723-
</Tabs>
724-
725-
Like the `onException`, the handler support a regex matching the text returned by the telegram api:
726-
727-
```php
728-
use SergiX44\Nutgram\Nutgram;
729-
use SergiX44\Nutgram\Telegram\Exceptions\TelegramException;
730-
731-
$bot = new Nutgram($_ENV['TOKEN']);
732-
733-
$bot->onMessage(function (Nutgram $bot) {
734-
$bot->sendMessage(
735-
text: 'Invalid call!',
736-
chat_id: null,
737-
);
738-
});
739-
740-
$bot->onApiError('chat not found', function (Nutgram $bot, TelegramException $exception) {
741-
//
742-
});
743-
744-
745-
$bot->onApiError('user(.*)deactivated', function (Nutgram $bot, TelegramException $exception) {
746-
//
747662
});
748663

749664
$bot->run();
750665
```
751666

752-
#### Register API exceptions
753-
As alternative method, you can also able to register a user defined
754-
TelegramApiError class to throw when a specific error occurs:
755-
756-
```php
757-
// exception file
758-
class UserDeactivatedException extends ApiException
759-
{
760-
public static ?string $pattern = '.*deactivated.*';
761-
}
762-
763-
// handlers file
764-
$bot->registerApiException(UserDeactivatedException::class);
765-
```
766-
767-
As default, the `ApiException` class will throw when invoked, but you can also override this behaviour:
768-
769-
```php
770-
class UserDeactivatedException extends ApiException
771-
{
772-
public static ?string $pattern = '.*deactivated.*';
773-
774-
public function __invoke(Nutgram $bot, TelegramException $e)
775-
{
776-
// override this method to change the default behaviour:
777-
throw new static($e->getMessage(), $e->getCode(), $e);
778-
}
779-
}
780-
```
781-
667+
:::tip
668+
For a more specific error handling, you can visit the [Handling Exceptions](exceptions#telegram-api-exceptions) section.
669+
:::
782670

783671
### `beforeApiRequest`
784672

sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const sidebars = {
5353
'usage/extend',
5454
'usage/bulk_messenger',
5555
'usage/web_validation',
56+
'usage/exceptions',
5657
],
5758
},
5859
{

0 commit comments

Comments
 (0)