using HTEXLib.COMM.Helpers; using Newtonsoft.Json.Linq; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models.Dtos; using static OpenXmlPowerTools.RevisionProcessor; namespace TEAMModelOS.SDK.Models.Service { public static class SystemService { public static async Task RecordAccumulateData(AzureRedisFactory azureRedis,DingDing dingDing, Accumulate accumulate) { if (!string.IsNullOrWhiteSpace(accumulate.key) && !string.IsNullOrWhiteSpace(accumulate.target) && !string.IsNullOrWhiteSpace(accumulate.id) && !string.IsNullOrWhiteSpace(accumulate.name) && !string.IsNullOrWhiteSpace(accumulate.scope) && !string.IsNullOrWhiteSpace(accumulate.client)) { await RecordAccumulateData(azureRedis, accumulate.key, accumulate.target, accumulate.id, accumulate.name, accumulate.scope, accumulate.client, accumulate.count); } else { await dingDing.SendBotMsg($"IES累计数据变更统计参数异常,{accumulate.ToJsonString()}", GroupNames.成都开发測試群組); } } /// /// 记录累计数据 /// public static async Task RecordAccumulateData(AzureRedisFactory azureRedis, string key, string target, string id, string name, string scope, string client,int count) { if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(target) && !string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(name) && !string.IsNullOrWhiteSpace(scope)&& !string.IsNullOrWhiteSpace(client)) { //处理UTC时差 var nowTime = DateTimeOffset.UtcNow.GetGMTTime(); int difference = (DayOfWeek.Sunday - nowTime.DayOfWeek + 7) % 7; //1-7的结果0-6 var day = nowTime.ToString("yyyyMMdd"); string redisKey = $"Accumulate:Daily:{scope}:{key}:{day}"; string member = $"{target}::{id}::{client}::{name}"; await azureRedis.GetRedisClient(8).SortedSetIncrementAsync(redisKey, member, count); await azureRedis.GetRedisClient(8).KeyExpireAsync(redisKey,new TimeSpan((difference+1)*24, 10,0)); //if (key.Equals("lesson") || key.StartsWith("login_")) //{ // redisKey = $"Accumulate:Daily:ies:{key}:{day}"; // if (scope.Equals("school")) // { // member = $"ies::{id}::{name}"; // } // else { // member = $"ies::ies::{name}"; // } // await azureRedis.GetRedisClient(8).SortedSetIncrementAsync(redisKey, member, 1); //} } } public static (ConcurrentBag vists, ConcurrentBag<(string uuid, HttpLog httpLog, List tmdid, List school)> uuidInfo) ConvertHttpLog(ConcurrentBag logs, IPSearcher _ipSearcher, Region2LongitudeLatitudeTranslator _longitudeLatitudeTranslator) { ConcurrentBag vists = new ConcurrentBag(); ConcurrentBag<(string uuid, HttpLog httpLog, List tmdid, List school)> uuidInfo = new ConcurrentBag<(string uuid, HttpLog httpLog, List tmdid, List school)>(); object lockObj = new object(); Parallel.ForEach(logs, async log => { string uuid = Guid.NewGuid().ToString(); List schoolMatch = new List(); List useridMatch = new List(); var vist = new ApiVist() { id=uuid, ip=log.ip, tid=log.tid, time= log.time, userId= log.id, school= log.school, tname= log.name, path = log.path, year=log.year, month=log.month, day=log.day, hour=log.hour }; if (string.IsNullOrWhiteSpace(vist.userId)) { //var jsonPathContext = new JsonPathContext(); //jsonPathContext.ValueSystem= new JsonTextValueSystem(); string path = "$..['id_token','idToken','idtoken','tmdid','id','teacherId','teacher','tid','tId','userid','userId','code','studentId','student','studentid']"; JObject jsonObject = JObject.Parse(log.param.GetRawText()); //var nodes_path = jsonPathContext.SelectNodes(log.param, path); var nodes_path = jsonObject.SelectTokens(path); foreach (var node in nodes_path) { // 只获取是字符串的 if (node.Type.Equals(JTokenType.String)) { switch (true) { case bool when node.Path.Contains("id_token")||node.Path.Contains("idToken")||node.Path.Contains("idtoken"): { try { var jwt = new JwtSecurityToken($"{node}"); string id = jwt.Payload.Sub; var name = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("name"))?.Value; if (!string.IsNullOrWhiteSpace(id) && long.TryParse(id, out long _id)) { useridMatch.Add(id); } } catch (Exception ex) { } break; } case bool when node.Path.Contains("tmdid")||node.Path.Contains("id")||node.Path.Contains("teacherId") ||node.Path.Contains("teacher")||node.Path.Contains("tid")||node.Path.Contains("tId")||node.Path.Contains("userid") ||node.Path.Contains("userId")||node.Path.Contains("studentId")||node.Path.Contains("student")||node.Path.Contains("studentid"): { if (!string.IsNullOrWhiteSpace($"{node}") && long.TryParse($"{node}", out long _id)) { useridMatch.Add($"{node}"); } break; } case bool when node.Path.Contains("code"): { if (!string.IsNullOrWhiteSpace($"{node}")) { if (long.TryParse($"{node}", out long _id)) { useridMatch.Add($"{node}"); } else { string[] codes = $"{node}".Split("-"); foreach (var _code in codes) { if (long.TryParse(_code, out long _codeid)) { useridMatch.Add($"{_code}"); break; } } } } break; } } } } } if (string.IsNullOrWhiteSpace(vist.school)) { string path = "$..['school','id','schoolId','schoolid','schoolCode','school_code','schoolcode','code']"; JObject jsonObject = JObject.Parse(log.param.GetRawText()); var nodes_path = jsonObject.SelectTokens(path); foreach (var node in nodes_path) { // 只获取是字符串的 if (node.Type.Equals(JTokenType.String)) { switch (true) { case bool when node.Path.Contains("school")||node.Path.Contains("id")||node.Path.Contains("schoolId") ||node.Path.Contains("schoolid")||node.Path.Contains("schoolCode")||node.Path.Contains("school_code")||node.Path.Contains("schoolcode"): { if (!$"{node}".Contains("-")&& $"{node}".Length<=8) { schoolMatch.Add($"{node}"); } break; } case bool when node.Path.Contains("code"): { if (!$"{node}".Contains("-")&& $"{node}".Length<=8) { schoolMatch.Add($"{node}"); } else { string[] codes = $"{node}".Split("-"); foreach (var _code in codes) { if ($"{node}".Length<=8) { schoolMatch.Add($"{_code}"); break; } } } break; } } } } } //处理 client { if (!string.IsNullOrWhiteSpace(log.client)) { if (log.client.Equals("IES", StringComparison.OrdinalIgnoreCase)) { vist.client="ies5"; } if (log.client.Equals("AClassONE", StringComparison.OrdinalIgnoreCase)) { vist.client="aclassone"; } if (log.client.Equals("BB", StringComparison.OrdinalIgnoreCase)) { vist.client="habb"; } if (log.client.Equals("HiTool", StringComparison.OrdinalIgnoreCase) ||log.client.Equals("HiTools", StringComparison.OrdinalIgnoreCase)) { vist.client="hiscan"; } if (log.client.Equals("HiTA", StringComparison.OrdinalIgnoreCase)) { vist.client="hita"; } if (log.client.Equals("HiTeachCC", StringComparison.OrdinalIgnoreCase)) { vist.client="hiteachcc"; } if (log.client.Equals("HiTeach", StringComparison.OrdinalIgnoreCase)) { vist.client="hiteach"; } if (log.client.Equals("Open", StringComparison.OrdinalIgnoreCase)) { vist.client="open"; } } } //补全站点 { if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("teammodelos-yx.chinacloudsites.cn")||log.host.Equals("teammodelos.chinacloudsites.cn") ||log.host.Equals("yx.teammodel.cn"))) { log.host="IES-正式站"; log.host="www.teammodel.cn"; vist.client="ies5"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("scyx.teammodel.cn") ||log.host.Equals("jinniu.teammodel.cn"))) { log.host="研修2.0-正式站"; log.host="scyx.teammodel.cn"; vist.client="ability"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("open.teammodel.cn"))) { log.host="开放平台-正式站"; log.host="open.teammodel.cn"; vist.client="open"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("open-test.teammodel.cn") ||log.host.Equals("zhiyin-test.teammodel.cn"))) { log.host="开放平台-测试站"; log.host="open-test.teammodel.cn"; vist.client="open"; } // if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("teammodelos-rc.chinacloudsites.cn"))) { log.host="IES-RC站"; log.host="rc.teammodel.cn"; vist.client="ies5"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("teammodelos-test.chinacloudsites.cn"))) { log.host="IES-测试站"; log.host="test.teammodel.cn"; vist.client="ies5"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("teammodelbi-test.chinacloudsites.cn"))) { log.host="BI-测试站"; log.host="bitest.teammodel.cn"; vist.client="bi"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("teammodelbi.chinacloudsites.cn"))) { log.host="BI-正式站"; log.host="bi.teammodel.cn"; vist.client="bi"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("teamcontest.chinacloudsites.cn"))) { log.host="赛课-正式站"; log.host="contest.teammodel.cn"; vist.client="contest"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("contest.chinacloudsites.cn"))) { log.host="赛课-正式站"; log.host="contest.teammodel.cn"; vist.client="contest"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("contest-test.chinacloudsites.cn"))) { log.host="赛课-测试站"; log.host="contest-test.teammodel.cn"; vist.client="contest"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("hiteachcc.chinacloudsites.cn"))) { log.host="CC-正式站"; log.host="hiteachcc.teammodel.cn"; vist.client="hiteachcc"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("appraisal.chinacloudsites.cn"))) { log.host="评价-正式站"; log.host="appraisal.teammodel.cn"; vist.client="appraisal"; } if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("appraisal-test.chinacloudsites.cn"))) { log.host="评价-测试站"; log.host="appraisal-test.teammodel.cn"; vist.client="appraisal"; } if (log.host.Equals("localhost") && log.p.Equals("appraisal")) { log.host="评价-测试站"; log.host="appraisal-test.teammodel.cn"; vist.client="appraisal"; } if (log.host.Equals("localhost") && log.p.Equals("os")) { log.host="IES-测试站"; log.host="test.teammodel.cn"; vist.client="ies5"; } else if (log.host.Equals("localhost") && (log.p.Equals("bi"))) { log.host="BI-测试站"; log.host="bitest.teammodel.cn"; vist.client="bi"; } } //补全产品端 { //研修2.0 if (log.path.Contains("research") || log.path.Contains("study") || log.path.Contains("standard-file")) { vist.client="ability"; } if (log.path.StartsWith("/activity")) { vist.client="contest"; } //小程序 if (log.path.Contains("aclassone")) { vist.client="aclassone"; } // /// /// ExamInfo qamode 書面問答類型 0:書面問答 1:紙本測驗 2:艺术评测 /// //艺术评测 if (log.path.Contains("art") ||log.path.Contains("aclassone/find-children-activity") ||log.path.Contains("aclassone/find-teacher-activity") ||log.path.Contains("aclassone/find-summary-activity") ||log.path.Contains("aclassone/upload-all") ||log.path.Contains("aclassone/delete")) { vist.client="art"; } if (log.path.Contains("habb")) { vist.client="habb"; } //阅卷客户端 if (log.path.Contains("hiscan")) { vist.client="hiscan"; } if (log.path.Contains("hita")) { vist.client="hita"; } if (log.path.Contains("hiteachcc")) { vist.client="hiteachcc"; } if (log.path.Contains("sokrate")) { vist.client="sokrate"; } if (log.path.Contains("sokrate") || log.path.Contains("score")) { vist.client="sokrate"; } if (log.path.Contains("hiteach")) { vist.client="hiteach"; } ///IES开放平台 if (log.path.Contains("business") || log.path.Contains("biz") || log.path.Contains("openapi-config") || log.path.Contains("open-api")) { vist.client="open"; } //从token的role 能否获取 开放平台 //单点登录及第三方接口 if (log.path.Contains("lepei") || log.path.Contains("sc/") || log.path.Contains("/sso") || log.path.Contains("sc-init") || log.path.Contains("data-push") || log.path.Contains("xkw")|| log.path.Contains("tianbo") || log.path.Contains("oauth/check-bind")|| log.path.Contains("dingding") || log.path.Contains("wechat") ) { vist.client="sso-third"; } } //处理IP转地区 vist.region=await _ipSearcher.SearchIpAsync(vist.ip); if (!string.IsNullOrWhiteSpace(vist.region)) { vist.region= vist.region.Replace("省·", "·").Replace("市·", "·").Replace("特别行政区·", "·").Replace("藏族羌族自治州·", "·"); var regions = vist.region.Split("·"); if (regions.Length==4) { vist.area= regions[0]; vist.province = regions[1]; vist.city = regions[2]; } if (regions.Length==3) { vist.area= regions[0]; vist.province = regions[1]; } if (regions.Length==2) { vist.area= regions[0]; vist.province = regions[1]; } if (regions.Length==1) { vist.area= regions[0]; } } //处理地区转经纬度 { IEnumerable tokens = default; if (!string.IsNullOrWhiteSpace(vist.city) && !string.IsNullOrWhiteSpace(vist.province) && !string.IsNullOrWhiteSpace(vist.area)) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i && @.city=~ /.*{vist.city}/i)]"); if (!(tokens.Any() && tokens.Count()>0)) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i && @.city=~ /.*{vist.province}/i)]"); if (!(tokens.Any() && tokens.Count()>0)) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i || @.city=~ /.*{vist.city}/i)]"); } if (!(tokens.Any() && tokens.Count()>0)) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i||@.city=~ /.*{vist.province}/i)]"); } } } else if (string.IsNullOrWhiteSpace(vist.city) && !string.IsNullOrWhiteSpace(vist.province) && !string.IsNullOrWhiteSpace(vist.area)) { if (vist.area.Equals("中国")) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i)]"); if (!(tokens.Any() && tokens.Count()>0)) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i)]"); } } else { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i || @.province=~ /.*{vist.province}/i)]"); } } else if (!string.IsNullOrWhiteSpace(vist.city) && string.IsNullOrWhiteSpace(vist.province)&& !string.IsNullOrWhiteSpace(vist.area)) { if (vist.area.Equals("中国")) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i)]"); if (!(tokens.Any() && tokens.Count()>0)) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i)]"); } } else { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.city}/i || @.city=~ /.*{vist.province}/i)]"); } } else if (string.IsNullOrWhiteSpace(vist.city) && string.IsNullOrWhiteSpace(vist.province)&& !string.IsNullOrWhiteSpace(vist.area)) { tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.country=~ /.*{vist.area}/i && @.m=='1')]"); } if (tokens!= null && tokens!=default && tokens.Any() && tokens.Count()>0) { List regionLngLats = new List(); foreach (JToken token in tokens) { regionLngLats.Add(token.ToString().ToObject()); } var region = regionLngLats.FindAll(x => string.IsNullOrWhiteSpace(x.area)); if (!region.IsNotEmpty()) { region= regionLngLats.FindAll(x => !string.IsNullOrWhiteSpace(x.m) && x.m.Equals("1")); } vist.point= region?.FirstOrDefault(); } } vist.host= log.host; vist.hostName=log.hostName; uuidInfo.Add((uuid, log, useridMatch, schoolMatch)); vists.Add(vist); }); return (vists, uuidInfo); } public class ApiVist { public string id { get; set; } public string path { get; set; } /// /// 细分 /// ies5 ,hiteach,hita,cc,bi,contest,open,aclassone,sokrates,ability,art /// 产品端 /// public string client { get; set; } /// /// 具体功能 /// public string func { get; set; } public string userId { get; set; } public string scope { get; set; } public string tname { get; set; } public string school { get; set; } public string ip { get; set; } public string region { get; set; } public string area { get; set; } public string province { get; set; } public string city { get; set; } public long time { get; set; } /// /// /// public string host { get; set; } public string hostName = "其他"; /// /// tokenid /// public string tid { get; set; } public string year { get; set; } public string month { get; set; } public string day { get; set; } public string hour { get; set; } public RegionLngLat point { get; set; } } public class HttpLog { public string ip { get; set; } public long time { get; set; } public string host { get; set; } public string hostName = "其他"; public string tid { get; set; } public string path { get; set; } public string client { get; set; } public JsonElement param { get; set; } public string id { get; set; } public string name { get; set; } public string school { get; set; } public string p { get; set; } // public string ua { get; set; } // public string referer { get; set; } public string scope { get; set; } public string year { get; set; } public string month { get; set; } public string day { get; set; } public string hour { get; set; } } public record RegionLngLat { public string country { get; set; } public string province { get; set; } public string city { get; set; } public string lat { get; set; } public string lng { get; set; } public string area { get; set; } public string m { get; set; } = "0"; } } }