同步主分支

This commit is contained in:
hudingwen 2023-02-12 22:00:04 +08:00
parent 552d94beb8
commit d09de26d6e
25 changed files with 1345 additions and 1 deletions

View File

@ -982,6 +982,76 @@
Tibug 博文
</summary>
</member>
<member name="T:Blog.Core.Model.Models.TrojanCusServers">
<summary>
users自定义服务器
</summary>
</member>
<member name="T:Blog.Core.Model.Models.TrojanDetails">
<summary>
用户流量每月汇总表
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.id">
<summary>
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.userId">
<summary>
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.calDate">
<summary>
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.download">
<summary>
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.upload">
<summary>
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.CreateId">
<summary>
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.CreateBy">
<summary>
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanDetails.CreateTime">
<summary>
</summary>
</member>
<member name="T:Blog.Core.Model.Models.TrojanServers">
<summary>
Trojan服务器
</summary>
</member>
<member name="T:Blog.Core.Model.Models.TrojanUrlServers">
<summary>
users自定义URL服务器
</summary>
</member>
<member name="T:Blog.Core.Model.Models.TrojanUsers">
<summary>
Trojan用户
</summary>
</member>
<member name="P:Blog.Core.Model.Models.TrojanUsers.useList">
<summary>
历史流量记录
</summary>
</member>
<member name="T:Blog.Core.Model.Models.UserRole">
<summary>
用户跟角色关联表
@ -2407,6 +2477,73 @@
</summary>
</member>
<member name="T:Blog.Core.Model.ViewModels.TrojanLimitFlowDto">
<summary>
限制流量dto
作者:胡丁文
时间:2020-4-27 16:57:07
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanLimitFlowDto.users">
<summary>
用户
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanLimitFlowDto.quota">
<summary>
流量(-1为无限,单位为最小单位byte)
</summary>
</member>
<member name="T:Blog.Core.Model.ViewModels.TrojanServerSpliceDto">
<summary>
Trojan服务器拼接服务器和订阅地址
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanServerSpliceDto.normalApi">
<summary>
普通订阅连接
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanServerSpliceDto.clashApi">
<summary>
clash订阅连接
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanServerSpliceDto.clashApiBackup">
<summary>
备用clash订阅连接
</summary>
</member>
<member name="T:Blog.Core.Model.ViewModels.TrojanUseDetailDto">
<summary>
Trojan用户流量统计分组
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanUseDetailDto.userId">
<summary>
用户ID
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanUseDetailDto.moth">
<summary>
月度
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanUseDetailDto.up">
<summary>
上传流量
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanUseDetailDto.down">
<summary>
下载流量
</summary>
</member>
<member name="P:Blog.Core.Model.ViewModels.TrojanUseDetailDto.total">
<summary>
下载流量
</summary>
</member>
<member name="T:Blog.Core.Model.ViewModels.WeChatApiDto">
<summary>
微信接口消息DTO

View File

@ -650,6 +650,159 @@
<param name="id"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.GetUser(Blog.Core.Model.PaginationModel,System.String,System.Boolean)">
<summary>
获取Trojan用户
</summary>
<param name="pagination"></param>
<param name="name"></param>
<param name="isuse"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.GetAllTrojanUser">
<summary>
获取Trojan用户-下拉列表用
</summary>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.AddUser(Blog.Core.Model.Models.TrojanUsers)">
<summary>
添加Trojan用户
</summary>
<param name="user"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.UpdateUser(Blog.Core.Model.Models.TrojanUsers)">
<summary>
更新Trojan用户
</summary>
<param name="user"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.DelUser(System.Int32[])">
<summary>
删除用户
</summary>
<param name="users"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.ResetFlow(System.Int32[])">
<summary>
重置流量
</summary>
<param name="users"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.LimitFlow(Blog.Core.Model.ViewModels.TrojanLimitFlowDto)">
<summary>
限制流量
</summary>
<param name="limit"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.ResetPass(System.Int32[])">
<summary>
重置链接密码
</summary>
<param name="users"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.GetServers">
<summary>
获取Trojan服务器
</summary>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.GetSpliceServers(System.String)">
<summary>
获取拼接后的Trojan服务器
</summary>
<param name="id">passwordshow</param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.DelServers(System.Int32[])">
<summary>
删除Trojan服务器
</summary>
<param name="servers"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.UpdateServers(Blog.Core.Model.Models.TrojanServers)">
<summary>
更新Trojan服务器
</summary>
<param name="server"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.AddServers(Blog.Core.Model.Models.TrojanServers)">
<summary>
添加Trojan服务器
</summary>
<param name="server"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.GetCusServers">
<summary>
获取Cus服务器
</summary>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.DelCusServers(System.Int32[])">
<summary>
删除Cus服务器
</summary>
<param name="servers"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.UpdateCusServers(Blog.Core.Model.Models.TrojanCusServers)">
<summary>
更新Cus服务器
</summary>
<param name="server"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.AddCusServers(Blog.Core.Model.Models.TrojanCusServers)">
<summary>
添加Cus服务器
</summary>
<param name="server"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.GetUrlServers">
<summary>
获取Url服务器
</summary>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.DelUrlServers(System.Int32[])">
<summary>
删除Url服务器
</summary>
<param name="servers"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.UpdateUrlServers(Blog.Core.Model.Models.TrojanUrlServers)">
<summary>
更新Url服务器
</summary>
<param name="server"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.AddUrlServers(Blog.Core.Model.Models.TrojanUrlServers)">
<summary>
添加Url服务器
</summary>
<param name="server"></param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.TrojanController.RSS(System.String,System.Boolean)">
<summary>
获取订阅数据
</summary>
<param name="id">链接密码</param>
<param name="isUseBase64">是否使用base64加密</param>
<returns></returns>
</member>
<member name="T:Blog.Core.Controllers.UserController">
<summary>
用户管理
@ -1062,6 +1215,13 @@
<param name="msg">卡片消息对象</param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.WeChatController.PushCardMsgGet(Blog.Core.Model.ViewModels.WeChatCardMsgDataDto)">
<summary>
推送卡片消息接口
</summary>
<param name="msg">卡片消息对象</param>
<returns></returns>
</member>
<member name="M:Blog.Core.Controllers.WeChatController.PushTxtMsg(Blog.Core.Model.ViewModels.WeChatPushTestDto)">
<summary>
推送文本消息

View File

@ -0,0 +1,451 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Blog.Core.Common;
using Blog.Core.Common.Extensions;
using Blog.Core.Common.Helper;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.IServices;
using Blog.Core.IServices.BASE;
using Blog.Core.Model;
using Blog.Core.Model.Models;
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Blog.Core.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
[Authorize(Permissions.Name)]
public class TrojanController : ControllerBase
{
private ITrojanUsersServices _trojanUsersServices;
public IBaseServices<TrojanServers> _baseServicesServers;
public IBaseServices<TrojanDetails> _baseServicesDetails;
public IBaseServices<TrojanCusServers> _baseServicesCusServers;
public IBaseServices<TrojanUrlServers> _baseServicesUrlServers;
private IUser _user;
public TrojanController(ITrojanUsersServices trojanUsersServices,IUser user
, IBaseServices<TrojanServers> baseServicesServers
, IBaseServices<TrojanDetails> baseServicesDetails
, IBaseServices<TrojanCusServers> baseServicesCusServers
, IBaseServices<TrojanUrlServers> baseServicesUrlServers)
{
_baseServicesDetails = baseServicesDetails;
_baseServicesServers = baseServicesServers;
_trojanUsersServices = trojanUsersServices;
_baseServicesCusServers = baseServicesCusServers;
_baseServicesUrlServers = baseServicesUrlServers;
_user = user;
}
/// <summary>
/// 获取Trojan用户
/// </summary>
/// <param name="pagination"></param>
/// <param name="name"></param>
/// <param name="isuse"></param>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<PageModel<TrojanUsers>>> GetUser([FromQuery]PaginationModel pagination, [FromQuery] string name, [FromQuery] bool isuse)
{
var whereFind = LinqHelper.True<TrojanUsers>();
if (!string.IsNullOrEmpty(name))
whereFind = whereFind.And(t=>t.username.Contains(name));
if (isuse)
whereFind = whereFind.And(t => t.upload > 0 || t.download > 0);
var data = await _trojanUsersServices.QueryPage(whereFind, pagination.PageIndex, pagination.PageSize);
if (data.data.Count > 0)
{
var ids = data.data.Select(t => t.id).ToList();
var where = LinqHelper.True<TrojanDetails>();
where = where.And(t => ids.Contains(t.userId));//.And(t => t.calDate < DateTime.Now).And(t => t.calDate > DateTime.Now.AddMonths(-12));
var userDetails = await _baseServicesDetails.Query(where);
foreach (var trojanUser in data.data)
{
var ls = from t in userDetails
where t.userId == trojanUser.id
group t by new { moth = t.calDate.ToString("yyyy-MM"), id = t.userId } into g
orderby g.Key.moth descending
select new TrojanUseDetailDto { userId = g.Key.id, moth = g.Key.moth, up = g.Sum(t => Convert.ToDecimal(t.upload)), down = g.Sum(t => Convert.ToDecimal(t.download)) };
var lsData = ls.ToList();
trojanUser.useList = lsData;
}
}
return MessageModel<PageModel<TrojanUsers>>.Success("获取成功", data);
}
/// <summary>
/// 获取Trojan用户-下拉列表用
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<DataTable>> GetAllTrojanUser()
{
var data = await _trojanUsersServices.QueryTable("select id,username from users");
return MessageModel<DataTable>.Success("获取成功", data);
}
/// <summary>
/// 添加Trojan用户
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
[HttpPost]
public async Task<MessageModel<object>> AddUser([FromBody]TrojanUsers user)
{
var find = await _trojanUsersServices.Query(t => t.username == user.username);
if(find!=null && find.Count>0) return MessageModel<object>.Fail("用户名已存在");
var pass = StringHelper.GetGUID();
var passEcrypt = ShaHelper.Sha224(pass);
//user.quota = 0;
user.upload = 0;
user.download = 0;
user.password = passEcrypt;
user.passwordshow = pass;
var data = await _trojanUsersServices.Add(user);
return MessageModel<object>.Success("添加成功", data);
}
/// <summary>
/// 更新Trojan用户
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<object>> UpdateUser([FromBody]TrojanUsers user)
{
var find = await _trojanUsersServices.QueryById(user.id);
if (find == null) return MessageModel<object>.Fail("用户名不存在");
find.username = user.username;
var data = await _trojanUsersServices.Update(find, new List<string> { "username" });
return MessageModel<object>.Success("更新成功", data);
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="users"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<string>> DelUser([FromBody]int[] users)
{
var data = await _trojanUsersServices.Query(t => users.Contains(t.id));
var list = data.Select(t => t.id.ToString()).ToArray();
await _trojanUsersServices.DeleteByIds(list);
return MessageModel<string>.Success("删除成功");
}
/// <summary>
/// 重置流量
/// </summary>
/// <param name="users"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<string>> ResetFlow([FromBody]int[] users)
{
var data = await _trojanUsersServices.Query(t => users.Contains(t.id));
foreach (var item in data)
{
item.upload = 0;
item.download = 0;
await _trojanUsersServices.Update(item, new List<string> { "upload", "download" });
}
return MessageModel<string>.Success("重置流量成功");
}
/// <summary>
/// 限制流量
/// </summary>
/// <param name="limit"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<string>> LimitFlow([FromBody] TrojanLimitFlowDto limit)
{
var data = await _trojanUsersServices.Query(t => limit.users.Contains(t.id));
foreach (var item in data)
{
item.quota = limit.quota;
await _trojanUsersServices.Update(item, new List<string> { "quota" });
}
return MessageModel<string>.Success("限制流量成功");
}
/// <summary>
/// 重置链接密码
/// </summary>
/// <param name="users"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<string>> ResetPass([FromBody]int[] users)
{
var data = await _trojanUsersServices.Query(t => users.Contains(t.id));
var pass = StringHelper.GetGUID();
var passEcrypt = ShaHelper.Sha224(pass);
foreach (var item in data)
{
item.password = passEcrypt;
item.passwordshow = pass;
await _trojanUsersServices.Update(item, new List<string> { "password" , "passwordshow" });
}
return MessageModel<string>.Success("重置链接密码成功");
}
/// <summary>
/// 获取Trojan服务器
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<List<TrojanServers>>> GetServers()
{
var data = await _baseServicesServers.Query();
data = data.OrderBy(t => t.servername).ToList();
return MessageModel<List<TrojanServers>>.Success("获取成功", data);
}
/// <summary>
/// 获取拼接后的Trojan服务器
/// </summary>
/// <param name="id">passwordshow</param>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<TrojanServerSpliceDto>> GetSpliceServers(string id)
{
var data = await _baseServicesServers.Query();
data = data.OrderBy(t => t.servername).ToList();
var res = new TrojanServerSpliceDto();
res.normalApi = AppSettings.app(new string[] { "trojan", "normalApi" }).ObjToString();
res.clashApi = AppSettings.app(new string[] { "trojan", "clashApi" }).ObjToString();
res.clashApiBackup = AppSettings.app(new string[] { "trojan", "clashApiBackup" }).ObjToString();
foreach (var item in data)
{
var serverSplice = GetSplice(item, id);
res.list.Add(new TrojanServerDto { name = item.servername, value = serverSplice });
}
return MessageModel<TrojanServerSpliceDto>.Success("获取成功", res); ;
}
/// <summary>
/// 删除Trojan服务器
/// </summary>
/// <param name="servers"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<List<TrojanServers>>> DelServers([FromBody]int[] servers)
{
var data = await _baseServicesServers.DeleteByIds(servers.Select(t=>t.ToString()).ToArray());
if (data)
return MessageModel<List<TrojanServers>>.Success("删除成功");
else
return MessageModel<List<TrojanServers>>.Fail("删除失败");
}
/// <summary>
/// 更新Trojan服务器
/// </summary>
/// <param name="server"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<List<TrojanServers>>> UpdateServers(TrojanServers server)
{
var data = await _baseServicesServers.Update(server);
return MessageModel<List<TrojanServers>>.Success("更新成功");
}
/// <summary>
/// 添加Trojan服务器
/// </summary>
/// <param name="server"></param>
/// <returns></returns>
[HttpPost]
public async Task<MessageModel<List<TrojanServers>>> AddServers(TrojanServers server)
{
var data = await _baseServicesServers.Add(server);
return MessageModel<List<TrojanServers>>.Success("添加成功");
}
/// <summary>
/// 获取Cus服务器
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<List<TrojanCusServers>>> GetCusServers()
{
var data = await _baseServicesCusServers.Query();
data = data.OrderBy(t => t.servername).ToList();
return MessageModel<List<TrojanCusServers>>.Success("获取成功", data);
}
/// <summary>
/// 删除Cus服务器
/// </summary>
/// <param name="servers"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<List<TrojanCusServers>>> DelCusServers([FromBody] int[] servers)
{
var data = await _baseServicesCusServers.DeleteByIds(servers.Select(t => t.ToString()).ToArray());
if (data)
return MessageModel<List<TrojanCusServers>>.Success("删除成功");
else
return MessageModel<List<TrojanCusServers>>.Fail("删除失败");
}
/// <summary>
/// 更新Cus服务器
/// </summary>
/// <param name="server"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<List<TrojanCusServers>>> UpdateCusServers(TrojanCusServers server)
{
var data = await _baseServicesCusServers.Update(server);
return MessageModel<List<TrojanCusServers>>.Success("更新成功");
}
/// <summary>
/// 添加Cus服务器
/// </summary>
/// <param name="server"></param>
/// <returns></returns>
[HttpPost]
public async Task<MessageModel<List<TrojanCusServers>>> AddCusServers(TrojanCusServers server)
{
var data = await _baseServicesCusServers.Add(server);
return MessageModel<List<TrojanCusServers>>.Success("添加成功");
}
/// <summary>
/// 获取Url服务器
/// </summary>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<List<TrojanUrlServers>>> GetUrlServers()
{
var data = await _baseServicesUrlServers.Query();
data = data.OrderBy(t => t.servername).ToList();
return MessageModel<List<TrojanUrlServers>>.Success("获取成功", data);
}
/// <summary>
/// 删除Url服务器
/// </summary>
/// <param name="servers"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<List<TrojanUrlServers>>> DelUrlServers([FromBody] int[] servers)
{
var data = await _baseServicesUrlServers.DeleteByIds(servers.Select(t => t.ToString()).ToArray());
if (data)
return MessageModel<List<TrojanUrlServers>>.Success("删除成功");
else
return MessageModel<List<TrojanUrlServers>>.Fail("删除失败");
}
/// <summary>
/// 更新Url服务器
/// </summary>
/// <param name="server"></param>
/// <returns></returns>
[HttpPut]
public async Task<MessageModel<List<TrojanUrlServers>>> UpdateUrlServers(TrojanUrlServers server)
{
var data = await _baseServicesUrlServers.Update(server);
return MessageModel<List<TrojanUrlServers>>.Success("更新成功");
}
/// <summary>
/// 添加Url服务器
/// </summary>
/// <param name="server"></param>
/// <returns></returns>
[HttpPost]
public async Task<MessageModel<List<TrojanUrlServers>>> AddUrlServers(TrojanUrlServers server)
{
var data = await _baseServicesUrlServers.Add(server);
return MessageModel<List<TrojanUrlServers>>.Success("添加成功");
}
private string GetSplice(TrojanServers item,string passwordshow)
{
if ("0".Equals(item.servertype))
return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?allowinsecure=0&tfo=0&peer={(string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress)}#{item.servername}";
else if ("1".Equals(item.servertype))
return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?wspath={item.serverpath}&ws=1&peer={(string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress)}#{item.servername}";
else
return $"servertype:({item.servertype})错误";
}
private List<string> GetSplice(List<TrojanServers> items, string passwordshow)
{
List<string> ls = new List<string>();
foreach (var item in items)
{
ls.Add(GetSplice(item, passwordshow));
}
return ls;
}
/// <summary>
/// 获取订阅数据
/// </summary>
/// <param name="id">链接密码</param>
/// <param name="isUseBase64">是否使用base64加密</param>
/// <returns></returns>
[HttpGet]
[AllowAnonymous]
public async Task<string> RSS(string id,bool isUseBase64=true)
{
StringBuilder sb = new StringBuilder();
try
{
var user = (await _trojanUsersServices.Query(t => t.passwordshow == id)).FirstOrDefault();
if (user == null) throw new Exception("用户不存在");
var data = await _baseServicesServers.Query(t => (t.userid == user.id || t.userid <= 0) && t.serverenable);
if (data != null)
{
data = data.OrderBy(t => t.servername).ToList();
foreach (var item in data)
{
sb.AppendLine(GetSplice(item, user.passwordshow));
}
}
var cusData = await _baseServicesCusServers.Query(t=> (t.userid == user.id || t.userid <=0) && t.serverenable);
if (cusData != null)
{
cusData = cusData.OrderBy(t => t.servername).ToList();
foreach (var item in cusData)
{
sb.AppendLine(item.serveraddress);
}
}
var urlData = await _baseServicesUrlServers.Query(t => (t.userid == user.id || t.userid <= 0) && t.serverenable);
if (urlData != null)
{
urlData = urlData.OrderBy(t => t.servername).ToList();
foreach (var item in urlData)
{
try
{
var urlStrObj = await HttpHelper.GetAsync(item.serveraddress);
var lines = "";
try
{
lines = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(urlStrObj));
}
catch (Exception)
{
lines = urlStrObj;
}
finally
{
sb.AppendLine(lines);
}
}
catch (Exception ex)
{
sb.AppendLine($"trojan://xxxxxx@xxxxxx.xx:443?allowinsecure=0&tfo=0#{ex.Message}");
}
}
}
}
catch (Exception ex)
{
sb.AppendLine($"trojan://xxxxxx@xxxxxx.xx:443?allowinsecure=0&tfo=0#{ex.Message}");
}
if (isUseBase64)
{
return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(sb.ToString()));
}
else{
return sb.ToString();
}
}
}
}

View File

@ -146,6 +146,18 @@ namespace Blog.Core.Controllers
return await _weChatConfigServices.PushCardMsg(msg, pushUserIP);
}
/// <summary>
/// 推送卡片消息接口
/// </summary>
/// <param name="msg">卡片消息对象</param>
/// <returns></returns>
[HttpGet]
[AllowAnonymous]
public async Task<MessageModel<WeChatResponseUserInfo>> PushCardMsgGet([FromQuery] WeChatCardMsgDataDto msg)
{
string pushUserIP = $"{Request.HttpContext.Connection.RemoteIpAddress}:{Request.HttpContext.Connection.RemotePort}";
return await _weChatConfigServices.PushCardMsg(msg, pushUserIP);
}
/// <summary>
/// 推送文本消息
/// </summary>
/// <param name="msg">消息对象</param>

View File

@ -3,7 +3,7 @@
#FROM swr.cn-south-1.myhuaweicloud.com/mcr/aspnet:5.0-alpine
#FROM mcr.microsoft.com/dotnet/core/aspnet:5.0-buster-slim
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim
FROM mcr.microsoft.com/dotnet/aspnet:6.0-bullseye-slim
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone

View File

@ -26,6 +26,7 @@ namespace Blog.Core.IServices.BASE
Task<bool> DeleteByIds(object[] ids);
Task<bool> Update(TEntity model);
Task<bool> Update(List<TEntity> model);
Task<bool> Update(TEntity entity, string where);
Task<bool> Update(object operateAnonymousObjects);

View File

@ -0,0 +1,14 @@
using Blog.Core.IServices.BASE;
using Blog.Core.Model.Models;
namespace Blog.Core.IServices
{
/// <summary>
/// TrojanUsersServices
/// </summary>
public interface ITrojanUsersServices : IBaseServices<TrojanUsers>
{
}
}

View File

@ -0,0 +1,26 @@

using System;
using System.Linq;
using System.Text;
using SqlSugar;
namespace Blog.Core.Model.Models
{
///<summary>
///users自定义服务器
///</summary>
[SugarTable("users_cus", "users自定义服务器")]
[TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库名字是appsettings.json 的 ConnId')
public partial class TrojanCusServers
{
[SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
public int id { set; get; }
public int userid { get; set; }
public string servername { set; get; }
public string serveraddress { set; get; }
[SugarColumn(IsNullable = true)]
public string serverremark { get; set; }
public bool serverenable { get; set; }
}
}

View File

@ -0,0 +1,63 @@
//模板自动生成(请勿修改)
//作者:胡丁文
using System;
using System.Linq;
using System.Text;
using SqlSugar;
namespace Blog.Core.Model.Models
{
///<summary>
///用户流量每月汇总表
///</summary>
[SugarTable("users_detail", "用户流量每月汇总表")]
[TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库名字是appsettings.json 的 ConnId')
public partial class TrojanDetails
{
/// <summary>
///
/// </summary>
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int id { get; set; }
/// <summary>
///
/// </summary>
public int userId { get; set; }
/// <summary>
///
/// </summary>
public DateTime calDate { get; set; }
/// <summary>
///
/// </summary>
public ulong download { get; set; }
/// <summary>
///
/// </summary>
public ulong upload { get; set; }
/// <summary>
///
/// </summary>
[SugarColumn(IsNullable = true)]
public int? CreateId { get; set; }
/// <summary>
///
/// </summary>
[SugarColumn(IsNullable = true)]
public string CreateBy { get; set; }
/// <summary>
///
/// </summary>
[SugarColumn(IsNullable = true)]
public DateTime? CreateTime { get; set; }
}
}

View File

@ -0,0 +1,31 @@

using System;
using System.Linq;
using System.Text;
using SqlSugar;
namespace Blog.Core.Model.Models
{
///<summary>
///Trojan服务器
///</summary>
[SugarTable("servers", "Trojan服务器")]
[TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库名字是appsettings.json 的 ConnId')
public partial class TrojanServers
{
[SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
public int id { set; get; }
public int userid { get; set; }
public string servername { set; get; }
public string serveraddress { set; get; }
public int serverport { get; set; }
[SugarColumn(IsNullable = true)]
public string serverremark { get; set; }
public bool serverenable { get; set; }
public string serverpeer { get; set; }
[SugarColumn(IsNullable = true)]
public string serverpath { get; set; }
public string servertype { get; set; }
}
}

View File

@ -0,0 +1,26 @@

using System;
using System.Linq;
using System.Text;
using SqlSugar;
namespace Blog.Core.Model.Models
{
///<summary>
///users自定义URL服务器
///</summary>
[SugarTable("users_url", "users自定义URL服务器")]
[TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库名字是appsettings.json 的 ConnId')
public partial class TrojanUrlServers
{
[SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
public int id { set; get; }
public int userid { get; set; }
public string servername { set; get; }
public string serveraddress { set; get; }
[SugarColumn(IsNullable = true)]
public string serverremark { get; set; }
public bool serverenable { get; set; }
}
}

View File

@ -0,0 +1,39 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Blog.Core.Model.ViewModels;
using SqlSugar;
namespace Blog.Core.Model.Models
{
///<summary>
///Trojan用户
///</summary>
[SugarTable("users", "Trojan用户表")]
[TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库名字是appsettings.json 的 ConnId')
public partial class TrojanUsers
{
[SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
public int id { set; get; }
public string username { set; get; }
public string password { set; get; }
public Int64 quota { set; get; }
public UInt64 download { set; get; }
public UInt64 upload { set; get; }
public string passwordshow { set; get; }
[SugarColumn(IsNullable = true)]
public int CreateId { get; set; }
[SugarColumn(IsNullable = true)]
public string CreateBy { get; set; }
[SugarColumn(IsNullable = true)]
public DateTime? CreateTime { get; set; }
/// <summary>
/// 历史流量记录
/// </summary>
[SugarColumn(IsIgnore = true)]
public List<TrojanUseDetailDto> useList { get; set; }
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Blog.Core.Model.ViewModels
{
/// <summary>
/// 限制流量dto
/// 作者:胡丁文
/// 时间:2020-4-27 16:57:07
/// </summary>
public class TrojanLimitFlowDto
{
/// <summary>
/// 用户
/// </summary>
public int[] users { get; set; }
/// <summary>
/// 流量(-1为无限,单位为最小单位byte)
/// </summary>
public Int64 quota { get; set; }
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Model.ViewModels
{
public class TrojanServerDto
{
public string name { get; set; }
public string value { get; set; }
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Model.ViewModels
{
/// <summary>
/// Trojan服务器拼接服务器和订阅地址
/// </summary>
public class TrojanServerSpliceDto
{
/// <summary>
/// 普通订阅连接
/// </summary>
public string normalApi { get; set; }
/// <summary>
/// clash订阅连接
/// </summary>
public string clashApi { get; set; }
/// <summary>
/// 备用clash订阅连接
/// </summary>
public string clashApiBackup { get; set; }
public List<TrojanServerDto> list { get; set; } = new List<TrojanServerDto>();
}
}

View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Model.ViewModels
{
/// <summary>
/// Trojan用户流量统计分组
/// </summary>
public class TrojanUseDetailDto
{
/// <summary>
/// 用户ID
/// </summary>
public int userId { get; set; }
/// <summary>
/// 月度
/// </summary>
public string moth { get; set; }
/// <summary>
/// 上传流量
/// </summary>
public decimal up { get; set; }
/// <summary>
/// 下载流量
/// </summary>
public decimal down { get; set; }
/// <summary>
/// 下载流量
/// </summary>
public decimal total { get { return up + down; } }
}
}

View File

@ -144,6 +144,19 @@ namespace Blog.Core.Repository.Base
//这种方式会以主键为条件
return await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
}
/// <summary>
/// 更新实体数据
/// </summary>
/// <param name="entity">博文实体类</param>
/// <returns></returns>
public async Task<bool> Update(List<TEntity> entity)
{
////这种方式会以主键为条件
//var i = await Task.Run(() => _db.Updateable(entity).ExecuteCommand());
//return i > 0;
//这种方式会以主键为条件
return await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
}
public async Task<bool> Update(TEntity entity, string where)
{

View File

@ -69,6 +69,12 @@ namespace Blog.Core.IRepository.Base
/// <param name="model"></param>
/// <returns></returns>
Task<bool> Update(TEntity model);
/// <summary>
/// 更新model
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
Task<bool> Update(List<TEntity> model);
/// <summary>
/// 根据model更新带where条件

View File

@ -76,6 +76,15 @@ namespace Blog.Core.Services.BASE
{
return await BaseDal.Update(entity);
}
/// <summary>
/// 更新实体数据
/// </summary>
/// <param name="entity">博文实体类</param>
/// <returns></returns>
public async Task<bool> Update(List<TEntity> entity)
{
return await BaseDal.Update(entity);
}
public async Task<bool> Update(TEntity entity, string where)
{
return await BaseDal.Update(entity, where);

View File

@ -0,0 +1,18 @@
using Blog.Core.Common;
using Blog.Core.IRepository.Base;
using Blog.Core.IServices;
using Blog.Core.Model.Models;
using Blog.Core.Services.BASE;
using System.Linq;
using System.Threading.Tasks;
namespace Blog.Core.Services
{
/// <summary>
/// TrojanUsersServices
/// </summary>
public class TrojanUsersServices : BaseServices<TrojanUsers>, ITrojanUsersServices
{
}
}

View File

@ -11,6 +11,7 @@
<ItemGroup>
<ProjectReference Include="..\Blog.Core.Common\Blog.Core.Common.csproj" />
<ProjectReference Include="..\Blog.Core.IServices\Blog.Core.IServices.csproj" />
<ProjectReference Include="..\Blog.Core.Repository\Blog.Core.Repository.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,60 @@
using Blog.Core.Common;
using Blog.Core.IServices;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Blog.Core.Tasks
{
public class Job1TimedService : IHostedService, IDisposable
{
private Timer _timer;
private readonly IBlogArticleServices _blogArticleServices;
// 这里可以注入
public Job1TimedService(IBlogArticleServices blogArticleServices)
{
_blogArticleServices = blogArticleServices;
}
public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 1 is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(60 * 60));//一个小时
return Task.CompletedTask;
}
private void DoWork(object state)
{
try
{
var model = _blogArticleServices.GetBlogDetails(1).Result;
Console.WriteLine($"Job 1 启动成功获取id=1的博客title为:{model?.btitle}");
}
catch (Exception ex)
{
Console.WriteLine($"Error:{ex.Message}");
}
ConsoleHelper.WriteSuccessLine($"Job 1 {DateTime.Now}");
}
public Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 1 is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}

View File

@ -0,0 +1,47 @@
using Blog.Core.Common;
using Microsoft.Extensions.Hosting;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Blog.Core.Tasks
{
public class Job2TimedService : IHostedService, IDisposable
{
private Timer _timer;
// 这里可以注入
public Job2TimedService()
{
}
public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 2 is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(60 * 60 * 2));//两个小时
return Task.CompletedTask;
}
private void DoWork(object state)
{
ConsoleHelper.WriteWarningLine($"Job 2 {DateTime.Now}");
}
public Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Job 2 is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
}

View File

@ -0,0 +1,79 @@
using Blog.Core.Repository.UnitOfWorks;
using Blog.Core.IServices;
using Blog.Core.IServices.BASE;
using Blog.Core.Model.Models;
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
/// <summary>
/// 这里要注意下,命名空间和程序集是一样的,不然反射不到(任务类要去JobSetup添加注入)
/// </summary>
namespace Blog.Core.Tasks
{
public class Job_Trojan_Quartz : JobBase, IJob
{
private readonly IUnitOfWorkManage _unitOfWorkManage;
public IBaseServices<TrojanDetails>_DetailServices;
private readonly ITrojanUsersServices _TrojanUsers;
private readonly ILogger<Job_Trojan_Quartz> _logger;
public Job_Trojan_Quartz(IUnitOfWorkManage unitOfWorkManage, IBaseServices<TrojanDetails> iusers_DetailServices, ITrojanUsersServices trojanUsers, ITasksQzServices tasksQzServices, ILogger<Job_Trojan_Quartz> logger)
{
_tasksQzServices = tasksQzServices;
_unitOfWorkManage = unitOfWorkManage;
_DetailServices = iusers_DetailServices;
_TrojanUsers = trojanUsers;
_logger = logger;
}
public async Task Execute(IJobExecutionContext context)
{
//var param = context.MergedJobDataMap;
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
}
public async Task Run(IJobExecutionContext context, int jobid)
{
if (jobid > 0)
{
try
{
//获取每月用户的数据
_unitOfWorkManage.BeginTran();
var now = DateTime.Now.AddMonths(-1);
var list = await _TrojanUsers.Query();
List<TrojanDetails> ls = new List<TrojanDetails>();
foreach (var us in list)
{
TrojanDetails u = new TrojanDetails();
u.calDate = now;
u.userId = us.id;
u.download = us.download;
u.upload = us.upload;
//清零
us.download = 0;
us.upload = 0;
ls.Add(u);
}
await _TrojanUsers.Update(list);
await _DetailServices.Add(ls);
_unitOfWorkManage.CommitTran();
}
catch (Exception)
{
_unitOfWorkManage.RollbackTran();
throw;
}
}
}
}
}

View File

@ -0,0 +1,51 @@
using Blog.Core.Common.Helper;
using Blog.Core.Repository.UnitOfWorks;
using Blog.Core.IServices;
using Blog.Core.IServices.BASE;
using Blog.Core.Model.Models;
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
/// <summary>
/// 这里要注意下,命名空间和程序集是一样的,不然反射不到(任务类要去JobSetup添加注入)
/// </summary>
namespace Blog.Core.Tasks
{
public class Job_URL_Quartz : JobBase, IJob
{
private readonly ILogger<Job_URL_Quartz> _logger;
public Job_URL_Quartz(ITasksQzServices tasksQzServices, ILogger<Job_URL_Quartz> logger)
{
_tasksQzServices = tasksQzServices;
_logger = logger;
}
public async Task Execute(IJobExecutionContext context)
{
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
}
public async Task Run(IJobExecutionContext context, int jobid)
{
if (jobid > 0)
{
JobDataMap data = context.JobDetail.JobDataMap;
string pars = data.GetString("JobParam");
if (!string.IsNullOrWhiteSpace(pars))
{
var log = await HttpHelper.GetAsync(pars);
_logger.LogInformation(log);
}
}
}
}
}