mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-11 10:33:54 +00:00
262 lines
9.9 KiB
PHP
262 lines
9.9 KiB
PHP
<?php
|
||
|
||
namespace App\Models;
|
||
|
||
use App\Module\Base;
|
||
use Carbon\Carbon;
|
||
use Hedeqiang\UMeng\Android;
|
||
use Hedeqiang\UMeng\IOS;
|
||
|
||
/**
|
||
* App\Models\UmengAlias
|
||
*
|
||
* @property int $id
|
||
* @property int|null $userid 会员ID
|
||
* @property string|null $alias 别名
|
||
* @property string|null $platform 平台类型
|
||
* @property string|null $device 设备类型
|
||
* @property string|null $device_hash 设备哈希值,用于关联UserDevice表
|
||
* @property string|null $version 应用版本号
|
||
* @property string|null $ua userAgent
|
||
* @property int|null $is_notified 通知权限
|
||
* @property \Illuminate\Support\Carbon|null $created_at
|
||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelAppend()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel cancelHidden()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel change($array)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel getKeyValue()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias newModelQuery()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias newQuery()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias query()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel remove()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|AbstractModel saveOrIgnore()
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereAlias($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereCreatedAt($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereDevice($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereDeviceHash($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereId($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereIsNotified($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias wherePlatform($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereUa($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereUpdatedAt($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereUserid($value)
|
||
* @method static \Illuminate\Database\Eloquent\Builder|UmengAlias whereVersion($value)
|
||
* @mixin \Eloquent
|
||
*/
|
||
class UmengAlias extends AbstractModel
|
||
{
|
||
protected $table = 'umeng_alias';
|
||
|
||
private static $waitSend = [];
|
||
|
||
|
||
/**
|
||
* 推送消息
|
||
* @param $push
|
||
* @return void
|
||
*/
|
||
private static function sendTask($push = null)
|
||
{
|
||
if ($push) {
|
||
self::$waitSend[] = $push;
|
||
}
|
||
|
||
if (!self::$waitSend) {
|
||
return;
|
||
}
|
||
|
||
$first = array_shift(self::$waitSend);
|
||
if (empty($first)) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
switch ($first['platform']) {
|
||
case 'ios':
|
||
$instance = new IOS($first['config']);
|
||
break;
|
||
case 'android':
|
||
$instance = new Android($first['config']);
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
$instance->send($first['data']);
|
||
} catch (\Exception $e) {
|
||
$first['retry'] = intval($first['retry'] ?? 0) + 1;
|
||
if ($first['retry'] > 3) {
|
||
info("[PushMsg] fail: " . $e->getMessage());
|
||
} else {
|
||
info("[PushMsg] retry ({$first['retry']}): " . $e->getMessage());
|
||
self::$waitSend[] = $first;
|
||
}
|
||
} finally {
|
||
self::sendTask();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 推送内容处理
|
||
* @param $string
|
||
* @return string
|
||
*/
|
||
private static function specialCharacters($string)
|
||
{
|
||
return str_replace(["\r\n", "\r", "\n"], '', $string);
|
||
}
|
||
|
||
/**
|
||
* 获取推送配置
|
||
* @return array|false
|
||
*/
|
||
public static function getPushConfig()
|
||
{
|
||
$setting = Base::setting('appPushSetting');
|
||
if ($setting['push'] !== 'open') {
|
||
return false;
|
||
}
|
||
$config = [];
|
||
if ($setting['ios_key']) {
|
||
$config['iOS'] = [
|
||
'appKey' => $setting['ios_key'],
|
||
'appMasterSecret' => $setting['ios_secret'],
|
||
'production_mode' => true,
|
||
];
|
||
}
|
||
if ($setting['android_key']) {
|
||
$config['Android'] = [
|
||
'appKey' => $setting['android_key'],
|
||
'appMasterSecret' => $setting['android_secret'],
|
||
'production_mode' => true,
|
||
];
|
||
}
|
||
return $config;
|
||
}
|
||
|
||
/**
|
||
* 推送消息
|
||
* @param string $alias
|
||
* @param string $platform
|
||
* @param array $array [title, subtitle, body, description, extra, seconds, badge]
|
||
* @return void
|
||
*/
|
||
private static function pushMsgToAlias($alias, $platform, $array)
|
||
{
|
||
$config = self::getPushConfig();
|
||
if ($config === false) {
|
||
return;
|
||
}
|
||
//
|
||
$title = self::specialCharacters($array['title'] ?: ''); // 标题
|
||
$subtitle = self::specialCharacters($array['subtitle'] ?: ''); // 副标题(iOS)
|
||
$body = self::specialCharacters($array['body'] ?: ''); // 通知内容
|
||
$description = $array['description'] ?: 'no description'; // 描述
|
||
$extra = is_array($array['extra']) ? $array['extra'] : []; // 额外参数
|
||
$seconds = intval($array['seconds']) ?: 86400; // 有效时间(单位:秒)
|
||
$badge = intval($array['badge']) ?: 0; // 角标数(iOS)
|
||
//
|
||
switch ($platform) {
|
||
case 'ios':
|
||
if (!isset($config['iOS'])) {
|
||
return;
|
||
}
|
||
self::sendTask([
|
||
'platform' => $platform,
|
||
'config' => $config,
|
||
'data' => [
|
||
'description' => $description,
|
||
'payload' => array_merge([
|
||
'aps' => [
|
||
'alert' => [
|
||
'title' => $title,
|
||
'subtitle' => $subtitle,
|
||
'body' => $body,
|
||
],
|
||
'sound' => 'default',
|
||
'badge' => $badge,
|
||
],
|
||
], $extra),
|
||
'type' => 'customizedcast',
|
||
'alias_type' => 'userid',
|
||
'alias' => $alias,
|
||
'policy' => [
|
||
'expire_time' => Carbon::now()->addSeconds($seconds)->toDateTimeString(),
|
||
],
|
||
]
|
||
]);
|
||
break;
|
||
|
||
case 'android':
|
||
if (!isset($config['Android'])) {
|
||
return;
|
||
}
|
||
self::sendTask([
|
||
'platform' => $platform,
|
||
'config' => $config,
|
||
'data' => [
|
||
'description' => $description,
|
||
'payload' => array_merge([
|
||
'display_type' => 'notification',
|
||
'body' => [
|
||
'ticker' => $title,
|
||
'text' => $body,
|
||
'title' => $title,
|
||
'after_open' => 'go_app',
|
||
'play_sound' => true,
|
||
],
|
||
], $extra),
|
||
'type' => 'customizedcast',
|
||
'alias_type' => 'userid',
|
||
'alias' => $alias,
|
||
'mipush' => true,
|
||
'mi_activity' => 'app.eeui.umeng.activity.MfrMessageActivity',
|
||
'policy' => [
|
||
'expire_time' => Carbon::now()->addSeconds($seconds)->toDateTimeString(),
|
||
],
|
||
'channel_properties' => [
|
||
'oppo_channel_id' => 'dootask',
|
||
'vivo_category' => 'IM',
|
||
'huawei_channel_importance' => 'NORMAL',
|
||
'huawei_channel_category' => 'IM',
|
||
'channel_fcm' => 0,
|
||
],
|
||
]
|
||
]);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 推送给指定会员
|
||
* @param array|int $userid
|
||
* @param array $array
|
||
* @return void
|
||
*/
|
||
public static function pushMsgToUserid($userid, $array)
|
||
{
|
||
$builder = self::select(['id', 'platform', 'alias', 'userid'])->where('updated_at', '>', Carbon::now()->subMonth());
|
||
if (is_array($userid)) {
|
||
$builder->whereIn('userid', $userid);
|
||
} elseif (Base::isNumber($userid)) {
|
||
$builder->whereUserid($userid);
|
||
}
|
||
$builder
|
||
->orderByDesc('updated_at')
|
||
->chunkById(100, function ($datas) use ($array) {
|
||
$uids = $datas->groupBy('userid');
|
||
foreach ($uids as $uid => $rows) {
|
||
$array['badge'] = WebSocketDialogMsgRead::whereUserid($uid)->whereSilence(0)->whereReadAt(null)->count();
|
||
$lists = $rows->take(5)->groupBy('platform'); // 每个会员最多推送5个别名
|
||
foreach ($lists as $platform => $list) {
|
||
$alias = $list->pluck('alias')->implode(',');
|
||
try {
|
||
self::pushMsgToAlias($alias, $platform, $array);
|
||
} catch (\Exception $e) {
|
||
info("[PushMsg] fail: " . $e->getMessage());
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
}
|