using CommonUtil;
|
using EasyCaching.Core;
|
using Link.DbModel;
|
using Link.DTOModel;
|
using Link.IService;
|
using Microsoft.AspNetCore.Mvc;
|
using System;
|
using System.Collections.Generic;
|
using System.ComponentModel.DataAnnotations;
|
using System.Linq;
|
using System.Net;
|
using System.Text;
|
using System.Text.RegularExpressions;
|
|
namespace Link.Api.Controllers
|
{
|
/// <summary>
|
///
|
/// </summary>
|
public class IndexController : BaseController
|
{
|
/// <summary>
|
/// 短链接口
|
/// </summary>
|
private readonly ILkLinkService _lkLinkService;
|
|
/// <summary>
|
/// 短链访问记录接口
|
/// </summary>
|
private readonly ILkAccessHistoryService _lkAccessHistoryService;
|
|
/// <summary>
|
/// 短链访问统计接口
|
/// </summary>
|
private readonly ILkAccessStatisticService _lkAccessStatisticService;
|
|
/// <summary>
|
/// 缓存容器
|
/// </summary>
|
private readonly IEasyCachingProvider _provider;
|
|
/// <summary>
|
/// 构造函数
|
/// </summary>
|
/// <param name="provider"></param>
|
/// <param name="lkLkinkService"></param>
|
/// <param name="lkAccessHistoryService"></param>
|
/// <param name="lkAccessStatisticService"></param>
|
public IndexController(IEasyCachingProvider provider, ILkLinkService lkLkinkService, ILkAccessHistoryService lkAccessHistoryService, ILkAccessStatisticService lkAccessStatisticService)
|
{
|
_provider = provider;
|
_lkLinkService = lkLkinkService;
|
_lkAccessHistoryService = lkAccessHistoryService;
|
_lkAccessStatisticService = lkAccessStatisticService;
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="id"></param>
|
/// <returns></returns>
|
[HttpGet("/{id}")]
|
[ProducesResponseType((int)HttpStatusCode.Redirect)]
|
[ProducesResponseType((int)HttpStatusCode.NotFound)]
|
public IActionResult Index([Required]string id)
|
{
|
string mobEncry = "";//加密手机号
|
if (id.Length > 7)
|
{
|
try
|
{
|
mobEncry = id.Substring(id.Length - 7, 7);
|
mobEncry = MobileDecry(mobEncry);
|
}
|
catch
|
{
|
|
}
|
id = id.Substring(0, id.Length - 7);
|
}
|
if (id == "favicon.ico")
|
{
|
return NotFound();
|
}
|
LkLink link = null;
|
var linkCache = _provider.Get<LkLink>($"LINK_{id}");
|
if (!linkCache.HasValue)
|
{
|
//var where = ExpressionUtil.Create<LkLink>().And(j => j.Key == id)
|
// .And(j => j.ExpireTime >= DateTime.Now)
|
// .ToExpression();
|
var where = ExpressionUtil.Create<LkLink>().And(j => j.Key == id)
|
.ToExpression();
|
link = _lkLinkService.GetFirst(where);
|
}
|
else
|
{
|
link = linkCache.Value;
|
}
|
if (link.IsNull())
|
{
|
return NotFound();
|
}
|
|
//if (link.IsNull() || link.ExpireTime < DateTime.Now)
|
//{
|
// return NotFound();
|
//}
|
|
var result = _lkAccessStatisticService.UseTran(() =>
|
{
|
string ip = GetClientIp();
|
|
DateTime minTime = DateTime.Now.Date;
|
DateTime maxTime = minTime.AddHours(23).AddMinutes(59).AddSeconds(59);
|
var historyWhere = ExpressionUtil.Create<LkAccessHistory>().And(j => j.Key == id)
|
.And(j => j.CreateTime >= minTime)
|
.And(j => j.CreateTime <= maxTime)
|
.And(j => j.Ip == ip)
|
.ToExpression();
|
var statistic = _lkAccessStatisticService.GetFirst(j => j.Key == id);
|
if (!statistic.IsNull())
|
{
|
StringBuilder updateSql = new StringBuilder();
|
updateSql.Append($"UPDATE lk_access_statistic SET pv=pv+1,update_time=NOW() ");
|
|
bool isExist = _lkAccessHistoryService.IsExist(historyWhere);
|
if (!isExist)
|
{
|
updateSql.Append($",uv=uv+1 ");
|
}
|
updateSql.Append($" WHERE id={statistic.Id};");
|
//更新访问统计
|
_lkAccessStatisticService.ExecuteCommand(updateSql.ToString());
|
}
|
UserAgentDTO agent = GetUserAgent();
|
var history = new LkAccessHistory
|
{
|
CreateTime = DateTime.Now,
|
Ip = ip,
|
Key = id,
|
EquipmentCode = agent.EquipmentCode,
|
EquipmentName = agent.EquipmentName,
|
Nick = link.Nick,
|
Mob = mobEncry
|
};
|
//插入访问历史
|
_lkAccessHistoryService.Insert(history);
|
});
|
|
return Redirect(link.OriginUrl);
|
}
|
|
/// <summary>
|
/// 获取远程客户端IP
|
/// </summary>
|
/// <returns></returns>
|
private string GetClientIp()
|
{
|
if (Request.Headers.ContainsKey("X-Forwarded-For"))
|
{
|
return Request.Headers["X-Forwarded-For"].ToString();
|
}
|
|
string ip = Request.HttpContext.Connection.RemoteIpAddress.ToString();
|
return ip == "::1" ? "127.0.0.1" : ip;
|
}
|
|
/// <summary>
|
/// 获取请求设备信息
|
/// </summary>
|
/// <returns></returns>
|
private UserAgentDTO GetUserAgent()
|
{
|
UserAgentDTO agentInfo = new UserAgentDTO();
|
if (Request.Headers.ContainsKey("User-Agent"))
|
{
|
string agent = Request.Headers["User-Agent"].ToString();
|
CommonUtil.LogUtil.Info(agent, "Agent");
|
Dictionary<string, string> agentList = GetAgentList();
|
foreach (var item in agentList)
|
{
|
Regex rx = new Regex(item.Value, RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
MatchCollection match = rx.Matches(agent);
|
if (match.Count > 0)
|
{
|
agentInfo.EquipmentCode = item.Key.Split('|')[0];
|
agentInfo.EquipmentName = item.Key.Split('|')[1];
|
return agentInfo;
|
}
|
}
|
|
}
|
agentInfo.EquipmentCode = "other";
|
agentInfo.EquipmentName = "其他";
|
return agentInfo;
|
}
|
|
private Dictionary<string, string> GetAgentList()
|
{
|
Dictionary<string, string> dic = new Dictionary<string, string>();
|
dic.Add("mi|小米", "/*mi.*Build/QKQ1");
|
dic.Add("huawei|华为", "/*HUAWEI");
|
dic.Add("iphone|苹果", "/*iPhone");
|
dic.Add("windows|WindowsPC", "/*Windows");
|
dic.Add("samsung|三星", "/*Android.*SM.*Build/QP1A");
|
return dic;
|
}
|
|
/// <summary>
|
/// 解密
|
/// </summary>
|
/// <param name="s"></param>
|
/// <returns></returns>
|
private string MobileDecry(string s)
|
{
|
s = s.Replace("_", "/").Replace("-", "+").PadRight((s.Length + 3) / 4 * 4, '=');
|
byte[] bytes = Convert.FromBase64String(s).Reverse().Concat(new byte[8]).Take(8).ToArray();
|
string re = BitConverter.ToInt64(bytes, 0).ToString();
|
return re.Length == 11 ? re : s;
|
}
|
}
|
}
|