296 lines
12 KiB
C#
296 lines
12 KiB
C#
|
using Api.Framework;
|
|||
|
using Api.Framework.Model;
|
|||
|
using Api.Framework.SDK;
|
|||
|
using Api.Framework.Tools;
|
|||
|
using Chat.Framework;
|
|||
|
using Chat.Framework.WXSdk.Implement;
|
|||
|
using CsharpHttpHelper;
|
|||
|
using EncourageUser.Entitys;
|
|||
|
using Newtonsoft.Json;
|
|||
|
using System;
|
|||
|
using System.Collections;
|
|||
|
using System.Collections.Concurrent;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Threading;
|
|||
|
using System.Threading.Tasks;
|
|||
|
|
|||
|
namespace EncourageUser
|
|||
|
{
|
|||
|
public class TaskJob : TimerTask
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 运行中的任务
|
|||
|
/// </summary>
|
|||
|
public static Dictionary<long, CancellationTokenSource> JobDic = new Dictionary<long, CancellationTokenSource>();
|
|||
|
|
|||
|
public static bool isrun { get; set; } = false;
|
|||
|
|
|||
|
public override void Run(object state, bool timedOut)
|
|||
|
{
|
|||
|
if (isrun) return;
|
|||
|
try
|
|||
|
{
|
|||
|
isrun = true;
|
|||
|
var session = ApiClient.GetSession();
|
|||
|
var jobs = session.Find<fl_qunfa_task>("select * from fl_qunfa_task where execType = @execType", new { execType = ExecType.未执行完毕 });
|
|||
|
if (jobs == null || jobs.Count == 0)
|
|||
|
return;
|
|||
|
|
|||
|
foreach (var job in jobs)
|
|||
|
{
|
|||
|
//if (JobDic.ContainsKey(job.id))
|
|||
|
// continue;
|
|||
|
|
|||
|
//更新任务发送用户数量
|
|||
|
var qfUser = session.Queryable<fl_qunfa_user>().Where(f => f.taskid == job.id).ToList();
|
|||
|
if (qfUser.Count == 0)
|
|||
|
continue;
|
|||
|
else
|
|||
|
{
|
|||
|
var unSendNum = qfUser.Count(f => !f.issend);
|
|||
|
if (unSendNum == 0)
|
|||
|
{
|
|||
|
job.execType = ExecType.执行完毕;
|
|||
|
if (JobDic.ContainsKey(job.id))
|
|||
|
{
|
|||
|
Abort(job.id);
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
else if (!CheckSendNum(job.id, job.totalSentCount) && IsSendTime(job) && job.endTime.Date == DateTime.Today)//
|
|||
|
job.execType = ExecType.执行完毕;
|
|||
|
else if (job.endTime < DateTime.Now)//已经超出任务结束日期
|
|||
|
job.execType = ExecType.执行失效;
|
|||
|
else
|
|||
|
job.execType = ExecType.未执行完毕;
|
|||
|
|
|||
|
job.unsendnum = unSendNum;
|
|||
|
job.allsendnum = qfUser.Count;
|
|||
|
job.sendnum = qfUser.Count - unSendNum;
|
|||
|
session.Updateable(job).ExecuteCommand();
|
|||
|
if (job.execType != ExecType.未执行完毕)
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (!JobDic.ContainsKey(job.id) && IsSendTime(job) && CheckSendNum(job.id, job.totalSentCount))
|
|||
|
{
|
|||
|
//回复语不存在直接不执行
|
|||
|
var mess = session.Queryable<fl_plugin_encourage_user_messs>().First(f => f.id == job.messid);
|
|||
|
if (mess == null)
|
|||
|
{
|
|||
|
job.execType = ExecType.执行失效;
|
|||
|
session.Updateable(job).ExecuteCommand();
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
ExecTask(job, mess);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception)
|
|||
|
{
|
|||
|
EventClient.OnEvent(this, $"群发工具异常 -> 检测时间:{DateTime.Now.ToString("HH:mm:ss")}");
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
isrun = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static void ExecTask(fl_qunfa_task job, fl_plugin_encourage_user_messs taskMess)
|
|||
|
{
|
|||
|
var task = job;
|
|||
|
try
|
|||
|
{
|
|||
|
var taskCancel = new CancellationTokenSource();
|
|||
|
fl_plugin_encourage_user_messs taskmess = taskMess;
|
|||
|
|
|||
|
Task.Factory.StartNew(() =>
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
var db = ApiClient.GetSession();
|
|||
|
|
|||
|
var mList = db.Queryable<fl_qunfa_user>().Where(f => f.taskid == job.id);
|
|||
|
//未发送的用户集合
|
|||
|
var unSendMList = mList.Where(f => !f.issend).ToList();
|
|||
|
|
|||
|
//机器人分组
|
|||
|
var rGroup = unSendMList.GroupBy(f => f.robotname).Select(f => f.Key).ToList();
|
|||
|
|
|||
|
|
|||
|
foreach (var rname in rGroup)
|
|||
|
{
|
|||
|
if (taskCancel.IsCancellationRequested)
|
|||
|
return;
|
|||
|
|
|||
|
var sendMList = unSendMList.Where(f => f.robotname == rname).ToList();
|
|||
|
if (sendMList.Count != 0)
|
|||
|
{
|
|||
|
JobDic[task.id] = taskCancel;
|
|||
|
EventClient.OnEvent("", $"成功下达群发任务:{task.id}");
|
|||
|
SendTask(task, sendMList, taskmess, taskCancel);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
EventClient.OnEvent("", $"处理群发任务{task.id}异常:{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
}, taskCancel.Token);
|
|||
|
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
EventClient.OnEvent("", $"处理群发任务{task.id}异常2:{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 执行发送任务
|
|||
|
/// </summary>
|
|||
|
/// <param name="users">发送用户集合</param>
|
|||
|
/// <param name="tCancel">取消任务</param>
|
|||
|
private static void SendTask(fl_qunfa_task qunTask, List<fl_qunfa_user> users, fl_plugin_encourage_user_messs taskMess, CancellationTokenSource tCancel)
|
|||
|
{
|
|||
|
fl_qunfa_task quntask = qunTask;
|
|||
|
List<fl_qunfa_user> sendUsers = users;
|
|||
|
CancellationTokenSource taskCancel = tCancel;
|
|||
|
fl_plugin_encourage_user_messs taskmess = taskMess;
|
|||
|
Task.Factory.StartNew(() =>
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
var num = 1;
|
|||
|
foreach (var user in sendUsers)
|
|||
|
{
|
|||
|
//判断是否在可发送时间段 或者 今日发送数量已上限
|
|||
|
if (!IsSendTime(quntask) || !CheckSendNum(quntask.id, quntask.totalSentCount) || taskCancel.IsCancellationRequested)
|
|||
|
return;
|
|||
|
|
|||
|
var flag = false;//判断是否执行发送,执行了休眠才休眠
|
|||
|
if (user.chattype == ChatType.企业微信 || user.chattype == ChatType.微信)
|
|||
|
{
|
|||
|
var robot = ChatClient.WXClient.FirstOrDefault(f => f.Key == user.robotname).Value;
|
|||
|
if (robot == null || robot.Status != Chat.Framework.WXSdk.WxStatus.在线)
|
|||
|
continue;
|
|||
|
flag = true;
|
|||
|
robot.SendMessage(user.username, taskmess.mess);
|
|||
|
UpdUser(user);
|
|||
|
}
|
|||
|
else if (user.chattype == ChatType.QQ)
|
|||
|
{
|
|||
|
var robot = ChatClient.QQClients.FirstOrDefault(f => f.Key == user.robotname).Value;
|
|||
|
if (robot == null || !robot.IsLogin)
|
|||
|
continue;
|
|||
|
flag = true;
|
|||
|
robot.SendMessage(uint.Parse(user.username), taskmess.mess);
|
|||
|
UpdUser(user);
|
|||
|
}
|
|||
|
if (flag)
|
|||
|
{
|
|||
|
EventClient.OnEvent("发送任务", $"执行群发任务:{quntask.id},用户:{user.username},{DateTime.Now}");
|
|||
|
var second = quntask.interval;
|
|||
|
if (quntask.restSendCount <= num)
|
|||
|
{
|
|||
|
second = quntask.restInterval;
|
|||
|
num = 0;
|
|||
|
}
|
|||
|
//发送休眠时间
|
|||
|
Thread.Sleep(second * 1000 + new Random(Guid.NewGuid().GetHashCode()).Next(100, 1000));
|
|||
|
num++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
EventClient.OnEvent("", $"执行群发任务中异常:{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
Abort(quntask.id);
|
|||
|
}
|
|||
|
}, taskCancel.Token);
|
|||
|
}
|
|||
|
|
|||
|
private static void UpdUser(fl_qunfa_user user)
|
|||
|
{
|
|||
|
user.sendtime = HttpExtend.GetTimeStamp(DateTime.Now);
|
|||
|
user.issend = true;
|
|||
|
var db = ApiClient.GetSession();
|
|||
|
db.Updateable(user).ExecuteCommand();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否在发送时间段
|
|||
|
/// </summary>
|
|||
|
/// <param name="job"></param>
|
|||
|
/// <returns></returns>
|
|||
|
private static bool IsSendTime(fl_qunfa_task job)
|
|||
|
{
|
|||
|
var now = DateTime.Now;
|
|||
|
var date = now.ToString("yyyy-MM-dd");
|
|||
|
var startTime1 = DateTime.Parse($"{date} {job.startTime.Hour}:{job.startTime.Minute}:{job.startTime.Second}");
|
|||
|
var endTime1 = DateTime.Parse($"{date} {job.endTime.Hour}:{job.endTime.Minute}:{job.endTime.Second}");
|
|||
|
|
|||
|
var startTime = DateTime.Parse($"{job.startTime}");
|
|||
|
var endTime = DateTime.Parse($"{job.endTime}");
|
|||
|
//if (startTime <= now && now <= endTime && startTime1 <= now && now <= endTime1 && !JobDic.ContainsKey(job.id))
|
|||
|
return (startTime <= now && now <= endTime && startTime1 <= now && now <= endTime1);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 今日发送人数是否达标,还可发送返回true
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
private static bool CheckSendNum(long taskid, int dayCeilingNum)
|
|||
|
{
|
|||
|
var today = HttpExtend.GetTimeStamp(DateTime.Today);
|
|||
|
var db = ApiClient.GetSession();
|
|||
|
var daySendNum = db.Queryable<fl_qunfa_user>().Count(f => f.taskid == taskid && f.issend && today <= f.sendtime);
|
|||
|
return dayCeilingNum > daySendNum;//今天发送的数量比限定的少返回true
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 取消任务
|
|||
|
/// </summary>
|
|||
|
/// <param name="id"></param>
|
|||
|
public static void Abort(long id)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (JobDic == null || JobDic.Count == 0) return;
|
|||
|
if (!JobDic.ContainsKey(id)) return;
|
|||
|
JobDic[id].Cancel();
|
|||
|
JobDic.Remove(id);
|
|||
|
EventClient.OnEvent("取消任务", $"取消群发任务:{id}");
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
EventClient.OnEvent("取消任务", $"取消群发任务异常:{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public static void AbortAll()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (JobDic == null || JobDic.Count == 0) return;
|
|||
|
foreach (var taskCancel in JobDic.Values)
|
|||
|
{
|
|||
|
taskCancel.Cancel();
|
|||
|
}
|
|||
|
JobDic.Clear();
|
|||
|
EventClient.OnEvent("取消任务", $"取消所有群发任务");
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
EventClient.OnEvent("取消任务", $"取消所有群发任务异常:{ex.Message} - {ex.StackTrace}");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|