代码提交
This commit is contained in:
@@ -1537,4 +1537,500 @@ class Adapter implements WeChatServiceInterface
|
||||
} while ($affected > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自动问候功能
|
||||
* 根据不同的触发类型检查并发送问候消息
|
||||
*/
|
||||
public function handleAutoGreetings()
|
||||
{
|
||||
try {
|
||||
// 获取所有启用的问候规则
|
||||
$rules = Db::name('kf_auto_greetings')
|
||||
->where(['status' => 1, 'isDel' => 0])
|
||||
->order('level asc, id asc')
|
||||
->select();
|
||||
|
||||
if (empty($rules)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
$trigger = $rule['trigger'];
|
||||
$condition = json_decode($rule['condition'], true);
|
||||
|
||||
switch ($trigger) {
|
||||
case 1: // 新好友
|
||||
$this->handleNewFriendGreeting($rule);
|
||||
break;
|
||||
case 2: // 首次发消息
|
||||
$this->handleFirstMessageGreeting($rule);
|
||||
break;
|
||||
case 3: // 时间触发
|
||||
$this->handleTimeTriggerGreeting($rule, $condition);
|
||||
break;
|
||||
case 4: // 关键词触发
|
||||
$this->handleKeywordTriggerGreeting($rule, $condition);
|
||||
break;
|
||||
case 5: // 生日触发
|
||||
$this->handleBirthdayTriggerGreeting($rule, $condition);
|
||||
break;
|
||||
case 6: // 自定义
|
||||
$this->handleCustomTriggerGreeting($rule, $condition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('自动问候处理失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理新好友触发
|
||||
*/
|
||||
private function handleNewFriendGreeting($rule)
|
||||
{
|
||||
// 获取最近24小时内添加的好友(避免重复处理)
|
||||
$last24h = time() - 24 * 3600;
|
||||
|
||||
// 查询该用户/公司最近24小时内新添加的好友
|
||||
// 通过 s2_wechat_account -> s2_company_account 关联获取 companyId
|
||||
$friends = Db::table('s2_wechat_friend')
|
||||
->alias('wf')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wf.wechatAccountId = wa.id')
|
||||
->join(['s2_company_account' => 'ca'], 'wa.deviceAccountId = ca.id')
|
||||
->where([
|
||||
['wf.isPassed', '=', 1],
|
||||
['wf.isDeleted', '=', 0],
|
||||
['wf.passTime', '>=', $last24h],
|
||||
['ca.departmentId', '=', $rule['companyId']],
|
||||
])
|
||||
->field('wf.id, wf.wechatAccountId')
|
||||
->select();
|
||||
|
||||
foreach ($friends as $friend) {
|
||||
// 检查是否已经发送过问候
|
||||
$exists = Db::name('kf_auto_greetings_record')
|
||||
->where([
|
||||
'autoId' => $rule['id'],
|
||||
'friendIdOrGroupId' => $friend['id'],
|
||||
'wechatAccountId' => $friend['wechatAccountId'],
|
||||
])
|
||||
->find();
|
||||
|
||||
if (!$exists) {
|
||||
$this->sendGreetingMessage($rule, $friend['wechatAccountId'], $friend['id'], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理首次发消息触发
|
||||
*/
|
||||
private function handleFirstMessageGreeting($rule)
|
||||
{
|
||||
// 获取最近1小时内收到的消息
|
||||
$last1h = time() - 3600;
|
||||
|
||||
// 查询消息表,找出首次发消息的好友
|
||||
// 通过 s2_wechat_account -> s2_company_account 关联获取 companyId
|
||||
$messages = Db::table('s2_wechat_message')
|
||||
->alias('wm')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wm.wechatAccountId = wa.id')
|
||||
->join(['s2_company_account' => 'ca'], 'wa.deviceAccountId = ca.id')
|
||||
->where([
|
||||
['wm.isSend', '=', 0], // 接收的消息
|
||||
['wm.wechatChatroomId', '=', 0], // 个人消息
|
||||
['wm.createTime', '>=', $last1h],
|
||||
['ca.departmentId', '=', $rule['companyId']],
|
||||
])
|
||||
->group('wm.wechatFriendId, wm.wechatAccountId')
|
||||
->field('wm.wechatFriendId, wm.wechatAccountId, MIN(wm.createTime) as firstMsgTime')
|
||||
->select();
|
||||
|
||||
foreach ($messages as $msg) {
|
||||
// 检查该好友是否之前发送过消息
|
||||
$previousMsg = Db::table('s2_wechat_message')
|
||||
->where([
|
||||
'wechatFriendId' => $msg['wechatFriendId'],
|
||||
'wechatAccountId' => $msg['wechatAccountId'],
|
||||
'isSend' => 0,
|
||||
])
|
||||
->where('createTime', '<', $msg['firstMsgTime'])
|
||||
->find();
|
||||
|
||||
// 如果是首次发消息,且没有发送过问候
|
||||
if (!$previousMsg) {
|
||||
$exists = Db::name('kf_auto_greetings_record')
|
||||
->where([
|
||||
'autoId' => $rule['id'],
|
||||
'friendIdOrGroupId' => $msg['wechatFriendId'],
|
||||
'wechatAccountId' => $msg['wechatAccountId'],
|
||||
])
|
||||
->find();
|
||||
|
||||
if (!$exists) {
|
||||
$this->sendGreetingMessage($rule, $msg['wechatAccountId'], $msg['wechatFriendId'], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理时间触发
|
||||
*/
|
||||
private function handleTimeTriggerGreeting($rule, $condition)
|
||||
{
|
||||
if (empty($condition) || !isset($condition['type'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$currentTime = date('H:i', $now);
|
||||
$currentDate = date('m-d', $now);
|
||||
$currentDateTime = date('m-d H:i', $now);
|
||||
$currentWeekday = date('w', $now); // 0=周日, 1=周一, ..., 6=周六
|
||||
|
||||
$shouldTrigger = false;
|
||||
|
||||
switch ($condition['type']) {
|
||||
case 'daily_time': // 每天固定时间
|
||||
if ($currentTime === $condition['value']) {
|
||||
$shouldTrigger = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'yearly_datetime': // 每年固定日期时间
|
||||
if ($currentDateTime === $condition['value']) {
|
||||
$shouldTrigger = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'fixed_range': // 固定时间段
|
||||
if (is_array($condition['value']) && count($condition['value']) === 2) {
|
||||
$startTime = strtotime('2000-01-01 ' . $condition['value'][0]);
|
||||
$endTime = strtotime('2000-01-01 ' . $condition['value'][1]);
|
||||
$currentTimeStamp = strtotime('2000-01-01 ' . $currentTime);
|
||||
|
||||
if ($currentTimeStamp >= $startTime && $currentTimeStamp <= $endTime) {
|
||||
$shouldTrigger = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'workday': // 工作日
|
||||
// 周一到周五(1-5)
|
||||
if ($currentWeekday >= 1 && $currentWeekday <= 5 && $currentTime === $condition['value']) {
|
||||
$shouldTrigger = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ($shouldTrigger) {
|
||||
// 获取该用户/公司的所有好友
|
||||
// 通过 s2_wechat_account -> s2_company_account 关联获取 companyId
|
||||
$friends = Db::table('s2_wechat_friend')
|
||||
->alias('wf')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wf.wechatAccountId = wa.id')
|
||||
->join(['s2_company_account' => 'ca'], 'wa.deviceAccountId = ca.id')
|
||||
->where([
|
||||
['wf.isPassed', '=', 1],
|
||||
['wf.isDeleted', '=', 0],
|
||||
['ca.departmentId', '=', $rule['companyId']],
|
||||
])
|
||||
->field('wf.id, wf.wechatAccountId')
|
||||
->select();
|
||||
|
||||
foreach ($friends as $friend) {
|
||||
// 检查今天是否已经发送过
|
||||
$todayStart = strtotime(date('Y-m-d 00:00:00'));
|
||||
$exists = Db::name('kf_auto_greetings_record')
|
||||
->where([
|
||||
'autoId' => $rule['id'],
|
||||
'friendIdOrGroupId' => $friend['id'],
|
||||
'wechatAccountId' => $friend['wechatAccountId'],
|
||||
])
|
||||
->where('createTime', '>=', $todayStart)
|
||||
->find();
|
||||
|
||||
if (!$exists) {
|
||||
$this->sendGreetingMessage($rule, $friend['wechatAccountId'], $friend['id'], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理关键词触发
|
||||
*/
|
||||
private function handleKeywordTriggerGreeting($rule, $condition)
|
||||
{
|
||||
if (empty($condition) || empty($condition['keywords'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$keywords = $condition['keywords'];
|
||||
$matchType = $condition['match_type'] ?? 'fuzzy';
|
||||
|
||||
// 获取最近1小时内收到的消息
|
||||
$last1h = time() - 3600;
|
||||
|
||||
// 通过 s2_wechat_account -> s2_company_account 关联获取 companyId
|
||||
$messages = Db::table('s2_wechat_message')
|
||||
->alias('wm')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wm.wechatAccountId = wa.id')
|
||||
->join(['s2_company_account' => 'ca'], 'wa.deviceAccountId = ca.id')
|
||||
->where([
|
||||
['wm.isSend', '=', 0], // 接收的消息
|
||||
['wm.wechatChatroomId', '=', 0], // 个人消息
|
||||
['wm.msgType', '=', 1], // 文本消息
|
||||
['wm.createTime', '>=', $last1h],
|
||||
['ca.departmentId', '=', $rule['companyId']],
|
||||
])
|
||||
->field('wm.*')
|
||||
->select();
|
||||
|
||||
foreach ($messages as $msg) {
|
||||
$content = $msg['content'] ?? '';
|
||||
|
||||
// 检查关键词匹配
|
||||
$matched = false;
|
||||
foreach ($keywords as $keyword) {
|
||||
if ($matchType === 'exact') {
|
||||
// 精准匹配
|
||||
if ($content === $keyword) {
|
||||
$matched = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 模糊匹配
|
||||
if (strpos($content, $keyword) !== false) {
|
||||
$matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($matched) {
|
||||
// 检查是否已经发送过问候(同一好友同一规则,1小时内只发送一次)
|
||||
$last1h = time() - 3600;
|
||||
$exists = Db::name('kf_auto_greetings_record')
|
||||
->where([
|
||||
'autoId' => $rule['id'],
|
||||
'friendIdOrGroupId' => $msg['wechatFriendId'],
|
||||
'wechatAccountId' => $msg['wechatAccountId'],
|
||||
])
|
||||
->where('createTime', '>=', $last1h)
|
||||
->find();
|
||||
|
||||
if (!$exists) {
|
||||
$this->sendGreetingMessage($rule, $msg['wechatAccountId'], $msg['wechatFriendId'], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理生日触发
|
||||
*/
|
||||
private function handleBirthdayTriggerGreeting($rule, $condition)
|
||||
{
|
||||
if (empty($condition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析condition格式
|
||||
// 支持格式:
|
||||
// 1. {'month': 10, 'day': 10} - 当天任何时间都可以触发
|
||||
// 2. {'month': 10, 'day': 10, 'time': '09:00'} - 当天指定时间触发
|
||||
// 3. {'month': 10, 'day': 10, 'time_range': ['09:00', '10:00']} - 当天时间范围内触发
|
||||
// 兼容旧格式:['10-10'] 或 '10-10'(仅支持 MM-DD 格式,不包含年份)
|
||||
|
||||
$birthdayMonth = null;
|
||||
$birthdayDay = null;
|
||||
$birthdayTime = null;
|
||||
$timeRange = null;
|
||||
|
||||
if (is_array($condition)) {
|
||||
// 新格式:对象格式 {'month': 10, 'day': 10}
|
||||
if (isset($condition['month']) && isset($condition['day'])) {
|
||||
$birthdayMonth = (int)$condition['month'];
|
||||
$birthdayDay = (int)$condition['day'];
|
||||
$birthdayTime = $condition['time'] ?? null;
|
||||
$timeRange = $condition['time_range'] ?? null;
|
||||
}
|
||||
// 兼容旧格式:['10-10'] 或 ['10-10 09:00'](仅支持 MM-DD 格式)
|
||||
elseif (isset($condition[0])) {
|
||||
$dateStr = $condition[0];
|
||||
// 只接受月日格式:'10-10' 或 '10-10 09:00'
|
||||
if (preg_match('/^(\d{1,2})-(\d{1,2})(?:\s+(\d{2}:\d{2}))?$/', $dateStr, $matches)) {
|
||||
$birthdayMonth = (int)$matches[1];
|
||||
$birthdayDay = (int)$matches[2];
|
||||
if (isset($matches[3])) {
|
||||
$birthdayTime = $matches[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (is_string($condition)) {
|
||||
// 字符串格式:只接受 '10-10' 或 '10-10 09:00'(MM-DD 格式,不包含年份)
|
||||
if (preg_match('/^(\d{1,2})-(\d{1,2})(?:\s+(\d{2}:\d{2}))?$/', $condition, $matches)) {
|
||||
$birthdayMonth = (int)$matches[1];
|
||||
$birthdayDay = (int)$matches[2];
|
||||
if (isset($matches[3])) {
|
||||
$birthdayTime = $matches[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($birthdayMonth === null || $birthdayDay === null || $birthdayMonth < 1 || $birthdayMonth > 12 || $birthdayDay < 1 || $birthdayDay > 31) {
|
||||
return;
|
||||
}
|
||||
|
||||
$todayMonth = (int)date('m');
|
||||
$todayDay = (int)date('d');
|
||||
|
||||
// 检查今天是否是生日(只匹配月日,不匹配年份)
|
||||
if ($todayMonth !== $birthdayMonth || $todayDay !== $birthdayDay) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果配置了时间,检查当前时间是否匹配
|
||||
$now = time();
|
||||
$currentTime = date('H:i', $now);
|
||||
|
||||
if ($birthdayTime !== null) {
|
||||
// 指定了具体时间,检查是否在指定时间(允许1分钟误差,避免定时任务执行时间不精确)
|
||||
$birthdayTimestamp = strtotime('2000-01-01 ' . $birthdayTime);
|
||||
$currentTimestamp = strtotime('2000-01-01 ' . $currentTime);
|
||||
$diff = abs($currentTimestamp - $birthdayTimestamp);
|
||||
|
||||
// 如果时间差超过2分钟,不触发(允许1分钟误差)
|
||||
if ($diff > 120) {
|
||||
return;
|
||||
}
|
||||
} elseif ($timeRange !== null && is_array($timeRange) && count($timeRange) === 2) {
|
||||
// 指定了时间范围,检查当前时间是否在范围内
|
||||
$startTime = strtotime('2000-01-01 ' . $timeRange[0]);
|
||||
$endTime = strtotime('2000-01-01 ' . $timeRange[1]);
|
||||
$currentTimestamp = strtotime('2000-01-01 ' . $currentTime);
|
||||
|
||||
if ($currentTimestamp < $startTime || $currentTimestamp > $endTime) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 如果没有配置时间或时间范围,则当天任何时间都可以触发
|
||||
|
||||
// 获取该用户/公司的所有好友
|
||||
// 通过 s2_wechat_account -> s2_company_account 关联获取 companyId
|
||||
$friends = Db::table('s2_wechat_friend')
|
||||
->alias('wf')
|
||||
->join(['s2_wechat_account' => 'wa'], 'wf.wechatAccountId = wa.id')
|
||||
->join(['s2_company_account' => 'ca'], 'wa.deviceAccountId = ca.id')
|
||||
->where([
|
||||
['wf.isPassed', '=', 1],
|
||||
['wf.isDeleted', '=', 0],
|
||||
['ca.departmentId', '=', $rule['companyId']],
|
||||
])
|
||||
->field('wf.id, wf.wechatAccountId')
|
||||
->select();
|
||||
|
||||
foreach ($friends as $friend) {
|
||||
// 检查今天是否已经发送过
|
||||
$todayStart = strtotime(date('Y-m-d 00:00:00'));
|
||||
$exists = Db::name('kf_auto_greetings_record')
|
||||
->where([
|
||||
'autoId' => $rule['id'],
|
||||
'friendIdOrGroupId' => $friend['id'],
|
||||
'wechatAccountId' => $friend['wechatAccountId'],
|
||||
])
|
||||
->where('createTime', '>=', $todayStart)
|
||||
->find();
|
||||
|
||||
if (!$exists) {
|
||||
$this->sendGreetingMessage($rule, $friend['wechatAccountId'], $friend['id'], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自定义触发
|
||||
*/
|
||||
private function handleCustomTriggerGreeting($rule, $condition)
|
||||
{
|
||||
// 自定义类型需要根据具体业务需求实现
|
||||
// 这里提供一个基础框架,可根据实际需求扩展
|
||||
// 暂时不实现,留待后续扩展
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送问候消息
|
||||
* @param array $rule 问候规则
|
||||
* @param int $wechatAccountId 微信账号ID
|
||||
* @param int $friendId 好友ID
|
||||
* @param int $groupId 群ID(0表示个人消息)
|
||||
*/
|
||||
private function sendGreetingMessage($rule, $wechatAccountId, $friendId, $groupId = 0)
|
||||
{
|
||||
try {
|
||||
$content = $rule['content'];
|
||||
|
||||
// 创建记录
|
||||
$recordId = Db::name('kf_auto_greetings_record')->insertGetId([
|
||||
'autoId' => $rule['id'],
|
||||
'userId' => $rule['userId'],
|
||||
'companyId' => $rule['companyId'],
|
||||
'wechatAccountId' => $wechatAccountId,
|
||||
'friendIdOrGroupId' => $friendId,
|
||||
'isSend' => 0,
|
||||
'sendTime' => 0,
|
||||
'receiveTime' => 0,
|
||||
'createTime' => time(),
|
||||
]);
|
||||
|
||||
// 发送消息(文本消息)
|
||||
$username = Env::get('api.username', '');
|
||||
$password = Env::get('api.password', '');
|
||||
$toAccountId = '';
|
||||
if (!empty($username) || !empty($password)) {
|
||||
$toAccountId = Db::name('users')->where('account', $username)->value('s2_accountId');
|
||||
}
|
||||
|
||||
$wsController = new WebSocketController(['userName' => $username, 'password' => $password, 'accountId' => $toAccountId]);
|
||||
|
||||
$sendTime = time();
|
||||
$result = $wsController->sendPersonal([
|
||||
'wechatFriendId' => $friendId,
|
||||
'wechatAccountId' => $wechatAccountId,
|
||||
'msgType' => 1, // 文本消息
|
||||
'content' => $content,
|
||||
]);
|
||||
|
||||
$isSend = 0;
|
||||
$receiveTime = 0;
|
||||
|
||||
// 解析返回结果
|
||||
$resultData = json_decode($result, true);
|
||||
if (!empty($resultData) && $resultData['code'] == 200) {
|
||||
$isSend = 1;
|
||||
$receiveTime = time(); // 简化处理,实际应该从返回结果中获取
|
||||
}
|
||||
|
||||
// 更新记录
|
||||
Db::name('kf_auto_greetings_record')
|
||||
->where('id', $recordId)
|
||||
->update([
|
||||
'isSend' => $isSend,
|
||||
'sendTime' => $sendTime,
|
||||
'receiveTime' => $receiveTime,
|
||||
]);
|
||||
|
||||
// 更新规则使用次数
|
||||
Db::name('kf_auto_greetings')
|
||||
->where('id', $rule['id'])
|
||||
->setInc('usageCount');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('发送问候消息失败:' . $e->getMessage() . ',规则ID:' . $rule['id']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user