mirror of
https://github.com/ProxyPanel/ProxyPanel.git
synced 2026-04-13 07:59:20 +00:00
Fix & improve Telegram Notification | Bot
This commit is contained in:
@@ -9,6 +9,7 @@ use App\Http\Requests\Admin\SystemRequest;
|
||||
use App\Models\Config;
|
||||
use App\Notifications\Custom;
|
||||
use App\Services\TelegramService;
|
||||
use Auth;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -152,15 +153,16 @@ class SystemController extends Controller
|
||||
|
||||
public function sendTestNotification(): JsonResponse // 推送通知测试
|
||||
{
|
||||
$data = ['这是测试的标题', 'ProxyPanel测试内容'];
|
||||
switch (request('channel')) {
|
||||
case 'serverChan':
|
||||
Notification::sendNow(ServerChanChannel::class, new Custom('这是测试的标题', 'ProxyPanel测试内容'));
|
||||
Notification::sendNow(Auth::getUser(), new Custom($data[0], $data[1]), [ServerChanChannel::class]);
|
||||
break;
|
||||
case 'bark':
|
||||
Notification::sendNow(BarkChannel::class, new Custom('这是测试的标题', 'ProxyPanel测试内容'));
|
||||
Notification::sendNow(Auth::getUser(), new Custom($data[0], $data[1]), [BarkChannel::class]);
|
||||
break;
|
||||
case 'telegram':
|
||||
Notification::sendNow(TelegramChannel::class, new Custom('这是测试的标题', 'ProxyPanel测试内容'));
|
||||
Notification::sendNow(Auth::getUser(), new Custom($data[0], $data[1]), [TelegramChannel::class]);
|
||||
break;
|
||||
default:
|
||||
return Response::json(['status' => 'fail', 'message' => '未知渠道']);
|
||||
|
||||
@@ -5,7 +5,9 @@ namespace App\Http\Controllers;
|
||||
use App\Models\Ticket;
|
||||
use App\Models\User;
|
||||
use App\Services\TelegramService;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use StdClass;
|
||||
|
||||
class TelegramController extends Controller
|
||||
{
|
||||
@@ -13,7 +15,7 @@ class TelegramController extends Controller
|
||||
|
||||
public function __construct(Request $request)
|
||||
{
|
||||
if ($request->input('access_token') !== md5(sysConfig('telegram_token'))) {
|
||||
if (hash_equals(sysConfig('telegram_token'), $request->input('access_token'))) {
|
||||
abort(500, 'authentication failed');
|
||||
}
|
||||
}
|
||||
@@ -33,47 +35,19 @@ class TelegramController extends Controller
|
||||
$this->fromReply();
|
||||
break;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
$telegramService = new TelegramService();
|
||||
$telegramService->sendMessage($this->msg->chat_id, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function fromSend()
|
||||
{
|
||||
switch ($this->msg->command) {
|
||||
case '/bind':
|
||||
$this->bind();
|
||||
break;
|
||||
case '/traffic':
|
||||
$this->traffic();
|
||||
break;
|
||||
case '/getlatesturl':
|
||||
$this->getLatestUrl();
|
||||
break;
|
||||
case '/unbind':
|
||||
$this->unbind();
|
||||
break;
|
||||
default:
|
||||
$this->help();
|
||||
}
|
||||
}
|
||||
|
||||
private function fromReply()
|
||||
{
|
||||
// ticket
|
||||
if (preg_match('/[#](.*)/', $this->msg->reply_text, $match)) {
|
||||
$this->replayTicket($match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private function getMessage(array $data)
|
||||
{
|
||||
if (! isset($data['message'])) {
|
||||
return false;
|
||||
}
|
||||
$obj = new \StdClass();
|
||||
$obj->is_private = $data['message']['chat']['type'] === 'private' ? true : false;
|
||||
$obj = new StdClass();
|
||||
$obj->is_private = $data['message']['chat']['type'] === 'private';
|
||||
if (! isset($data['message']['text'])) {
|
||||
return false;
|
||||
}
|
||||
@@ -91,6 +65,26 @@ class TelegramController extends Controller
|
||||
return $obj;
|
||||
}
|
||||
|
||||
private function fromSend()
|
||||
{
|
||||
switch ($this->msg->command) {
|
||||
case '/bind':
|
||||
$this->bind();
|
||||
break;
|
||||
case '/traffic':
|
||||
$this->traffic();
|
||||
break;
|
||||
case '/getLatestUrl':
|
||||
$this->getLatestUrl();
|
||||
break;
|
||||
case '/unbind':
|
||||
$this->unbind();
|
||||
break;
|
||||
default:
|
||||
$this->help();
|
||||
}
|
||||
}
|
||||
|
||||
private function bind()
|
||||
{
|
||||
$msg = $this->msg;
|
||||
@@ -104,62 +98,27 @@ class TelegramController extends Controller
|
||||
if (! $user) {
|
||||
abort(500, '用户不存在');
|
||||
}
|
||||
if ($user->telegram_id) {
|
||||
if ($user->telegram_user_id) {
|
||||
abort(500, '该账号已经绑定了Telegram账号');
|
||||
}
|
||||
$user->telegram_id = $msg->chat_id;
|
||||
if (! $user->save()) {
|
||||
|
||||
if (! $user->userAuths()->create(['type' => 'telegram', 'identifier' => $msg->chat_id])) {
|
||||
abort(500, '设置失败');
|
||||
}
|
||||
$telegramService = new TelegramService();
|
||||
$telegramService->sendMessage($msg->chat_id, '绑定成功');
|
||||
}
|
||||
|
||||
private function unbind()
|
||||
{
|
||||
$msg = $this->msg;
|
||||
if (! $msg->is_private) {
|
||||
return;
|
||||
}
|
||||
$user = User::where('telegram_id', $msg->chat_id)->first();
|
||||
$telegramService = new TelegramService();
|
||||
if (! $user) {
|
||||
$this->help();
|
||||
$telegramService->sendMessage($msg->chat_id, '没有查询到您的用户信息,请先绑定账号', 'markdown');
|
||||
|
||||
return;
|
||||
}
|
||||
$user->telegram_id = null;
|
||||
if (! $user->save()) {
|
||||
abort(500, '解绑失败');
|
||||
}
|
||||
$telegramService->sendMessage($msg->chat_id, '解绑成功', 'markdown');
|
||||
}
|
||||
|
||||
private function help()
|
||||
{
|
||||
$msg = $this->msg;
|
||||
if (! $msg->is_private) {
|
||||
return;
|
||||
}
|
||||
$telegramService = new TelegramService();
|
||||
$commands = [
|
||||
'/bind 订阅地址 - 绑定你的'.sysConfig('website_name').'账号',
|
||||
'/traffic - 查询流量信息',
|
||||
'/getlatesturl - 获取最新的'.sysConfig('website_name').'网址',
|
||||
'/unbind - 解除绑定',
|
||||
];
|
||||
$text = implode(PHP_EOL, $commands);
|
||||
$telegramService->sendMessage($msg->chat_id, "你可以使用以下命令进行操作:\n\n$text", 'markdown');
|
||||
}
|
||||
|
||||
private function traffic()
|
||||
{
|
||||
$msg = $this->msg;
|
||||
if (! $msg->is_private) {
|
||||
return;
|
||||
}
|
||||
$user = User::where('telegram_id', $msg->chat_id)->first();
|
||||
$user = User::with(['userAuths' => function ($query) use ($msg) {
|
||||
$query->whereType('telegram')->whereIdentifier($msg->chat_id);
|
||||
}])->first();
|
||||
|
||||
$telegramService = new TelegramService();
|
||||
if (! $user) {
|
||||
$this->help();
|
||||
@@ -175,6 +134,23 @@ class TelegramController extends Controller
|
||||
$telegramService->sendMessage($msg->chat_id, $text, 'markdown');
|
||||
}
|
||||
|
||||
private function help()
|
||||
{
|
||||
$msg = $this->msg;
|
||||
if (! $msg->is_private) {
|
||||
return;
|
||||
}
|
||||
$telegramService = new TelegramService();
|
||||
$commands = [
|
||||
'/bind 订阅地址 - 绑定你的'.sysConfig('website_name').'账号',
|
||||
'/traffic - 查询流量信息',
|
||||
'/getLatestUrl - 获取最新的'.sysConfig('website_name').'网址',
|
||||
'/unbind - 解除绑定',
|
||||
];
|
||||
$text = implode(PHP_EOL, $commands);
|
||||
$telegramService->sendMessage($msg->chat_id, "你可以使用以下命令进行操作:\n\n$text", 'markdown');
|
||||
}
|
||||
|
||||
private function getLatestUrl()
|
||||
{
|
||||
$msg = $this->msg;
|
||||
@@ -187,20 +163,55 @@ class TelegramController extends Controller
|
||||
$telegramService->sendMessage($msg->chat_id, $text, 'markdown');
|
||||
}
|
||||
|
||||
private function unbind()
|
||||
{
|
||||
$msg = $this->msg;
|
||||
if (! $msg->is_private) {
|
||||
return;
|
||||
}
|
||||
$user = User::with(['userAuths' => function ($query) use ($msg) {
|
||||
$query->whereType('telegram')->whereIdentifier($msg->chat_id);
|
||||
},
|
||||
])->first();
|
||||
|
||||
$telegramService = new TelegramService();
|
||||
if (! $user) {
|
||||
$this->help();
|
||||
$telegramService->sendMessage($msg->chat_id, '没有查询到您的用户信息,请先绑定账号', 'markdown');
|
||||
|
||||
return;
|
||||
}
|
||||
if (! $user->userAuths()->whereType('telegram')->whereIdentifier($msg->chat_id)->delete()) {
|
||||
abort(500, '解绑失败');
|
||||
}
|
||||
$telegramService->sendMessage($msg->chat_id, '解绑成功', 'markdown');
|
||||
}
|
||||
|
||||
private function fromReply()
|
||||
{
|
||||
// ticket
|
||||
if (preg_match('/[#](.*)/', $this->msg->reply_text, $match)) {
|
||||
$this->replayTicket($match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private function replayTicket($ticketId)
|
||||
{
|
||||
$msg = $this->msg;
|
||||
if (! $msg->is_private) {
|
||||
return;
|
||||
}
|
||||
$user = User::where('telegram_id', $msg->chat_id)->first();
|
||||
$user = User::with(['userAuths' => function ($query) use ($msg) {
|
||||
$query->whereType('telegram')->whereIdentifier($msg->chat_id);
|
||||
},
|
||||
])->first();
|
||||
|
||||
if (! $user) {
|
||||
abort(500, '用户不存在');
|
||||
}
|
||||
$admin = User::role('Super Admin')->where('user.id', $user->id)->first();
|
||||
$admin = User::role('Super Admin')->whereId($user->id)->first();
|
||||
if ($admin) {
|
||||
$ticket = Ticket::where('id', $ticketId)
|
||||
->first();
|
||||
$ticket = Ticket::whereId($ticketId)->first();
|
||||
if (! $ticket) {
|
||||
abort(500, '工单不存在');
|
||||
}
|
||||
|
||||
@@ -36,6 +36,13 @@ class User extends Authenticatable implements JWTSubject
|
||||
return $this->d + $this->u;
|
||||
}
|
||||
|
||||
public function getTelegramUserIdAttribute()
|
||||
{
|
||||
$telegram = $this->userAuths()->whereType('telegram')->first();
|
||||
|
||||
return $telegram->identifier ?? null;
|
||||
}
|
||||
|
||||
public function profile()
|
||||
{
|
||||
return [
|
||||
@@ -321,13 +328,8 @@ class User extends Authenticatable implements JWTSubject
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Route notifications for the Telegram channel.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function routeNotificationForTelegram()
|
||||
{
|
||||
return $this->telegram_id;
|
||||
return $this->telegram_user_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,10 +45,6 @@ class DataAnomaly extends Notification implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
return TelegramMessage::create()
|
||||
|
||||
@@ -58,10 +58,6 @@ class NodeBlocked extends Notification implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
return TelegramMessage::create()
|
||||
|
||||
@@ -49,10 +49,6 @@ class NodeDailyReport extends Notification implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
return TelegramMessage::create()
|
||||
|
||||
@@ -67,10 +67,6 @@ class NodeOffline extends Notification implements ShouldQueue
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
return TelegramMessage::create()
|
||||
|
||||
@@ -43,10 +43,7 @@ class PaymentReceived extends Notification implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
// todo: 需要重新审视发送对象
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
foreach (User::role('Super Admin')->get() as $admin) {
|
||||
@@ -57,7 +54,7 @@ class PaymentReceived extends Notification implements ShouldQueue
|
||||
);
|
||||
|
||||
return TelegramMessage::create()
|
||||
->to($admin->telegram_id)
|
||||
->to($admin->telegram_user_id)
|
||||
->token(sysConfig('telegram_token'))
|
||||
->content($message);
|
||||
}
|
||||
|
||||
@@ -49,10 +49,6 @@ class TicketClosed extends Notification implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
return TelegramMessage::create()
|
||||
|
||||
@@ -46,10 +46,6 @@ class TicketCreated extends Notification implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
return TelegramMessage::create()
|
||||
|
||||
@@ -46,10 +46,6 @@ class TicketReplied extends Notification implements ShouldQueue
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $notifiable
|
||||
* @return TelegramMessage|\NotificationChannels\Telegram\Traits\HasSharedLogic
|
||||
*/
|
||||
public function toTelegram($notifiable)
|
||||
{
|
||||
return TelegramMessage::create()
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class RmTelegramInUserTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('user', function (Blueprint $table) {
|
||||
$table->dropColumn(['telegram_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('user', function (Blueprint $table) {
|
||||
$table->string('telegram_id')->nullable()->comment('用户绑定的Telegram_ID');
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user