123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- using Azure.Storage.Blobs.Models;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Options;
- using System;
- using System.Collections.Generic;
- using System.Drawing.Imaging;
- using System.IO;
- using System.Linq;
- using System.Net.Http;
- using System.Reflection;
- using System.Text.Json;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- using TEAMModelOS.Models;
- using TEAMModelOS.Models.Request;
- using TEAMModelOS.SDK;
- using TEAMModelOS.SDK.DI;
- using TEAMModelOS.SDK.Extension;
- using TEAMModelOS.SDK.Models.Service;
- using TEAMModelOS.SDK.PngQuant;
- namespace TEAMModelOS.Controllers
- {
- [Route("core")]
- [ApiController]
- public class CoreController : ControllerBase
- {
- private readonly AzureRedisFactory _azureRedis;
- private readonly AzureStorageFactory _azureStorage;
- private readonly DingDing _dingDing;
- private readonly Option _option;
- private readonly HttpClient _httpClient;
- private readonly IPSearcher _searcher;
- public CoreController(IPSearcher searcher,AzureRedisFactory azureRedis, AzureStorageFactory azureStorage , DingDing dingDing, IOptionsSnapshot<Option> option, HttpClient httpClient)
- {
- _searcher= searcher;
- _azureStorage = azureStorage;
- _dingDing = dingDing;
- _option = option?.Value;
- _httpClient = httpClient;
- _azureRedis = azureRedis;
- }
- [HttpPost("apply-school")]
-
- public async Task<IActionResult> ApplySchool(ApplySchool request)
- {
- string msg = $"有新学校申请。\n" +
- $"申请站点:{_option.Location}\n" +
- $"申请学校:{request.name}\n" +
- $"学制:{string.Join(",", request.period)}\n" +
- $"机构代码:{request.orgCode}\n" +
- $"所在国家\\地区:{request.area}\n" +
- $"申请人:{request.tmdname}({request.tmdid})\n" +
- $"联系电话:{request.cellphone}\n" +
- $"备注:{request.content}";
- await _dingDing.SendBotMsg(msg, GroupNames.AI智慧學校申請通知群);
- return Ok(new { msg });
- }
- [HttpPost("random-code")]
- [RequestSizeLimit(100_000_000)] //最大100m左右
- public async Task<IActionResult> RandomCode(JsonElement request)
- {
-
- if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();//学校编码 或者醍摩豆id
- string _num09 = "123456789";
- string no = $"{Utils.CreatSaltString(6, _num09)}";
- var Expire =DateTime.UtcNow.AddHours(1);
- string key = $"Random:Code:{no}-{code}";
- await _azureRedis.GetRedisClient(8).StringSetAsync(key, new { code=code,no=no, Expire = Expire.Ticks }.ToJsonString());
- _azureRedis.GetRedisClient(8).KeyExpire(key, Expire);
- return Ok(new { random=no });
- }
- [HttpPost("system-info")]
- [RequestSizeLimit(100_000_000)] //最大100m左右
- public async Task<IActionResult> SystemInfo(JsonElement request)
- {
- Type attr = this.GetType();
- string currentDirectory = Path.GetDirectoryName(attr.Assembly.Location);
- Assembly assembly = Assembly.LoadFrom( $"{currentDirectory}\\TEAMModelOS.dll");
- var description= assembly.GetCustomAttribute<AssemblyDescriptionAttribute>().Description;
- //var v1 = Assembly.GetEntryAssembly().GetName().Version;
- //var v2 = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
- // var description = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyDescriptionAttribute>().Description;
- var version = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
- long nowtime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
- //Console.WriteLine($"Assembly.GetEntryAssembly().GetName().Version: " +
- // $"{Assembly.GetEntryAssembly().GetName().Version}");5.2107.12.1
- //Console.WriteLine($"Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version:" +
- // $"{Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version}");5.2107.12.1
- //Console.WriteLine($"Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion:" +
- // $"{Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion}");5.2107.12
- var IpPort = HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
- if (string.IsNullOrEmpty(IpPort))
- {
- IpPort = HttpContext.Connection.RemoteIpAddress.ToString();
- }
- if (IpPort.Contains("::"))
- {
- IpPort = "127.0.0.1";
- }
- string ip = IpPort.Split(":")[0];
- string region = await _searcher.SearchIpAsync(ip);
- return Ok(new { version, description, nowtime , region,ip });
- }
- /// <summary>
- /// 等待P1V3,啟動Dcoker,支持EMF GDI+
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- [HttpPost("convert-emf")]
- [RequestSizeLimit(100_000_000)] //最大100m左右
- public async Task<IActionResult> ConvertEmf(ImageQuangRequest request)
- {
- try
- {
- if (string.IsNullOrWhiteSpace(request.base64)) return BadRequest();
- byte[] obase64data = Convert.FromBase64String(request.base64);
- using var obase64ms = new MemoryStream(obase64data);
- var (isimg, type, dupe) = Utils.ImageValidateByStream(obase64ms);
- if (isimg && type.Equals("emf"))
- {
- var pngimagebase64 = Utils.ConvertEMFtoPNG(obase64ms);
- return Ok(pngimagebase64);
- }
- else
- {
- return BadRequest("非EMF圖片格式");
- }
- }
- catch (Exception ex)
- {
- await _dingDing.SendBotMsg($"Core,{_option.Location},convert-emf()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
- return BadRequest();
- }
- }
- /// <summary>
- /// PNG JPF 圖片輕量化
- /// </summary>
- /// <param name="request">支持html base64標籤解析</param>
- /// <returns></returns>
- [HttpPost("image-quant")]
- //
- [RequestSizeLimit(100_000_000)] //最大100m左右
- public async Task<IActionResult> ImageQuang(List<ImageQuangRequest> request)
- {
- if (request.Count < 1) return BadRequest();
- Regex rex = new Regex(@"data:(?<key1>image.+?);base64,(?<key2>.+)");
- List<object> respons = new List<object>();
- var quantizer = new PngQuantizer();
- foreach (var item in request)
- {
- //正則處理,移除空白
- string trim = Regex.Replace(item.base64, @"\s", "");
- Match match = rex.Match(trim);
- string otype = match.Groups["key1"].Value;
- string obase64 = match.Groups["key2"].Value;
- byte[] obase64data = Convert.FromBase64String(obase64);
- using var obase64ms = new MemoryStream(obase64data);
- //驗證圖片格式及位深,判斷是否要處理量化演算
- var (isimg, type, dupe) = Utils.ImageValidateByStream(obase64ms);
- if (isimg && (type.Equals("png") || type.Equals("jpg")) && dupe > 8)
- {
- string img = string.Empty;
- using var quantized = quantizer.QuantizeImage(obase64ms, item.width, item.height); //JPEG,PNG輕量化
- if (quantized != null)
- {
- //檢查是否需要保存原圖到blob
- if (!string.IsNullOrWhiteSpace(item.blob))
- {
- img = $"{Guid.NewGuid():N}.{type}"; //命名新圖片名稱
- string Container = item.blob.Substring(0, item.blob.IndexOf("/")); //取得容器名稱
- string blobpath = $"{item.blob[(item.blob.Trim('/').IndexOf("/") + 1)..]}/{img}"; //處理路徑,避免多餘的字符
- obase64ms.Position = 0;
- await _azureStorage.GetBlobContainerClient(Container).GetBlobClient(blobpath).UploadAsync(obase64ms, new BlobHttpHeaders { ContentType = otype });
- }
- using var nbase64ms = new MemoryStream();
- quantized.Save(nbase64ms, ImageFormat.Png); //保存為PNG格式
- byte[] data = nbase64ms.ToArray();
- string base64 = $"data:image/png;base64,{Convert.ToBase64String(data)}"; //創建新的img src base64
- respons.Add(new { base64 = base64, blob = img });
- // TODO 下面註解,無法解決保存時,真正改變Format32bppArgb為Format8bppIndexed,需要再研究
- //ImageCodecInfo imageCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(info => info.MimeType == "image/png");
- //var parameters = new EncoderParameters(1);
- //parameters.Param[0] = new EncoderParameter(Encoder.ColorDepth, 8);
- //quantized.Save(nbase64ms, imageCodecInfo, parameters); //保存為PNG格式
- }
- else
- {
- respons.Add(new { base64 = item.base64, blob = "" }); //異常的圖片,原Base64返回
- }
- }
- else
- {
- respons.Add(new { base64 = item.base64, blob = "" }); //不符合的圖片,原Base64返回
- }
- }
- return Ok(respons);
- }
- }
- public record ApplySchool
- {
- /// <summary>
- /// 学校名称
- /// </summary>
- public string name { get; set; }
- /// <summary>
- /// 站点
- /// </summary>
- public string site { get; set; }
- public string area { get; set; }
- public string tmdname { get; set; }
- public string tmdid { get; set; }
- /// <summary>
- /// 手机号
- /// </summary>
- public string cellphone { get; set; }
- /// <summary>
- /// 备注
- /// </summary>
- public string content { get; set; }
- /// <summary>
- /// 学制
- /// </summary>
- public List<string> period { get; set; } = new List<string>();
- /// <summary>
- /// 机构代码
- /// </summary>
- public string orgCode { get; set; }
- }
- }
|