浏览代码

Merge pull request #1852 from visuddhinanda/laravel

支持 notification
visuddhinanda 2 年之前
父节点
当前提交
1be5bbad57

+ 1 - 1
app/Console/Commands/MqIssues.php

@@ -9,7 +9,7 @@ class MqIssues extends Command
 {
 {
     /**
     /**
      * The name and signature of the console command.
      * The name and signature of the console command.
-     *
+     * php artisan mq:issues
      * @var string
      * @var string
      */
      */
     protected $signature = 'mq:issues';
     protected $signature = 'mq:issues';

+ 59 - 13
app/Console/Commands/MqPr.php

@@ -3,19 +3,22 @@
 namespace App\Console\Commands;
 namespace App\Console\Commands;
 
 
 use Illuminate\Console\Command;
 use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
+
 use App\Http\Api\Mq;
 use App\Http\Api\Mq;
 use App\Models\Sentence;
 use App\Models\Sentence;
 use App\Models\WebHook;
 use App\Models\WebHook;
 use App\Models\PaliSentence;
 use App\Models\PaliSentence;
 use App\Tools\WebHook as WebHookSend;
 use App\Tools\WebHook as WebHookSend;
 use App\Http\Api\MdRender;
 use App\Http\Api\MdRender;
-use Illuminate\Support\Facades\Log;
+use App\Http\Api\PaliTextApi;
 
 
 class MqPr extends Command
 class MqPr extends Command
 {
 {
     /**
     /**
      * The name and signature of the console command.
      * The name and signature of the console command.
-     *
+     * php artisan mq:pr
      * @var string
      * @var string
      */
      */
     protected $signature = 'mq:pr';
     protected $signature = 'mq:pr';
@@ -53,28 +56,71 @@ class MqPr extends Command
         Log::debug("mq:pr start.");
         Log::debug("mq:pr start.");
         Mq::worker($exchange,$queue,function ($message){
         Mq::worker($exchange,$queue,function ($message){
             /**生成消息内容 */
             /**生成消息内容 */
+
             $msgTitle = '修改建议';
             $msgTitle = '修改建议';
-            $username = $message->editor->nickName;
-            $palitext = PaliSentence::where('book',$message->book)
-                                ->where('paragraph',$message->paragraph)
-                                ->where('word_begin',$message->word_start)
-                                ->where('word_end',$message->word_end)
+            $prData = $message->data;
+            $sent_num = "{$prData->book}-{$prData->paragraph}-{$prData->word_start}-{$prData->word_end}";
+            $this->info('request'.$sent_num);
+
+            $username = $prData->editor->nickName;
+            $palitext = PaliSentence::where('book',$prData->book)
+                                ->where('paragraph',$prData->paragraph)
+                                ->where('word_begin',$prData->word_start)
+                                ->where('word_end',$prData->word_end)
                                 ->value('text');
                                 ->value('text');
-            $prtext = mb_substr($message->content,0,140,"UTF-8");
-            $sent_num = "{$message->book}-{$message->paragraph}-{$message->word_start}-{$message->word_end}";
-            $link = config('app.url')."/pcd/article/para/{$message->book}-{$message->paragraph}";
-            $link .= "?book={$message->book}&par={$message->paragraph}&channel={$message->channel->id}";
+            $orgText = Sentence::where('book_id',$prData->book)
+                                ->where('paragraph',$prData->paragraph)
+                                ->where('word_start',$prData->word_start)
+                                ->where('word_end',$prData->word_end)
+                                ->where('channel_uid',$prData->channel->id)
+                                ->value('content');
+            $prtext = mb_substr($prData->content,0,140,"UTF-8");
+
+            $link = config('app.url')."/pcd/article/para/{$prData->book}-{$prData->paragraph}";
+            $link .= "?book={$prData->book}&par={$prData->paragraph}&channel={$prData->channel->id}";
 
 
             $msgContent = "{$username} 就文句`{$palitext}`提出了修改建议:\n";
             $msgContent = "{$username} 就文句`{$palitext}`提出了修改建议:\n";
             $msgContent .= ">内容摘要:<font color=\"comment\">{$prtext}</font>,\n";
             $msgContent .= ">内容摘要:<font color=\"comment\">{$prtext}</font>,\n";
             $msgContent .= ">句子编号:<font color=\"info\">{$sent_num}</font>\n";
             $msgContent .= ">句子编号:<font color=\"info\">{$sent_num}</font>\n";
             $msgContent .= "欢迎大家[点击链接]({$link})查看并讨论。";
             $msgContent .= "欢迎大家[点击链接]({$link})查看并讨论。";
 
 
-            $webhooks = WebHook::where('res_id',$message->channel->id)
+            //标题
+            if($prData->book<1000){
+                $path = json_decode(PaliTextApi::getChapterPath($prData->book,$prData->paragraph)) ;
+                $title = $path[0]->title;
+            }else{
+                $title = '';
+            }
+
+            $notificationContent = "**{$title}**\n\n";
+            $notificationContent .= ">{$orgText}\n\n";
+            $notificationContent .= "{$prtext}";
+            $result=0;
+            //发送站内信
+            $url = config('app.url').'/api/v2/notification';
+            $response = Http::withToken($message->token)
+                            ->post($url,
+                            [
+                                'to'=> $prData->channel->studio_id,
+                                'title'=> $msgTitle,
+                                'content'=> $notificationContent,
+                                'url'=>$link,
+                                'res_type'=> 'suggestion',
+                                'res_id'=> $prData->uid,
+                            ]);
+            if($response->failed()){
+                Log::error('send notification failed');
+            }else{
+                $this->info("send notification");
+            }
+
+            //发送webhook
+
+            $webhooks = WebHook::where('res_id',$prData->channel->id)
                             ->where('status','active')
                             ->where('status','active')
                             ->get();
                             ->get();
 
 
-            $result=0;
+
             foreach ($webhooks as $key => $hook) {
             foreach ($webhooks as $key => $hook) {
                 $event = json_decode($hook->event);
                 $event = json_decode($hook->event);
                 if(!in_array('pr',$event)){
                 if(!in_array('pr',$event)){

+ 10 - 3
app/Console/Commands/TestMq.php

@@ -3,20 +3,22 @@
 namespace App\Console\Commands;
 namespace App\Console\Commands;
 
 
 use Illuminate\Console\Command;
 use Illuminate\Console\Command;
+use Illuminate\Support\Str;
 
 
 use App\Http\Api\Mq;
 use App\Http\Api\Mq;
 use App\Models\Discussion;
 use App\Models\Discussion;
 use App\Http\Resources\DiscussionResource;
 use App\Http\Resources\DiscussionResource;
-use Illuminate\Support\Str;
+use App\Models\SentPr;
+use App\Http\Resources\SentPrResource;
 
 
 class TestMq extends Command
 class TestMq extends Command
 {
 {
     /**
     /**
      * The name and signature of the console command.
      * The name and signature of the console command.
-     *
+     * php artisan test:mq
      * @var string
      * @var string
      */
      */
-    protected $signature = 'test:mq {--discussion=}';
+    protected $signature = 'test:mq {--discussion=} {--pr=}';
 
 
     /**
     /**
      * The console command description.
      * The console command description.
@@ -51,6 +53,11 @@ class TestMq extends Command
             Mq::publish('discussion',new DiscussionResource(Discussion::find($discussion)));
             Mq::publish('discussion',new DiscussionResource(Discussion::find($discussion)));
         }
         }
 
 
+        $pr = $this->option('pr');
+        if($pr && Str::isUuid($pr)){
+            Mq::publish('suggestion',new SentPrResource(SentPr::where('uid',$pr)->first()));
+        }
+
         return 0;
         return 0;
     }
     }
 }
 }

+ 1 - 1
app/Console/Commands/TestMqWorker.php

@@ -10,7 +10,7 @@ class TestMqWorker extends Command
 {
 {
     /**
     /**
      * The name and signature of the console command.
      * The name and signature of the console command.
-     *
+     * php artisan test:mq.worker
      * @var string
      * @var string
      */
      */
     protected $signature = 'test:mq.worker';
     protected $signature = 'test:mq.worker';

+ 7 - 0
app/Http/Api/PaliTextApi.php

@@ -15,4 +15,11 @@ class PaliTextApi{
         $end = $para + $chapter->chapter_len -1;
         $end = $para + $chapter->chapter_len -1;
         return [$start,$end];
         return [$start,$end];
     }
     }
+
+    public static function getChapterPath($book,$para){
+        $path = PaliText::where('book',$book)
+                        ->where('paragraph',$para)
+                        ->value('path');
+        return $path;
+    }
 }
 }

+ 8 - 11
app/Http/Controllers/DiscussionController.php

@@ -2,17 +2,17 @@
 
 
 namespace App\Http\Controllers;
 namespace App\Http\Controllers;
 
 
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\Request;
 use App\Models\Discussion;
 use App\Models\Discussion;
 use App\Models\Wbw;
 use App\Models\Wbw;
 use App\Models\WbwBlock;
 use App\Models\WbwBlock;
 use App\Models\PaliSentence;
 use App\Models\PaliSentence;
 use App\Models\Sentence;
 use App\Models\Sentence;
-use Illuminate\Http\Request;
 use App\Http\Resources\DiscussionResource;
 use App\Http\Resources\DiscussionResource;
 use App\Http\Api\MdRender;
 use App\Http\Api\MdRender;
 use App\Http\Api\AuthApi;
 use App\Http\Api\AuthApi;
 use App\Http\Api\Mq;
 use App\Http\Api\Mq;
-use Illuminate\Support\Facades\Log;
 
 
 class DiscussionController extends Controller
 class DiscussionController extends Controller
 {
 {
@@ -77,15 +77,12 @@ class DiscussionController extends Controller
 
 
         $result = $table->get();
         $result = $table->get();
 
 
-        if($result){
-			return $this->ok(["rows"=>DiscussionResource::collection($result),
-                              "count"=>$count,
-                              'active'=>$activeNumber,
-                              'close'=>$closeNumber,
-                            ]);
-		}else{
-			return $this->error("没有查询到数据");
-		}
+        return $this->ok(["rows"=>DiscussionResource::collection($result),
+                            "count"=>$count,
+                            'active'=>$activeNumber,
+                            'close'=>$closeNumber,
+                        ]);
+
     }
     }
 
 
     public function discussion_tree(Request $request){
     public function discussion_tree(Request $request){

+ 127 - 0
app/Http/Controllers/NotificationController.php

@@ -0,0 +1,127 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Support\Str;
+use App\Models\Notification;
+use App\Http\Api\AuthApi;
+use App\Http\Resources\NotificationResource;
+
+class NotificationController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index(Request $request)
+    {
+        //
+        $user = AuthApi::current($request);
+        if(!$user){
+            Log::error('notification auth failed {request}',['request'=>$request]);
+            return $this->error(__('auth.failed'),401,401);
+        }
+        switch ($request->get('view')) {
+            case 'to':
+                $table = Notification::where('to',$user['user_uid']);
+                $unread = Notification::where('to',$user['user_uid'])
+                                    ->where('status','unread')->count();
+                break;
+        }
+
+        if($request->has('status')){
+            $table = $table->whereIn('status',explode(',',$request->get('status')) );
+        }
+        $count = $table->count();
+
+        $table = $table->orderBy($request->get('order','created_at'),$request->get('dir','desc'));
+
+        $table = $table->skip($request->get("offset",0))
+                    ->take($request->get('limit',10));
+
+        $result = $table->get();
+
+        return $this->ok(
+            [
+            "rows"=>NotificationResource::collection($result),
+            "count"=>$count,
+            'unread'=>$unread,
+            ]);
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+        $user = AuthApi::current($request);
+        if(!$user){
+            Log::error('notification auth failed {request}',['request'=>$request]);
+            return $this->error(__('auth.failed'),401,401);
+        }
+        $new = new Notification;
+        $new->id = Str::uuid();
+        $new->from = $user['user_uid'];
+        $new->to = $request->get('to');
+        $new->url = $request->get('url');
+        $new->content = $request->get('content');
+        $new->res_type = $request->get('res_type');
+        $new->res_id = $request->get('res_id');
+        $new->save();
+
+        return $this->ok(new NotificationResource($new));
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  Notification $notification
+     * @return \Illuminate\Http\Response
+     */
+    public function show(Notification $notification)
+    {
+        //
+        return $this->ok(new NotificationResource($notification));
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  Notification $notification
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, Notification $notification)
+    {
+        //
+        $notification->status = $request->get('status','read');
+        $notification->save();
+        $unread = Notification::where('to',$notification->to)
+                            ->where('status','unread')
+                            ->count();
+        return $this->ok(['unread'=>$unread]);
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  Notification $notification
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Notification $notification)
+    {
+        //
+        $notification->delete();
+        if($notification->trashed()){
+            return $this->ok('ok');
+        }else{
+            return $this->error('fail',500,500);
+        }
+    }
+}

+ 4 - 1
app/Http/Controllers/SentPrController.php

@@ -3,6 +3,7 @@
 
 
 namespace App\Http\Controllers;
 namespace App\Http\Controllers;
 
 
+use Illuminate\Support\Str;
 use App\Http\Api\AuthApi;
 use App\Http\Api\AuthApi;
 use App\Models\SentPr;
 use App\Models\SentPr;
 use App\Models\Channel;
 use App\Models\Channel;
@@ -118,6 +119,7 @@ class SentPrController extends Controller
         #不存在,新建
         #不存在,新建
         $new = new SentPr();
         $new = new SentPr();
         $new->id = app('snowflake')->id();
         $new->id = app('snowflake')->id();
+        $new->uid = Str::uuid();
         $new->book_id = $data['book'];
         $new->book_id = $data['book'];
         $new->paragraph = $data['para'];
         $new->paragraph = $data['para'];
         $new->word_start = $data['begin'];
         $new->word_start = $data['begin'];
@@ -131,7 +133,8 @@ class SentPrController extends Controller
         $new->create_time = time()*1000;
         $new->create_time = time()*1000;
         $new->modify_time = time()*1000;
         $new->modify_time = time()*1000;
         $new->save();
         $new->save();
-        Mq::publish('suggestion',new SentPrResource($new));
+        Mq::publish('suggestion',['data'=>new SentPrResource($new),
+                                  'token'=>AuthApi::getToken($request)]);
 
 
 		$robotMessageOk=false;
 		$robotMessageOk=false;
 		$webHookMessage="";
 		$webHookMessage="";

+ 33 - 0
app/Http/Resources/NotificationResource.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Http\Resources;
+
+use Illuminate\Http\Resources\Json\JsonResource;
+use App\Http\Api\UserApi;
+
+class NotificationResource extends JsonResource
+{
+    /**
+     * Transform the resource into an array.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
+     */
+    public function toArray($request)
+    {
+        $data = [
+            "id"=>$this->id,
+            "from"=> UserApi::getByUuid($this->from),
+            "to"=> UserApi::getByUuid($this->to),
+            "url"=> $this->url,
+            "content"=> $this->content,
+            "content_type"=> $this->content_type,
+            "res_type"=> $this->res_type,
+            "res_id"=> $this->res_id,
+            "status"=> $this->status,
+            "created_at"=> $this->created_at,
+            "updated_at"=> $this->updated_at,
+        ];
+        return $data;
+    }
+}

+ 1 - 0
app/Http/Resources/SentPrResource.php

@@ -28,6 +28,7 @@ class SentPrResource extends JsonResource
         $mode = $request->get("mode",'read');
         $mode = $request->get("mode",'read');
         return [
         return [
             "id"=>$this->id,
             "id"=>$this->id,
+            "uid"=>$this->uid,
             "book"=> $this->book_id,
             "book"=> $this->book_id,
             "paragraph"=> $this->paragraph,
             "paragraph"=> $this->paragraph,
             "word_start"=> $this->word_start,
             "word_start"=> $this->word_start,

+ 16 - 0
app/Models/Notification.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Notification extends Model
+{
+    use HasFactory;
+    protected $primaryKey = 'id';
+	protected $casts = [
+		'id' => 'string'
+	];
+    protected $dates = ['delete_at'];
+}

+ 40 - 0
database/migrations/2023_12_17_033134_create_notifications_table.php

@@ -0,0 +1,40 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateNotificationsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('notifications', function (Blueprint $table) {
+            $table->uuid('id')->primary();
+            $table->uuid('from')->index();
+            $table->uuid('to')->index();
+            $table->string('url',1024)->nullable();
+            $table->text('content')->nullable()->index();
+            $table->string('content_type',16)->index()->default('markdown');
+            $table->string('res_type',32)->index();
+            $table->uuid('res_id')->index();
+            $table->string('status',32)->index()->default('unread');
+            $table->softDeletes();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('notifications');
+    }
+}

+ 35 - 0
database/migrations/2023_12_17_112858_add_uid_in_sent_prs.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddUidInSentPrs extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('sent_prs', function (Blueprint $table) {
+            //
+            $table->uuid('uid')->default(DB::raw('uuid_generate_v1mc()'));
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('sent_prs', function (Blueprint $table) {
+            //
+            $table->dropColumn('uid');
+        });
+    }
+}

+ 2 - 0
routes/api.php

@@ -84,6 +84,7 @@ use App\Http\Controllers\NavArticleController;
 use App\Http\Controllers\NavCSParaController;
 use App\Http\Controllers\NavCSParaController;
 use App\Http\Controllers\SentencesInChapterController;
 use App\Http\Controllers\SentencesInChapterController;
 use App\Http\Controllers\CompoundController;
 use App\Http\Controllers\CompoundController;
+use App\Http\Controllers\NotificationController;
 
 
 /*
 /*
 |--------------------------------------------------------------------------
 |--------------------------------------------------------------------------
@@ -223,6 +224,7 @@ Route::group(['prefix' => 'v2'],function(){
     Route::apiResource('book-title',BookTitleController::class);
     Route::apiResource('book-title',BookTitleController::class);
     Route::apiResource('sentences-in-chapter',SentencesInChapterController::class);
     Route::apiResource('sentences-in-chapter',SentencesInChapterController::class);
     Route::apiResource('compound',CompoundController::class);
     Route::apiResource('compound',CompoundController::class);
+    Route::apiResource('notification',NotificationController::class);
 
 
     Route::get('download/{type1}/{type2}/{uuid}/{filename}', function ($type1,$type2,$uuid,$filename) {
     Route::get('download/{type1}/{type2}/{uuid}/{filename}', function ($type1,$type2,$uuid,$filename) {
         header("Content-Type: {$type1}/{$type1}");
         header("Content-Type: {$type1}/{$type1}");