notices and tg-bot module created
This commit is contained in:
parent
c2501e8a29
commit
57b1c744b9
18
app/Http/Controllers/NotificationProbeController.php
Normal file
18
app/Http/Controllers/NotificationProbeController.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\Deal\Deal;
|
||||||
|
|
||||||
|
use App\Notifications\UniqueContact;
|
||||||
|
|
||||||
|
class NotificationProbeController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
auth()->user()->notify(new UniqueContact(Deal::find(4)));
|
||||||
|
echo auth()->user()->unreadNotifications->count() . '<br>';
|
||||||
|
die(auth()->user()->notifications);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,11 @@
|
|||||||
@php($title = 'Жилые комплексы')
|
@php($title = 'Жилой комплекс «' . $complex->name . '»')
|
||||||
|
@php($backUrl = route('admin.complexes'))
|
||||||
@extends('layouts.admin')
|
@extends('layouts.admin')
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 p-3">
|
<div class="fs-5 bg-light p-0 m-0 border border-1 rounded-4 p-3">
|
||||||
<h4 class="fw-bold my-3">{{ $complex->name }}</h4>
|
<h4 class="fw-bold my-3">
|
||||||
|
Редактирование
|
||||||
|
</h4>
|
||||||
<form action="{{ route('admin.complexes.update', ['complex' => $complex]) }}" method="post"
|
<form action="{{ route('admin.complexes.update', ['complex' => $complex]) }}" method="post"
|
||||||
enctype="multipart/form-data">
|
enctype="multipart/form-data">
|
||||||
@csrf
|
@csrf
|
||||||
@ -28,6 +31,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary">Сохранить</button>
|
<button type="submit" class="btn btn-primary">Сохранить</button>
|
||||||
|
<a class="btn btn-secondary" href="{{ route('admin.complexes') }}">Отмена</a>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|||||||
14
app/Modules/Bot/Config/config.php
Normal file
14
app/Modules/Bot/Config/config.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'telegram_bot_token' => '8108664710:AAG4sNtP02P0a6ElSHpCypsYV77EZCADwSo',
|
||||||
|
'telegram_bot_identifier' => 'testnaviomiro38_bot',
|
||||||
|
'telegram_bot_id' => 1,
|
||||||
|
'telegram_type' => 'Telegram',
|
||||||
|
|
||||||
|
'vk_bot_id' => 2,
|
||||||
|
'vk_type' => 'Vk',
|
||||||
|
'vk_group_token' => 'vk1.a.s1l2J2Nri9FukE8m-eIAjq1fgBMXO_O5WR6T-cCoDjetrY9XrVggY2JyhGDv5pcTeJQuX16OxUrcCaTLagjIyp1w1A6CXKstsCPcnIxDm0GATK15360lhQ5SFjT0ciYh809wf22cQbFssHkkQj6shGzhVvJC7rdpjXNmdMyPs2geiaxktWjEVM7-2oIUrcOrs-zeGxKeucJ7_ofstL4g0A',
|
||||||
|
'vk_group_id' => 227931308,
|
||||||
|
'vk_group_confirmation' => '1bb6fd31'
|
||||||
|
];
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('messenger_bots', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('type');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Добавляем запись с type "Telegram"
|
||||||
|
DB::table('messenger_bots')->insertOrIgnore([
|
||||||
|
'type' => 'Telegram',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('messenger_bots');
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
// Добавляем запись с type "Vk"
|
||||||
|
DB::table('messenger_bots')->insertOrIgnore([
|
||||||
|
'type' => 'Vk',
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
DB::table('messenger_bots')->where('type', 'Vk')->delete();
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('user_bots', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('bot_id')->constrained(
|
||||||
|
table: 'messenger_bots',
|
||||||
|
indexName: 'messenger_bots_bot_id_foreign_key'
|
||||||
|
)->onDelete('cascade');
|
||||||
|
$table->foreignId('user_id')->constrained(
|
||||||
|
table: 'users',
|
||||||
|
indexName: 'users_user_id_foreign_key'
|
||||||
|
)->onDelete('cascade');
|
||||||
|
$table->string('user_bot_id');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('user_bots');
|
||||||
|
}
|
||||||
|
};
|
||||||
28
app/Modules/Bot/Http/Controllers/BotNotificationSender.php
Normal file
28
app/Modules/Bot/Http/Controllers/BotNotificationSender.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Bot\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Modules\Bot\Models\UserBot;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class BotNotificationSender {
|
||||||
|
|
||||||
|
public static function routeMessage(int $userId, string $message): void
|
||||||
|
{
|
||||||
|
$userBots = UserBot::where('user_id', $userId)->with('bot')->get();
|
||||||
|
|
||||||
|
foreach ($userBots as $userBot) {
|
||||||
|
switch ($userBot->bot->type) {
|
||||||
|
case config('bot.telegram_type'):
|
||||||
|
TelegramBot::sendMessage($userBot->user_bot_id, $message);
|
||||||
|
break;
|
||||||
|
case config('bot.vk_type'):
|
||||||
|
VkBot::sendMessage($userBot->user_bot_id, $message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log::warning("Unknown bot type: {$userBot->bot->type}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
161
app/Modules/Bot/Http/Controllers/TelegramBot.php
Normal file
161
app/Modules/Bot/Http/Controllers/TelegramBot.php
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Bot\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Modules\Bot\Http\Interfaces\MessengerBotInterface;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Modules\Bot\Models\UserBot;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class TelegramBot implements MessengerBotInterface
|
||||||
|
{
|
||||||
|
private $botIdentifier;
|
||||||
|
private $botToken;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->botIdentifier = config('bot.telegram_bot_identifier');
|
||||||
|
$this->botToken = config('bot.telegram_bot_token');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleWebhook(Request $request)
|
||||||
|
{
|
||||||
|
$update = $request->all();
|
||||||
|
|
||||||
|
if (isset($update['message'])) {
|
||||||
|
$this->handleMessage($update['message']);
|
||||||
|
} elseif (isset($update['my_chat_member'])) {
|
||||||
|
$this->handleChatMemberUpdate($update['my_chat_member']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMessage($message)
|
||||||
|
{
|
||||||
|
if (isset($message['text'])) {
|
||||||
|
$text = $message['text'];
|
||||||
|
$chatId = $message['chat']['id'];
|
||||||
|
$command = strtolower(explode(' ', $text)[0]);
|
||||||
|
|
||||||
|
switch ($command) {
|
||||||
|
case '/start':
|
||||||
|
$this->handleStart($text, $chatId);
|
||||||
|
break;
|
||||||
|
case '/stop':
|
||||||
|
$this->handleUnsubscribe($chatId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleChatMemberUpdate($chatMember)
|
||||||
|
{
|
||||||
|
$chatId = $chatMember['chat']['id'];
|
||||||
|
$newStatus = $chatMember['new_chat_member']['status'];
|
||||||
|
|
||||||
|
if ($newStatus === 'kicked' || $newStatus === 'left') {
|
||||||
|
$this->stopBot($chatId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleStart($text, $chatId)
|
||||||
|
{
|
||||||
|
$parts = explode(' ', $text);
|
||||||
|
if (count($parts) > 1) {
|
||||||
|
$encryptedUserId = $parts[1];
|
||||||
|
try {
|
||||||
|
$userId = base64_decode($encryptedUserId);
|
||||||
|
|
||||||
|
$user = User::find($userId);
|
||||||
|
if ($user) {
|
||||||
|
UserBot::updateOrCreate(
|
||||||
|
['user_id' => $userId, 'bot_id' => config('bot.telegram_bot_id')],
|
||||||
|
['user_bot_id' => $chatId]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->sendMessage($chatId, "Здравствуйте, {$user->name}! Вы успешно подписались на уведомления.");
|
||||||
|
} else {
|
||||||
|
$this->sendMessage($chatId, "Извините, не удалось найти вашу учетную запись.");
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Error decrypting user ID', ['error' => $e->getMessage()]);
|
||||||
|
$this->sendMessage($chatId, "Произошла ошибка при обработке вашего запроса.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->sendMessage($chatId, "Добро пожаловать! Для подписки на уведомления, пожалуйста, используйте ссылку с нашего сайта.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function stopBot($chatId)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$userBot = UserBot::where('user_bot_id', $chatId)
|
||||||
|
->where('bot_id', config('bot.telegram_bot_id'))
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($userBot) {
|
||||||
|
$userBot->delete();
|
||||||
|
Log::info('User unsubscribed', ['chatId' => $chatId]);
|
||||||
|
} else {
|
||||||
|
Log::info('Unsubscribe attempt for non-subscribed user', ['chatId' => $chatId]);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Error during unsubscribe process', ['error' => $e->getMessage(), 'chatId' => $chatId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleUnsubscribe($chatId)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$userBot = UserBot::where('user_bot_id', $chatId)
|
||||||
|
->where('bot_id', config('bot.telegram_bot_id'))
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($userBot) {
|
||||||
|
$userBot->delete();
|
||||||
|
$this->sendMessage($chatId, "Вы успешно отписались от уведомлений. Если захотите подписаться снова, воспользуйтесь ссылкой на нашем сайте.");
|
||||||
|
Log::info('User unsubscribed', ['chatId' => $chatId]);
|
||||||
|
} else {
|
||||||
|
$this->sendMessage($chatId, "Вы не были подписаны на уведомления.");
|
||||||
|
Log::info('Unsubscribe attempt for non-subscribed user', ['chatId' => $chatId]);
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Log::error('Error during unsubscribe process', ['error' => $e->getMessage(), 'chatId' => $chatId]);
|
||||||
|
$this->sendMessage($chatId, "Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function subscribe() :mixed
|
||||||
|
{
|
||||||
|
$userId = Auth::id();
|
||||||
|
$encryptedUserId = base64_encode($userId);
|
||||||
|
|
||||||
|
$telegramUrl = "https://t.me/$this->botIdentifier?start=$encryptedUserId";
|
||||||
|
|
||||||
|
return redirect($telegramUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function sendMessage(string $userBotId, string $message): void
|
||||||
|
{
|
||||||
|
$botToken = config('bot.telegram_bot_token');
|
||||||
|
Http::withoutVerifying()
|
||||||
|
->post("https://api.telegram.org/bot{$botToken}/sendMessage", [
|
||||||
|
'chat_id' => $userBotId,
|
||||||
|
'text' => $message,
|
||||||
|
'parse_mode' => 'HTML'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHook()
|
||||||
|
{
|
||||||
|
$response = Http::withoutVerifying()
|
||||||
|
->post("https://api.telegram.org/bot{$this->botToken}/setWebhook", [
|
||||||
|
'url' => 'https://naviom.iro38.ru/api/telegramWebhook',
|
||||||
|
'allowed_updates' => ['message', 'my_chat_member']
|
||||||
|
])->json();
|
||||||
|
dd($response);
|
||||||
|
}
|
||||||
|
}
|
||||||
75
app/Modules/Bot/Http/Controllers/VkBot.php
Normal file
75
app/Modules/Bot/Http/Controllers/VkBot.php
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Bot\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Modules\Bot\Http\Interfaces\MessengerBotInterface;
|
||||||
|
use App\Modules\Bot\Models\UserBot;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class VkBot implements MessengerBotInterface
|
||||||
|
{
|
||||||
|
private int $botId;
|
||||||
|
private int $groupId;
|
||||||
|
private string $groupConfirmation;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->botId = config('bot.vk_bot_id');
|
||||||
|
$this->groupId = config('bot.vk_group_id');
|
||||||
|
$this->groupConfirmation = config('bot.vk_group_confirmation');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function sendMessage(string $userBotId, string $message): void
|
||||||
|
{
|
||||||
|
Log::info('Попытка отправить сообщение');
|
||||||
|
$params['access_token'] = config('bot.vk_group_token');
|
||||||
|
$params['v'] = '5.199';
|
||||||
|
$params['random_id'] = random_int(1, PHP_INT_MAX);
|
||||||
|
$params['user_id'] = $userBotId;
|
||||||
|
$params['message'] = $message;
|
||||||
|
|
||||||
|
$response = Http::withoutVerifying()->withQueryParameters($params)->post("https://api.vk.com/method/messages.send");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function allowMessages(Request $request)
|
||||||
|
{
|
||||||
|
if ($request->vkUserId and $request->naviomUserId and User::find($request->naviomUserId)) {
|
||||||
|
UserBot::updateOrCreate(
|
||||||
|
['user_id' => $request->naviomUserId, 'bot_id' => $this->botId],
|
||||||
|
['user_bot_id' => $request->vkUserId]
|
||||||
|
);
|
||||||
|
$user = User::find($request->naviomUserId);
|
||||||
|
$this->sendMessage($request->vkUserId, "Здравствуйте, {$user->name}! Вы успешно подписались на уведомления.");
|
||||||
|
}
|
||||||
|
return response()->json(['success' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleVkCallback(Request $request)
|
||||||
|
{
|
||||||
|
switch ($request->type) {
|
||||||
|
case 'confirmation':
|
||||||
|
return $this->handleConfirmation($request->group_id);
|
||||||
|
case 'message_deny':
|
||||||
|
return $this->handleDenyMessage($request->object['user_id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleConfirmation(int $groupId): string
|
||||||
|
{
|
||||||
|
if ($groupId == $this->groupId) {
|
||||||
|
return $this->groupConfirmation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleDenyMessage(int $vkUserId): string
|
||||||
|
{
|
||||||
|
$subscription = UserBot::where('user_bot_id', $vkUserId)->where('bot_id', $this->botId)->first();
|
||||||
|
if ($subscription) {
|
||||||
|
$subscription->delete();
|
||||||
|
}
|
||||||
|
return 'ok';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Modules\Bot\Http\Interfaces;
|
||||||
|
|
||||||
|
interface MessengerBotInterface {
|
||||||
|
|
||||||
|
public static function sendMessage(string $userBotId, string $message): void;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
13
app/Modules/Bot/Models/Bot.php
Normal file
13
app/Modules/Bot/Models/Bot.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Modules\Bot\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Bot extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = ['name'];
|
||||||
|
}
|
||||||
11
app/Modules/Bot/Models/MessengerBot.php
Normal file
11
app/Modules/Bot/Models/MessengerBot.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Modules\Bot\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class MessengerBot extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
}
|
||||||
22
app/Modules/Bot/Models/UserBot.php
Normal file
22
app/Modules/Bot/Models/UserBot.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Modules\Bot\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class UserBot extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'bot_id',
|
||||||
|
'user_id',
|
||||||
|
'user_bot_id'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function bot()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MessengerBot::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
68
app/Modules/Bot/Providers/ModuleServiceProvider.php
Normal file
68
app/Modules/Bot/Providers/ModuleServiceProvider.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Bot\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
|
||||||
|
class ModuleServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
protected String $moduleName = 'Bot';
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->register(RouteServiceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->registerViews();
|
||||||
|
$this->registerLivewireViews();
|
||||||
|
$this->registerMigrations();
|
||||||
|
$this->registerConfig();
|
||||||
|
$this->registerComponent();
|
||||||
|
$this->registerLivewire();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerViews()
|
||||||
|
{
|
||||||
|
$moduleViewsPath = __DIR__.'/../Views';
|
||||||
|
$this->loadViewsFrom(
|
||||||
|
$moduleViewsPath, strtolower($this->moduleName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerLivewireViews()
|
||||||
|
{
|
||||||
|
$moduleViewsPath = __DIR__.'/../Views/livewire';
|
||||||
|
$this->loadViewsFrom(
|
||||||
|
$moduleViewsPath, strtolower($this->moduleName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerMigrations()
|
||||||
|
{
|
||||||
|
$this->loadMigrationsFrom(
|
||||||
|
app_path('Modules/'.$this->moduleName.'/Database/Migrations')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerConfig()
|
||||||
|
{
|
||||||
|
$path = app_path('Modules/'.$this->moduleName.'/Config/config.php');
|
||||||
|
$this->mergeConfigFrom(
|
||||||
|
$path, strtolower($this->moduleName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerLivewire()
|
||||||
|
{
|
||||||
|
//Livewire::component('<name>', \Modules\<NAME>\Http\Livewire\<NAME>::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerComponent()
|
||||||
|
{
|
||||||
|
//Blade::component('<name>', \Modules\<NAME>\Http\Components\<NAME>::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/Modules/Bot/Providers/RouteServiceProvider.php
Normal file
24
app/Modules/Bot/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Bot\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
public function map()
|
||||||
|
{
|
||||||
|
$this->registerWebRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerWebRoutes()
|
||||||
|
{
|
||||||
|
//Add Web Routes with web Guard
|
||||||
|
Route::middleware('web')
|
||||||
|
//Set Default Controllers Namespace
|
||||||
|
->namespace('Modules\\Bot\\Http\\Controllers')
|
||||||
|
->group(app_path('Modules/Bot/Routes/web.php'));
|
||||||
|
}
|
||||||
|
}
|
||||||
20
app/Modules/Bot/Routes/web.php
Normal file
20
app/Modules/Bot/Routes/web.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Modules\Bot\Http\Controllers\TelegramBot;
|
||||||
|
use Modules\Bot\Http\Controllers\VkBot;
|
||||||
|
|
||||||
|
Route::middleware(['auth'])->group(function() {
|
||||||
|
|
||||||
|
Route::get('/telegram/subscribe',[TelegramBot::class, 'subscribe'])->name('telegram.subscribe');
|
||||||
|
Route::get('/telegramHook', [TelegramBot::class, 'setHook'])->name('setHook');
|
||||||
|
|
||||||
|
Route::post('/vk/allowMessages',[VkBot::class, 'allowMessages'])->name('vk.allowMessages');
|
||||||
|
|
||||||
|
|
||||||
|
Route::middleware(['hasAccess'])->group(function() {
|
||||||
|
/** Routes that need to be protected - Маршруты которые нужно защитить */
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
4
app/Modules/Bot/Views/index.blade.php
Normal file
4
app/Modules/Bot/Views/index.blade.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
<h1> Example views </h1>
|
||||||
|
@endsection
|
||||||
5
app/Modules/Notice/Config/config.php
Normal file
5
app/Modules/Notice/Config/config.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
5
app/Modules/Notice/Config/notices.php
Normal file
5
app/Modules/Notice/Config/notices.php
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'new Recomendation' => 'NewRecomendationNotice',
|
||||||
|
];
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
/*Schema::create('notifications', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('user_id')->constrained(
|
||||||
|
table: 'users', indexName: 'notifications_user_id_foreign_key'
|
||||||
|
)->onDelete('cascade');
|
||||||
|
$table->string('action');
|
||||||
|
$table->string('object_name');
|
||||||
|
$table->unsignedInteger('object_id');
|
||||||
|
$table->date('read_at')->nullable();
|
||||||
|
$table->date('sended_to_email_at')->nullable();
|
||||||
|
$table->date('disabled_at')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('notifications', function (Blueprint $table) {
|
||||||
|
$table->unique(['user_id', 'action', 'object_name', 'object_id']);
|
||||||
|
});*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
//Schema::dropIfExists('notifications');
|
||||||
|
}
|
||||||
|
};
|
||||||
25
app/Modules/Notice/Http/Controllers/NoticeController.php
Normal file
25
app/Modules/Notice/Http/Controllers/NoticeController.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Http\Controllers;
|
||||||
|
|
||||||
|
use Modules\Notice\Models\Notice;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
use Modules\Notice\Models\UnreadMessagesMailer;
|
||||||
|
|
||||||
|
class NoticeController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return view('notice::index');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$mailer = new UnreadMessagesMailer();
|
||||||
|
$mailer->run();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
app/Modules/Notice/Http/Livewire/UserNotices.php
Normal file
23
app/Modules/Notice/Http/Livewire/UserNotices.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Http\Livewire;
|
||||||
|
|
||||||
|
use Livewire\Component;
|
||||||
|
use Illuminate\Notifications\DatabaseNotification;
|
||||||
|
|
||||||
|
class UserNotices extends Component
|
||||||
|
{
|
||||||
|
public function read(DatabaseNotification $notice)
|
||||||
|
{
|
||||||
|
$notice->markAsRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
$currentDate = date("Y-m-d");
|
||||||
|
$startDate = date("Y-m-d", strtotime($currentDate . " -2 months"));
|
||||||
|
return view('notice::user-notifications', [
|
||||||
|
'notifications' => auth()->user()->notifications
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
23
app/Modules/Notice/Http/Livewire/UserNoticesButton.php
Normal file
23
app/Modules/Notice/Http/Livewire/UserNoticesButton.php
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Http\Livewire;
|
||||||
|
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
use Modules\Notice\Models\Notice;
|
||||||
|
use Modules\Chat\Models\ChatMessageRead;
|
||||||
|
|
||||||
|
class UserNoticesButton extends Component
|
||||||
|
{
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
$currentDate = date("Y-m-d");
|
||||||
|
$startDate = date("Y-m-d", strtotime($currentDate . " -2 months"));
|
||||||
|
|
||||||
|
return view('notice::user-notices-button', [
|
||||||
|
'unreadedCount' =>
|
||||||
|
auth()->user()->unreadNotifications
|
||||||
|
->count()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Modules/Notice/Models/NewWayMeetingNotice.php
Normal file
22
app/Modules/Notice/Models/NewWayMeetingNotice.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Models;
|
||||||
|
|
||||||
|
use Modules\Notice\Models\Notice;
|
||||||
|
|
||||||
|
use App\Models\Meeting\WayMeeting;
|
||||||
|
|
||||||
|
class NewWayMeetingNotice
|
||||||
|
{
|
||||||
|
public static function getParameters(Notice $notice)
|
||||||
|
{
|
||||||
|
$wayMeeting = WayMeeting::find($notice->object_id);
|
||||||
|
if (!$wayMeeting)
|
||||||
|
return false;
|
||||||
|
return [
|
||||||
|
'id' => $wayMeeting->id,
|
||||||
|
'name' => $wayMeeting->meeting->name,
|
||||||
|
'action' => route('way.index', ['way' => $wayMeeting->way->id]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
39
app/Modules/Notice/Models/Notice.php
Normal file
39
app/Modules/Notice/Models/Notice.php
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Notice extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'notices';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'user_id',
|
||||||
|
'action',
|
||||||
|
'object_name',
|
||||||
|
'object_id',
|
||||||
|
'read_at'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function toString()
|
||||||
|
{
|
||||||
|
$noticeName = "$this->action $this->object_name";
|
||||||
|
$noticeClass = __DIR__ . '/' . config('notice.types.' . $noticeName);
|
||||||
|
if (file_exists($noticeClass . '.php')) {
|
||||||
|
$noticeClass = 'Modules\\Notice\\Models\\' . config('notice.types.' . $noticeName);
|
||||||
|
if ($parameters = $noticeClass::getParameters($this)) {
|
||||||
|
return __("notification.$this->action $this->object_name", $parameters);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return FALSE;
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function created_at()
|
||||||
|
{
|
||||||
|
return date_format(date_create($this->created_at), env('DATETIME_FORMAT'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
72
app/Modules/Notice/Models/NoticesMailer.php
Normal file
72
app/Modules/Notice/Models/NoticesMailer.php
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Models;
|
||||||
|
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Illuminate\Support\Facades\Notification;
|
||||||
|
|
||||||
|
use App\Notifications\NoticesMailerNotification;
|
||||||
|
use Modules\Notice\Models\Notice;
|
||||||
|
use Modules\Bot\Http\Controllers\BotNotificationSender;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
|
||||||
|
class NoticesMailer
|
||||||
|
{
|
||||||
|
use Notifiable;
|
||||||
|
|
||||||
|
private $user;
|
||||||
|
private $notices;
|
||||||
|
private $messages;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$date = Carbon::now();
|
||||||
|
//$date->subDays(1);
|
||||||
|
$date = $date->toDateTimeString();
|
||||||
|
$latest_notice = Notice::where('created_at', '<=', $date)
|
||||||
|
->whereNull('sended_to_email_at')
|
||||||
|
->whereNull('read_at')
|
||||||
|
->orderBy('created_at', 'desc');
|
||||||
|
if ($latest_notice = $latest_notice->first()) {
|
||||||
|
$this->user = User::findOrFail($latest_notice->user_id);
|
||||||
|
$this->notices = Notice::where('user_id', $this->user->id)
|
||||||
|
->whereNull('sended_to_email_at')
|
||||||
|
->whereNull('read_at')
|
||||||
|
->orderBy('object_name')
|
||||||
|
->orderBy('created_at')->get();
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
if (!$this->user) {
|
||||||
|
Log::error('Has no notices for mailing');
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($this->notices->count() == 0) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$notification = new NoticesMailerNotification($this->notices);
|
||||||
|
|
||||||
|
Notification::route('mail', $this->user->email)
|
||||||
|
->notify($notification);
|
||||||
|
|
||||||
|
$botMessage = $notification->buildBotMessage();
|
||||||
|
BotNotificationSender::routeMessage($this->user->id, $botMessage);
|
||||||
|
|
||||||
|
foreach ($this->notices as $notice) {
|
||||||
|
$notice->sended_to_email_at = now();
|
||||||
|
$notice->save();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
69
app/Modules/Notice/Models/UnreadMessagesMailer.php
Normal file
69
app/Modules/Notice/Models/UnreadMessagesMailer.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Models;
|
||||||
|
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Illuminate\Support\Facades\Notification;
|
||||||
|
|
||||||
|
use App\Notifications\NewChatMessageNoticesMailerNotification;
|
||||||
|
use Modules\Notice\Models\Notice;
|
||||||
|
use Modules\Chat\Models\Chat;
|
||||||
|
use Modules\Chat\Models\ChatMessage;
|
||||||
|
use Modules\Chat\Models\ChatMessageRead;
|
||||||
|
use App\Models\User;
|
||||||
|
use Modules\Bot\Http\Controllers\BotNotificationSender;
|
||||||
|
|
||||||
|
class UnreadMessagesMailer
|
||||||
|
{
|
||||||
|
use Notifiable;
|
||||||
|
|
||||||
|
private $user;
|
||||||
|
private $notices;
|
||||||
|
private $senders;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$newChatNotice = Notice::whereNull('sended_to_email_at')
|
||||||
|
->whereNull('read_at')
|
||||||
|
->where('object_name', 'Chat')
|
||||||
|
->orderBy('created_at');
|
||||||
|
if ($newChatNotice = $newChatNotice->first()) {
|
||||||
|
$this->user = User::findOrFail($newChatNotice->user_id);
|
||||||
|
$this->notices = Notice::where('user_id', $this->user->id)
|
||||||
|
->whereNull('sended_to_email_at')
|
||||||
|
->whereNull('read_at')
|
||||||
|
->where('object_name', 'Chat')
|
||||||
|
->orderBy('created_at')->get();
|
||||||
|
//$this->senders = ChatMessageRead::where('receiver_id', $this->user->id)->where('message.sender_id');
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
if (!$this->user) {
|
||||||
|
//Log::error('Has no notices for mailing');
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($this->notices->count() == 0) {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$notification = new NewChatMessageNoticesMailerNotification();
|
||||||
|
|
||||||
|
Notification::route('mail', $this->user->email)
|
||||||
|
->notify($notification);
|
||||||
|
|
||||||
|
$botMessage = $notification->buildBotMessage();
|
||||||
|
BotNotificationSender::routeMessage($this->user->id, $botMessage);
|
||||||
|
|
||||||
|
foreach ($this->notices as $notice) {
|
||||||
|
$notice->sended_to_email_at = now();
|
||||||
|
$notice->save();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
78
app/Modules/Notice/Providers/ModuleServiceProvider.php
Normal file
78
app/Modules/Notice/Providers/ModuleServiceProvider.php
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Livewire\Livewire;
|
||||||
|
|
||||||
|
class ModuleServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
protected string $moduleName = 'Notice';
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->register(RouteServiceProvider::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->registerViews();
|
||||||
|
$this->registerLivewireViews();
|
||||||
|
$this->registerMigrations();
|
||||||
|
$this->registerConfig();
|
||||||
|
$this->registerComponent();
|
||||||
|
$this->registerLivewire();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerViews()
|
||||||
|
{
|
||||||
|
$moduleViewsPath = __DIR__ . '/../Views';
|
||||||
|
$this->loadViewsFrom(
|
||||||
|
$moduleViewsPath,
|
||||||
|
strtolower($this->moduleName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerLivewireViews()
|
||||||
|
{
|
||||||
|
$moduleViewsPath = __DIR__ . '/../Views/livewire';
|
||||||
|
$this->loadViewsFrom(
|
||||||
|
$moduleViewsPath,
|
||||||
|
strtolower($this->moduleName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerMigrations()
|
||||||
|
{
|
||||||
|
$this->loadMigrationsFrom(
|
||||||
|
app_path('Modules/' . $this->moduleName . '/Database/Migrations')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerConfig()
|
||||||
|
{
|
||||||
|
$path = app_path('Modules/' . $this->moduleName . '/Config/config.php');
|
||||||
|
$this->mergeConfigFrom(
|
||||||
|
$path,
|
||||||
|
strtolower($this->moduleName)
|
||||||
|
);
|
||||||
|
|
||||||
|
$path = app_path('Modules/' . $this->moduleName . '/Config/notices.php');
|
||||||
|
$this->mergeConfigFrom(
|
||||||
|
$path,
|
||||||
|
'notice.types'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerLivewire()
|
||||||
|
{
|
||||||
|
Livewire::component('notices.user-notices', \Modules\Notice\Http\Livewire\UserNotices::class);
|
||||||
|
Livewire::component('notices.user-notices-button', \Modules\Notice\Http\Livewire\UserNoticesButton::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerComponent()
|
||||||
|
{
|
||||||
|
//Blade::component('<name>', \Modules\<NAME>\Http\Components\<NAME>::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
app/Modules/Notice/Providers/RouteServiceProvider.php
Normal file
24
app/Modules/Notice/Providers/RouteServiceProvider.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Notice\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
class RouteServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
|
||||||
|
public function map()
|
||||||
|
{
|
||||||
|
$this->registerWebRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function registerWebRoutes()
|
||||||
|
{
|
||||||
|
//Add Web Routes with web Guard
|
||||||
|
Route::middleware('web')
|
||||||
|
//Set Default Controllers Namespace
|
||||||
|
->namespace('Modules\\Notice\\Http\\Controllers')
|
||||||
|
->group(app_path('Modules/Notice/Routes/web.php'));
|
||||||
|
}
|
||||||
|
}
|
||||||
14
app/Modules/Notice/Routes/web.php
Normal file
14
app/Modules/Notice/Routes/web.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Modules\Notice\Http\Controllers\NoticeController;
|
||||||
|
|
||||||
|
Route::middleware(['auth'])->group(function() {
|
||||||
|
|
||||||
|
Route::get('/notice', [NoticeController::class, 'index']);
|
||||||
|
Route::get('/notice/run', [NoticeController::class, 'run']);
|
||||||
|
|
||||||
|
Route::middleware(['hasAccess'])->group(function() {
|
||||||
|
/** Routes that need to be protected - Маршруты которые нужно защитить */
|
||||||
|
});
|
||||||
|
});
|
||||||
16
app/Modules/Notice/Views/index.blade.php
Normal file
16
app/Modules/Notice/Views/index.blade.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<div>
|
||||||
|
<div class="offcanvas offcanvas-end rounded-start offcanvas-animated-xl" tabindex="-1" id="notificationsOffcanvas"
|
||||||
|
aria-labelledby="offcanvasExampleLabel">
|
||||||
|
<div class="offcanvas-header">
|
||||||
|
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Уведомления</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="offcanvas-body">
|
||||||
|
<div class="list-group list-group-flush scrollarea">
|
||||||
|
@livewireStyles
|
||||||
|
<livewire:notices.user-notices />
|
||||||
|
@livewireScripts
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
29
app/Modules/Notice/Views/user-notices-button.blade.php
Normal file
29
app/Modules/Notice/Views/user-notices-button.blade.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<div wire:poll.10000ms>
|
||||||
|
<div class="d-block">
|
||||||
|
<a type="button" class="rounded-circle p-2 lh-1 link-secondary bg-primary-soft-hover text-decoration-none p-1"
|
||||||
|
data-bs-toggle="offcanvas" href="#notificationsOffcanvas">
|
||||||
|
<div class="position-relative">
|
||||||
|
<i class="bi bi-bell fs-4"></i>
|
||||||
|
@if ($unreadedCount > 0)
|
||||||
|
<span class="notices-badge animation-blink"></span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{-- <div class="d-lg-none d-block">
|
||||||
|
<a class="nav-link text-center" data-bs-toggle="offcanvas" href="#notificationsOffcanvas">
|
||||||
|
<div class="position-relative">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" fill="currentColor" class="bi bi-bell" viewBox="0 0 16 16">
|
||||||
|
<path
|
||||||
|
d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2M8 1.918l-.797.161A4 4 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4 4 0 0 0-3.203-3.92zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5 5 0 0 1 13 6c0 .88.32 4.2 1.22 6"/>
|
||||||
|
</svg>
|
||||||
|
<div class="position-absolute start-45 bottom-100">
|
||||||
|
@if ($unreadedCount > 0 || $unreadedMessages > 0)
|
||||||
|
<span class="notices-badge animation-blink"></span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="small d-block text-small-mobile">Уведомления</span>
|
||||||
|
</a>
|
||||||
|
</div> --}}
|
||||||
|
</div>
|
||||||
38
app/Modules/Notice/Views/user-notifications.blade.php
Normal file
38
app/Modules/Notice/Views/user-notifications.blade.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<div wire:poll.10000ms>
|
||||||
|
@if ($notifications->count() == 0)
|
||||||
|
<div class="d-flex justify-content-center align-items-center">
|
||||||
|
<div class="d-grid gap-1 p-3">
|
||||||
|
<i class="bi bi-inbox display-5 text-center"></i>
|
||||||
|
<span class="fs-6 fw-semibold">{{ __('notification.has no notifications') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<ul class="list-group gap-1">
|
||||||
|
@foreach ($notifications as $notification)
|
||||||
|
@if (array_key_exists('text', $notification->data))
|
||||||
|
<li href="#"
|
||||||
|
class="list-group-item list-group-item-action rounded {{ !$notification->read_at ? 'list-group-item-warning' : 'list-group-item-light' }}"
|
||||||
|
aria-current="true" wire:click="read({{ $notification }})">
|
||||||
|
<div class="small">
|
||||||
|
<p class="m-0">
|
||||||
|
{{ $notification->data['text'] }}
|
||||||
|
</p>
|
||||||
|
<p class="m-0 d-flex flex-wrap justify-content-end align-items-center">
|
||||||
|
<span class="badge fw-light text-secondary">{{ $notification->created_at }}</span>
|
||||||
|
@if ($notification->read_at)
|
||||||
|
<span class=" fs-5 text-success">
|
||||||
|
<i class="bi bi-check-all"></i>
|
||||||
|
</span>
|
||||||
|
@else
|
||||||
|
<span class=" fs-5 text-secondary">
|
||||||
|
<i class="bi bi-check"></i>
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
62
app/Notifications/UniqueContact.php
Normal file
62
app/Notifications/UniqueContact.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
|
use Illuminate\Notifications\Notification;
|
||||||
|
|
||||||
|
use App\Models\Deal\Deal;
|
||||||
|
use App\Models\Deal\DealStatus;
|
||||||
|
|
||||||
|
class UniqueContact extends Notification
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
private $deal;
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*/
|
||||||
|
public function __construct(Deal $deal)
|
||||||
|
{
|
||||||
|
if ($deal->status != DealStatus::UNIQUE)
|
||||||
|
{
|
||||||
|
//throw new \Exception('Notification sending: deal is not unique');
|
||||||
|
}
|
||||||
|
$this->deal = $deal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the notification's delivery channels.
|
||||||
|
*
|
||||||
|
* @return array<int, string>
|
||||||
|
*/
|
||||||
|
public function via(object $notifiable): array
|
||||||
|
{
|
||||||
|
return ['database'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mail representation of the notification.
|
||||||
|
*/
|
||||||
|
public function toMail(object $notifiable): MailMessage
|
||||||
|
{
|
||||||
|
return (new MailMessage)
|
||||||
|
->line('The introduction to the notification.')
|
||||||
|
->action('Notification Action', url('/'))
|
||||||
|
->line('Thank you for using our application!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(object $notifiable): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'deal' => $this->deal->id,
|
||||||
|
'text' => __('notifications.' . get_class($this), ['contact' => $this->deal->user->name])
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('notifications', function (Blueprint $table) {
|
||||||
|
$table->uuid('id')->primary();
|
||||||
|
$table->string('type');
|
||||||
|
$table->morphs('notifiable');
|
||||||
|
$table->text('data');
|
||||||
|
$table->timestamp('read_at')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('notifications');
|
||||||
|
}
|
||||||
|
};
|
||||||
18
lang/ru/notifications.php
Normal file
18
lang/ru/notifications.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Password Reset Language Lines
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The following language lines are the default lines which match reasons
|
||||||
|
| that are given by the password broker for a password update attempt
|
||||||
|
| has failed, such as for an invalid token or invalid new password.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'App\Notifications\UniqueContact' => 'Контакт :contact был проверен, уникальность подтверждена',
|
||||||
|
|
||||||
|
];
|
||||||
@ -66,4 +66,45 @@ .active>.page-link {
|
|||||||
.page-item:not(.active)>.page-link:hover {
|
.page-item:not(.active)>.page-link:hover {
|
||||||
color: #e6662a !important;
|
color: #e6662a !important;
|
||||||
border-color: #ccc
|
border-color: #ccc
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*NOTOFICATIONS*/
|
||||||
|
.notices-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
left: 15px;
|
||||||
|
transform: translate(50%, -50%);
|
||||||
|
background-color: #d63939 !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.notices-badge:empty {
|
||||||
|
display: inline-block;
|
||||||
|
width: .5rem;
|
||||||
|
height: .5rem;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: auto;
|
||||||
|
padding: 0;
|
||||||
|
border-radius: 100rem;
|
||||||
|
vertical-align: baseline
|
||||||
|
}
|
||||||
|
|
||||||
|
.animation-blink {
|
||||||
|
-webkit-animation: blink 2s infinite;
|
||||||
|
animation: blink 2s infinite
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blink {
|
||||||
|
0% {
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -27,11 +27,21 @@
|
|||||||
<img src={{ url('/images/logo.png') }} alt="Logo" width="70">
|
<img src={{ url('/images/logo.png') }} alt="Logo" width="70">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col px-0 px-md-4 text-start text-truncate fw-light fs-4 text-secondary text-uppercase"
|
<div class="col px-0 px-md-4 text-start" id="pageTitle">
|
||||||
id="pageTitle">
|
<a class="icon-link icon-link-hover text-truncate fw-lighter fs-4 text-secondary text-uppercase text-decoration-none align-middle"
|
||||||
@isset($title)
|
href="@isset($backUrl) {{ $backUrl }} @endisset"
|
||||||
{{ $title }}
|
style="--bs-icon-link-transform: translate3d(-.125rem, 0, 0);">
|
||||||
@endisset
|
@isset($backUrl)
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
|
||||||
|
class="bi bi-caret-left" viewBox="0 0 16 16">
|
||||||
|
<path
|
||||||
|
d="M10 12.796V3.204L4.519 8zm-.659.753-5.48-4.796a1 1 0 0 1 0-1.506l5.48-4.796A1 1 0 0 1 11 3.204v9.592a1 1 0 0 1-1.659.753" />
|
||||||
|
</svg>
|
||||||
|
@endisset
|
||||||
|
@isset($title)
|
||||||
|
{{ $title }}
|
||||||
|
@endisset
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto col-sm-2">
|
<div class="col-auto col-sm-2">
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
|
<link href="https://fonts.bunny.net/css?family=Nunito" rel="stylesheet">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||||
@vite(['resources/sass/app.scss', 'resources/js/app.js', 'resources/css/app.css', 'resources/css/docs.css'])
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -47,7 +47,10 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Right Side Of Navbar -->
|
<!-- Right Side Of Navbar -->
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav align-items-center ms-auto">
|
||||||
|
<div class="nav-item ">
|
||||||
|
@livewire('notices.user-notices-button')
|
||||||
|
</div>
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button"
|
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button"
|
||||||
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
|
||||||
@ -118,6 +121,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@include('notice::index')
|
||||||
|
@vite(['resources/sass/app.scss', 'resources/js/app.js', 'resources/css/app.css', 'resources/css/docs.css'])
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -59,4 +59,6 @@
|
|||||||
Route::get('profile', function ()
|
Route::get('profile', function ()
|
||||||
{
|
{
|
||||||
return view(view: 'user.profile');
|
return view(view: 'user.profile');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::get('/notices', [App\Http\Controllers\NotificationProbeController::class, 'index']);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user