Files
chatroom/app/Services/WechatBot/WechatNotificationService.php

264 lines
7.3 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:微信消息发送核心业务逻辑服务
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Services\WechatBot;
use App\Jobs\SendWechatBotMessage;
use App\Models\SysParam;
use App\Models\User;
use Illuminate\Support\Facades\Redis;
class WechatNotificationService
{
protected array $config = [];
protected bool $globalEnabled = false;
public function __construct()
{
$param = SysParam::where('alias', 'wechat_bot_config')->first();
if ($param && ! empty($param->body)) {
$this->config = json_decode($param->body, true) ?? [];
}
}
/**
* 检查当前时间是否在全局配置的允许推送免打扰时间窗口内
*/
protected function isWithinNotificationWindow(): bool
{
$startTime = $this->config['global_notify']['start_time'] ?? '';
$endTime = $this->config['global_notify']['end_time'] ?? '';
// 如果没有配置起止时间,默认全天放行
if (! $startTime || ! $endTime) {
return true;
}
$nowTime = date('H:i');
if ($startTime < $endTime) {
return $nowTime >= $startTime && $nowTime <= $endTime;
} else {
// 跨天逻辑,如 22:00 -> 08:00
return $nowTime >= $startTime || $nowTime <= $endTime;
}
}
/**
* 管理员上线群通知
*/
public function notifyAdminOnline(User $user): void
{
if (! $this->isWithinNotificationWindow()) {
return;
}
if (empty($this->config['group_notify']['toggle_admin_online'])) {
return;
}
$groupWxid = $this->config['group_notify']['target_wxid'] ?? '';
if (! $groupWxid) {
return;
}
// 只播报有职务的管理员
$activePosition = $user->activePosition;
if (! $activePosition) {
return;
}
$departmentName = $activePosition->position->department->name ?? '';
$positionName = $activePosition->position->name ?? '';
$title = trim("{$departmentName}{$positionName}") ?: '技术员';
$message = "👑 【管理员上线】\n"
."{$title} [{$user->username}] 刚刚登录了系统。";
SendWechatBotMessage::dispatch($groupWxid, $message);
}
/**
* 百家乐开奖群通知
*/
public function notifyBaccaratResult(string $historyText): void
{
if (! $this->isWithinNotificationWindow()) {
return;
}
if (empty($this->config['group_notify']['toggle_baccarat_result'])) {
return;
}
$groupWxid = $this->config['group_notify']['target_wxid'] ?? '';
if (! $groupWxid) {
return;
}
SendWechatBotMessage::dispatch($groupWxid, $historyText);
}
/**
* 彩票开奖群通知
*/
public function notifyLotteryResult(string $historyText): void
{
if (! $this->isWithinNotificationWindow()) {
return;
}
if (empty($this->config['group_notify']['toggle_lottery_result'])) {
return;
}
$groupWxid = $this->config['group_notify']['target_wxid'] ?? '';
if (! $groupWxid) {
return;
}
SendWechatBotMessage::dispatch($groupWxid, $historyText);
}
/**
* 发送自定义群内公告
*
* @throws \Exception
*/
public function sendCustomGroupAnnouncement(string $message): void
{
$groupWxid = $this->config['group_notify']['target_wxid'] ?? '';
if (! $groupWxid) {
throw new \Exception('未配置目标微信群 Wxid无法发送公告消息');
}
SendWechatBotMessage::dispatch($groupWxid, $message);
}
/**
* 好友上线私聊通知(带冷却)
*/
public function notifyFriendsOnline(User $user): void
{
if (! $this->isWithinNotificationWindow()) {
return;
}
if (empty($this->config['personal_notify']['toggle_friend_online'])) {
return;
}
$cacheKey = "wechat_notify_cd:friend_online:{$user->id}";
if (Redis::exists($cacheKey)) {
return;
}
// 假定有好友关系模型 Friends (视具体业务而定,目前先预留或者查询好友)
$friends = $this->getUserFriends($user->id);
foreach ($friends as $friend) {
if ($friend->wxid) {
$message = "👋 【好友上线】\n您的好友 [{$user->username}] 刚刚上线了!";
SendWechatBotMessage::dispatch($friend->wxid, $message);
}
}
// 冷却 30 分钟
Redis::setex($cacheKey, 1800, 1);
}
/**
* 夫妻上线私聊通知(带冷却)
*/
public function notifySpouseOnline(User $user): void
{
if (! $this->isWithinNotificationWindow()) {
return;
}
if (empty($this->config['personal_notify']['toggle_spouse_online'])) {
return;
}
$cacheKey = "wechat_notify_cd:spouse_online:{$user->id}";
if (Redis::exists($cacheKey)) {
return;
}
// 获取伴侣
$spouse = $this->getUserSpouse($user);
if ($spouse && $spouse->wxid) {
$message = "❤️ 【伴侣上线】\n您的伴侣 [{$user->username}] 刚刚上线了!";
SendWechatBotMessage::dispatch($spouse->wxid, $message);
// 冷却 30 分钟
Redis::setex($cacheKey, 1800, 1);
}
}
/**
* 等级变动私聊通知
*/
public function notifyLevelChange(User $user, int $oldLevel, int $newLevel): void
{
if (! $this->isWithinNotificationWindow()) {
return;
}
if (empty($this->config['personal_notify']['toggle_level_change'])) {
return;
}
if (! $user->wxid || $newLevel <= $oldLevel) {
return;
}
$message = "✨ 【等级提升】\n"
."恭喜您!您的聊天室等级已从 LV{$oldLevel} 提升至 LV{$newLevel}";
SendWechatBotMessage::dispatch($user->wxid, $message);
}
// ---------------------------------------------------------
// Helper Methods (Mocking the real data retrieval methods)
// ---------------------------------------------------------
protected function getUserFriends(int $userId)
{
$user = User::find($userId);
if (! $user) {
return collect([]);
}
// 谁把当前用户加为了好友(当前用户是 towho谁就应该收到上线通知
$watcherNames = \App\Models\FriendRequest::where('towho', $user->username)
->pluck('who');
if ($watcherNames->isEmpty()) {
return collect([]);
}
return User::whereIn('username', $watcherNames)
->whereNotNull('wxid')
->where('wxid', '!=', '')
->get();
}
protected function getUserSpouse(User $user)
{
// 如果有配偶字段
$mateName = $user->peiou ?? null;
if ($mateName && $mateName !== '无' && $mateName !== '') {
return User::where('username', $mateName)->whereNotNull('wxid')->first();
}
return null;
}
}