codewiser / telegram-channel

Laravel Telegram 通知频道

v1.1.3 2024-05-30 11:36 UTC

This package is auto-updated.

Last update: 2024-09-30 12:16:58 UTC


README

本包提供了一种通过 Telegram 发送通知的方法。

安装和设置

包使用 irazasyed/telegram-bot-sdk。因此,请先遵循Telegram Bot SDK 指示并设置您的第一个 Telegram Bot。您可能需要运行以下命令:

php artisan vendor:publish --tag="telegram-config"

config/telegram.php 配置文件中添加 name 参数并注册 DeeplinkCommand。您可能不需要定义 webhook_url,因为它将在运行时重新配置。

'bots' => [
    'my_bot' => [
        'name'             => env('TELEGRAM_BOT_NAME'),
        'token'            => env('TELEGRAM_BOT_TOKEN'),
        'certificate_path' => env('TELEGRAM_CERTIFICATE_PATH'),
        //'webhook_url'      => env('TELEGRAM_WEBHOOK_URL'),
        'commands'         => [
            \Codewiser\Telegram\Commands\DeeplinkCommand::class
        ],
    ],
]

接下来,将 \Codewiser\Telegram\Contracts\TelegramNotifiable 实现到 User 模型中。您可能需要编写迁移...

use \Illuminate\Database\Eloquent\Model;
use \Codewiser\Telegram\Contracts\TelegramNotifiable;

class User extends Model implements TelegramNotifiable
{
    public function routeNotificationForTelegram($notification = null): mixed
    {
        return $this->telegram;
    }

    public function setRouteForTelegram($route): void
    {
        $this->telegram = $route;
        $this->save();
    }
}

现在,创建服务以实现 \Codewiser\Telegram\Contracts\TelegramNotifiableProvider。这是一个实现示例,您可以根据需要实现它。

use \Codewiser\Telegram\Contracts\TelegramNotifiableProvider;

class TelegramUserProvider implements TelegramNotifiableProvider
{
    /**
     * Issue and remember new token for a given notifiable.
     */
    public function generateToken(TelegramNotifiable $notifiable): string
    {
        $token = Str::random(40);

        cache()->set(
            $token,
            $notifiable->getKey(),
            now()->addMinutes(5)
        );

        return $token;
    }
    
    /**
     * Find notifiable associated with a given token.
     */
    public function resolveToken(string $token): ?TelegramNotifiable
    {
        $key = cache()->pull($token);

        if ($key) {
            return User::query()->find($key);
        }

        return null;
    }
}

最后,在您的应用程序的 AppServiceProvider 中注册此服务。

public function register()
{
    $this->app->singleton(TelegramNotifiableProvider::class, fn() => new TelegramUserProvider);
}

我们已准备好开始。

获取更新

注册 webhook

如果您的 bot 在 config/telegram.php 中配置正确,这足以使用 Telegram Bot SDK 包提供的 telegram:webhook 命令。我们建议您阅读帮助文档。

php artisan help telegram:webhook

本包提供处理传入消息的 webhook 控制器。

例如,上面提到的 DeeplinkCommand 用于处理带 deep link 令牌的 /start 命令。

您可以在 config/telegram.php 中添加任何其他命令处理器。

有关Bot Commands的更多信息。

长轮询

本包带来了 telegram:poll 命令,无需注册 webhook 即可获取更新。只需调用命令即可。

用法

订阅用户

首先,我们需要为用户生成一个 deep link。

use \Illuminate\Http\Request;
use \Codewiser\Telegram\TelegramService;

class DeeplinkController extends Controller
{
    public function __invoke(Request $request, TelegramService $service) {
        return $service->getDeeplink($request->user());
    }
}

用户点击 deep link,打开 Telegram 客户端并点击 Start 按钮。

Codewiser\Telegram\Commands\DeeplinkCommand 处理传入的更新,解析 deep link 令牌并更新 Userchat_id

目前,此用户拥有 Telegram 路由,可以通过 Telegram 进行通知。

通知用户

要通知用户,请向通知中添加 toTelegram 方法。别忘了将 telegram 添加到 via 方法中。

class Notification extends \Illuminate\Notifications\Notification
{
    /**
     * Get the notification's delivery channels.
     */
    public function via(object $notifiable): array
    {
        return ['mail', 'telegram'];
    }
    
    /**
     * Get the telegram representation of the notification.
     */
    public function toTelegram(object $notifiable)
    {
        //
    }
}

Telegram 通知消息可以是字符串,也可以是数组。

数组键符合Telegram sendMessage 方法

字符串被解释为 HTML,并将使用 ['parse_mode' => 'HTML'] 发送。

失败的通知

当通知无法发送给用户时,会传播 \Illuminate\Notifications\Events\NotificationFailed 事件。

一些失败是可以捕获的。例如,如果用户锁定了一个 bot,我们会收到一个 403 响应状态。在这种情况下,我们应该从未来的通知中取消订阅用户。400 表示聊天未找到。

如果您希望自动取消订阅此类用户,请在应用程序 AppServiceProvider 的 boot 方法中注册事件监听器。

use \Codewiser\Telegram\Listeners\UnsubscribeTelegramNotifiable;
use \Illuminate\Notifications\Events\NotificationFailed;

public function boot(): void
{
    Event::listen(
        NotificationFailed::class,
        UnsubscribeTelegramNotifiable::class,
    );
}