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 { /// /// /// public class IndexController : BaseController { /// /// 短链接口 /// private readonly ILkLinkService _lkLinkService; /// /// 短链访问记录接口 /// private readonly ILkAccessHistoryService _lkAccessHistoryService; /// /// 短链访问统计接口 /// private readonly ILkAccessStatisticService _lkAccessStatisticService; /// /// 缓存容器 /// private readonly IEasyCachingProvider _provider; /// /// 构造函数 /// /// /// /// /// public IndexController(IEasyCachingProvider provider, ILkLinkService lkLkinkService, ILkAccessHistoryService lkAccessHistoryService, ILkAccessStatisticService lkAccessStatisticService) { _provider = provider; _lkLinkService = lkLkinkService; _lkAccessHistoryService = lkAccessHistoryService; _lkAccessStatisticService = lkAccessStatisticService; } /// /// /// /// /// [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($"LINK_{id}"); if (!linkCache.HasValue) { //var where = ExpressionUtil.Create().And(j => j.Key == id) // .And(j => j.ExpireTime >= DateTime.Now) // .ToExpression(); var where = ExpressionUtil.Create().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().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); } /// /// 获取远程客户端IP /// /// 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; } /// /// 获取请求设备信息 /// /// 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 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 GetAgentList() { Dictionary dic = new Dictionary(); 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; } /// /// 解密 /// /// /// 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; } } }