You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Model.cs 76 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776
  1. using COSXML.Auth;
  2. using COSXML.CosException;
  3. using COSXML.Model.Object;
  4. using COSXML;
  5. using Newtonsoft.Json;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.IO;
  9. using System.Security.Cryptography;
  10. using System.Text;
  11. using System;
  12. using COSXML.Model.Bucket;
  13. using System.Runtime.InteropServices;
  14. using System.Text.Json.Nodes;
  15. using System.Net.Http.Json;
  16. using System.Text.Json;
  17. using System.Xml.Schema;
  18. using static Downloader.Program;
  19. using System.Threading.Tasks;
  20. using System.Net.Http;
  21. using System.Windows;
  22. using System.Windows.Shapes;
  23. //using System.Windows.Forms;
  24. using System.Threading.Tasks;
  25. using System.Threading;
  26. using MessageBox = System.Windows.MessageBox;
  27. using Downloader;
  28. using COSXML.Transfer;
  29. using WebConnect;
  30. using System.IO.Compression;
  31. using ICSharpCode.SharpZipLib.Tar;
  32. using ICSharpCode.SharpZipLib.GZip;
  33. using static System.Net.WebRequestMethods;
  34. using File = System.IO.File;
  35. using System.Linq;
  36. using Installer;
  37. using starter.viewmodel.settings;
  38. using System.Security.Permissions;
  39. using System.Windows.Media;
  40. namespace starter.viewmodel.settings
  41. {
  42. /// <summary>
  43. /// Settings Window Model
  44. /// </summary>
  45. public class SettingsModel
  46. {
  47. /// <summary>
  48. /// downloader function
  49. /// </summary>
  50. private Data configData = new Data("");
  51. private Tencent_cos_download cloud = new Tencent_cos_download();
  52. private HttpClient client = new HttpClient();
  53. private WebConnect.Web web = new WebConnect.Web();
  54. public SettingsModel()
  55. {
  56. Route = Data.FilePath;
  57. Username = "";
  58. Password = "";
  59. updates = "";
  60. CodeRoute = "";
  61. PlayerNum = "nSelect";
  62. UploadReady = false;
  63. LoginFailed = false;
  64. launchLanguage = LaunchLanguage.cpp;
  65. usingOS = ReadUsingOS();
  66. }
  67. /// <summary>
  68. /// save settings
  69. /// </summary>
  70. public bool install()
  71. {
  72. if (Tencent_cos_download.CheckAlreadyDownload())
  73. {
  74. MessageBoxResult repeatOption = MessageBox.Show($"文件已存在于{Downloader.Program.Data.FilePath},是否移动到新位置?", "重复安装", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
  75. // ask if abort install, with warning sign, defalut move instead of abort;
  76. if (repeatOption == MessageBoxResult.No)
  77. {
  78. Route = Data.FilePath;
  79. return false;
  80. }
  81. else
  82. {
  83. Downloader.Program.Tencent_cos_download.MoveProgram(Route);
  84. return true;
  85. }
  86. }
  87. else
  88. {
  89. Data.ResetFilepath(Route);
  90. Tencent_cos_download.DownloadAll();
  91. return true;
  92. }
  93. }
  94. public int move()
  95. {
  96. int state = Tencent_cos_download.MoveProgram(Route);
  97. if (state != 0)
  98. Route = Data.FilePath;
  99. return state;
  100. }
  101. ///<summary>
  102. ///check for update
  103. /// </summary>
  104. static bool ProfileAvailable
  105. {
  106. get; set;
  107. }
  108. /// <summary>
  109. /// 检查更新
  110. /// </summary>
  111. /// <returns></returns>
  112. public Status checkUpdate()
  113. {
  114. UpdateInfo updateInfo = Tencent_cos_download.Check(usingOS);
  115. if (updateInfo.newFileCount == -1)
  116. {
  117. if (updateInfo.changedFileCount == -1)
  118. {
  119. return Status.error;
  120. }
  121. else
  122. {
  123. return Status.disconnected;
  124. }
  125. }
  126. else
  127. {
  128. if (updateInfo.changedFileCount != 0 || updateInfo.newFileCount != 0)
  129. {
  130. Updates = $"{updateInfo.newFileCount}个新文件,{updateInfo.changedFileCount}个文件变化";
  131. }
  132. return Status.menu;
  133. }
  134. }
  135. public async Task<int> Login()
  136. {
  137. return await web.LoginToEEsast(client, Username, Password);
  138. }
  139. public bool RememberUser()
  140. {
  141. int result = 0;
  142. result |= Web.WriteJson("email", Username);
  143. result |= Web.WriteJson("password", Password);
  144. return result == 0;
  145. }
  146. public bool RecallUser()
  147. {
  148. Username = Web.ReadJson("email");
  149. if (Username == null || Username.Equals(""))
  150. {
  151. Username = "";
  152. return false;
  153. }
  154. Password = Web.ReadJson("password");
  155. if (Password == null || Username.Equals(""))
  156. {
  157. Password = "";
  158. return false;
  159. }
  160. return true;
  161. }
  162. public bool ForgetUser()
  163. {
  164. int result = 0;
  165. result |= Web.WriteJson("email", "");
  166. result |= Web.WriteJson("password", "");
  167. return result == 0;
  168. }
  169. public bool Update()
  170. {
  171. try
  172. {
  173. return Tencent_cos_download.Update();
  174. }
  175. catch
  176. {
  177. return false;
  178. }
  179. }
  180. public int Uninst()
  181. {
  182. return Tencent_cos_download.DeleteAll();
  183. }
  184. public bool Launch()
  185. {
  186. if (Tencent_cos_download.CheckAlreadyDownload())
  187. {
  188. Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
  189. return true;
  190. }
  191. else
  192. {
  193. MessageBox.Show($"文件还不存在,请安装主体文件", "文件不存在", MessageBoxButton.OK, MessageBoxImage.Warning, MessageBoxResult.OK);
  194. return false;
  195. }
  196. }
  197. public async Task<int> Upload()
  198. {
  199. switch (CodeRoute.Substring(CodeRoute.LastIndexOf('.') + 1))
  200. {
  201. case "cpp":
  202. Language = "cpp";
  203. break;
  204. case "h":
  205. Language = "cpp";
  206. break;
  207. case "py":
  208. Language = "python";
  209. break;
  210. default:
  211. return -8;
  212. }
  213. if (PlayerNum.Equals("nSelect"))
  214. return -9;
  215. return await web.UploadFiles(client, CodeRoute, Language, PlayerNum);
  216. }
  217. public bool WriteUsingOS()
  218. {
  219. string OS = "";
  220. switch (usingOS)
  221. {
  222. case UsingOS.Win:
  223. OS = "win";
  224. break;
  225. case UsingOS.Linux:
  226. OS = "linux";
  227. break;
  228. case UsingOS.OSX:
  229. OS = "osx";
  230. break;
  231. }
  232. return Web.WriteJson("OS", OS) == 0;
  233. }
  234. public UsingOS ReadUsingOS()
  235. {
  236. string OS = Web.ReadJson("OS");
  237. if (OS == null)
  238. return UsingOS.Win;
  239. else if (OS.Equals("linux"))
  240. return UsingOS.Linux;
  241. else if (OS.Equals("osx"))
  242. return UsingOS.OSX;
  243. else
  244. return UsingOS.Win;
  245. }
  246. /// <summary>
  247. /// Route of files
  248. /// </summary>
  249. public string Route
  250. {
  251. get; set;
  252. }
  253. public string Username
  254. {
  255. get; set;
  256. }
  257. public string Password
  258. {
  259. get; set;
  260. }
  261. public string CodeRoute
  262. {
  263. get; set;
  264. }
  265. public string Language
  266. {
  267. get; set;
  268. }
  269. public string PlayerNum
  270. {
  271. get; set;
  272. }
  273. /// <summary>
  274. /// 关于更新的屏幕显示信息
  275. /// </summary>
  276. private string updates;
  277. public string Updates
  278. {
  279. get
  280. {
  281. return updates;
  282. }
  283. set
  284. {
  285. updates = value;
  286. }
  287. }
  288. /// <summary>
  289. /// 关于介绍的屏幕显示信息
  290. /// </summary>
  291. public enum Status { newUser, menu, move, working, disconnected, error, successful, login, web };
  292. public Status status
  293. {
  294. get; set;
  295. }
  296. public bool Working
  297. {
  298. get; set;
  299. }
  300. /// <summary>
  301. /// if an update is planned
  302. /// </summary>
  303. public bool UpdatePlanned
  304. {
  305. get
  306. {
  307. return Program.UpdatePlanned;
  308. }
  309. }
  310. public bool CombatCompleted
  311. {
  312. get
  313. {
  314. return false;
  315. }
  316. }
  317. public bool LoginFailed
  318. {
  319. get; set;
  320. }
  321. public bool UploadReady
  322. {
  323. get; set;
  324. }
  325. public bool RememberMe
  326. {
  327. get; set;
  328. }
  329. public enum LaunchLanguage { cpp, python };
  330. public LaunchLanguage launchLanguage
  331. {
  332. get; set;
  333. }
  334. public enum UsingOS { Win, Linux, OSX };
  335. public UsingOS usingOS
  336. {
  337. get; set;
  338. }
  339. }
  340. }
  341. namespace Downloader
  342. {
  343. class UserInfo
  344. {
  345. static public string _id = "";
  346. static public string email = "";
  347. }
  348. class Program
  349. {
  350. static List<string> newFileName = new List<string>(); // 新文件名
  351. static List<string> updateFileName = new List<string>(); // 更新文件名
  352. static List<string> updateFailed = new List<string>(); //更新失败的文件名
  353. static public List<string> UpdateFailed
  354. {
  355. get { return updateFailed; }
  356. }
  357. static public void ResetUpdateFailedInfo()
  358. {
  359. updateFailed.Clear();
  360. }
  361. public static string ProgramName = "THUAI6"; // 要运行或下载的程序名称
  362. public static string playerFolder = "player"; // 选手代码保存文件夹路径
  363. public static string startName = "maintest.exe"; // 启动的程序名
  364. public struct UpdateInfo // 更新信息,包括新版本版本号、更改文件数和新文件数
  365. {
  366. public string status;
  367. public int changedFileCount;
  368. public int newFileCount;
  369. }
  370. public static bool UpdatePlanned
  371. {
  372. get; set;
  373. }
  374. static int filenum = 0; // 总文件个数
  375. public class Data
  376. {
  377. public static string path = ""; // 标记路径记录文件THUAI6.json的路径
  378. public static string FilePath = ""; // 最后一级为THUAI6文件夹所在目录
  379. public static string dataPath = ""; // C盘的文档文件夹
  380. public Data(string path)
  381. {
  382. dataPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
  383. //dataPath = new DirectoryInfo(".").FullName;
  384. Data.path = System.IO.Path.Combine(dataPath, "THUAI6.json");
  385. if (File.Exists(Data.path))
  386. {
  387. var dict = new Dictionary<string, string>();
  388. using (StreamReader r = new StreamReader(Data.path))
  389. {
  390. string json = r.ReadToEnd();
  391. if (json == null || json == "")
  392. {
  393. json += @"{""THUAI6""" + ":" + @"""2023""}";
  394. }
  395. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  396. if (dict != null && dict.ContainsKey("installpath"))
  397. {
  398. FilePath = dict["installpath"].Replace('\\', '/');
  399. } //读取安装路径
  400. }
  401. dict?.TryAdd("installpath", @path);
  402. using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  403. using StreamWriter sw = new StreamWriter(fs);
  404. sw.Write(JsonConvert.SerializeObject(dict));
  405. sw.Flush();
  406. }
  407. else
  408. {
  409. FilePath = System.IO.Path.GetDirectoryName(@path);
  410. //将dat文件写入程序运行路径
  411. string json;
  412. Dictionary<string, string> dict = new Dictionary<string, string>();
  413. using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  414. using (StreamReader r = new StreamReader(fs))
  415. {
  416. json = r.ReadToEnd();
  417. if (json == null || json == "")
  418. {
  419. json += @"{""THUAI6""" + ":" + @"""2023""}";
  420. }
  421. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  422. dict?.Add("installpath", path);
  423. }
  424. using FileStream fs2 = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  425. using StreamWriter sw = new StreamWriter(fs2);
  426. sw.Write(JsonConvert.SerializeObject(dict));
  427. sw.Flush();
  428. }
  429. }
  430. public static void ResetFilepath(string newPath)
  431. {
  432. string json;
  433. Dictionary<string, string> dict = new Dictionary<string, string>();
  434. FilePath = newPath.Replace('\\', '/');
  435. path = System.IO.Path.Combine(dataPath, "THUAI6.json");
  436. using FileStream fs = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
  437. using (StreamReader r = new StreamReader(fs))
  438. {
  439. json = r.ReadToEnd();
  440. if (json == null || json == "")
  441. {
  442. json += @"{""THUAI6""" + ":" + @"""2023""}";
  443. }
  444. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  445. if (dict != null && dict.ContainsKey("installpath"))
  446. {
  447. dict["installpath"] = newPath;
  448. }
  449. else
  450. {
  451. dict.Add("installpath", newPath);
  452. }
  453. if (dict == null || !dict.ContainsKey("download"))
  454. {
  455. dict?.Add("download", "true");
  456. }
  457. else
  458. {
  459. dict["download"] = "true";
  460. }
  461. }
  462. using FileStream fs2 = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
  463. using StreamWriter sw = new StreamWriter(fs2);
  464. fs2.SetLength(0);
  465. sw.Write(JsonConvert.SerializeObject(dict));
  466. sw.Flush();
  467. }
  468. }
  469. public class Tencent_cos_download
  470. {
  471. public void download(string download_dir, string key)
  472. {
  473. // download_dir标记根文件夹路径,key为相对根文件夹的路径(不带./)
  474. // 初始化CosXmlConfig(提供配置SDK接口)
  475. string appid = "1314234950"; // 设置腾讯云账户的账户标识(APPID)
  476. string region = "ap-beijing"; // 设置一个默认的存储桶地域
  477. CosXmlConfig config = new CosXmlConfig.Builder()
  478. .IsHttps(true) // 设置默认 HTTPS 请求
  479. .SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
  480. .SetRegion(region) // 设置一个默认的存储桶地域
  481. .SetDebugLog(true) // 显示日志
  482. .Build(); // 创建 CosXmlConfig 对象
  483. // 永久密钥访问凭证
  484. string secretId = "AKIDvhEVXN4cv0ugIlFYiniV6Wk1McfkplYA"; //"云 API 密钥 SecretId";
  485. string secretKey = "YyGLGCJG4f5VsEUddnz9JSRPSSK8sYBo"; //"云 API 密钥 SecretKey";
  486. long durationSecond = 1000; // 每次请求签名有效时长,单位为秒
  487. QCloudCredentialProvider cosCredentialProvider = new DefaultQCloudCredentialProvider(
  488. secretId, secretKey, durationSecond
  489. );
  490. // 初始化 CosXmlServer
  491. CosXmlServer cosXml = new CosXmlServer(config, cosCredentialProvider);
  492. // 创建存储桶
  493. try
  494. {
  495. string bucket = "thuai6-1314234950"; // 格式:BucketName-APPID
  496. string localDir = System.IO.Path.GetDirectoryName(download_dir); // 本地文件夹
  497. string localFileName = System.IO.Path.GetFileName(download_dir); // 指定本地保存的文件名
  498. GetObjectRequest request = new GetObjectRequest(bucket, key, localDir, localFileName);
  499. Dictionary<string, string> test = request.GetRequestHeaders();
  500. request.SetCosProgressCallback(delegate (long completed, long total)
  501. {
  502. //Console.WriteLine(String.Format("progress = {0:##.##}%", completed * 100.0 / total));
  503. });
  504. // 执行请求
  505. GetObjectResult result = cosXml.GetObject(request);
  506. // 请求成功
  507. }
  508. catch (CosClientException clientEx)
  509. {
  510. throw clientEx;
  511. }
  512. catch (CosServerException serverEx)
  513. {
  514. throw serverEx;
  515. }
  516. catch
  517. {
  518. MessageBox.Show($"下载{download_dir}时出现未知问题,请反馈");
  519. }
  520. }
  521. public static void GetNewHash()
  522. {
  523. Tencent_cos_download Downloader = new Tencent_cos_download();
  524. Downloader.download(System.IO.Path.Combine(Data.FilePath, "hash.json"), "hash.json");
  525. }
  526. public static string GetFileMd5Hash(string strFileFullPath)
  527. {
  528. FileStream fst = null;
  529. try
  530. {
  531. fst = new FileStream(strFileFullPath, FileMode.Open, FileAccess.Read);
  532. byte[] data = MD5.Create().ComputeHash(fst);
  533. StringBuilder sBuilder = new StringBuilder();
  534. for (int i = 0; i < data.Length; i++)
  535. {
  536. sBuilder.Append(data[i].ToString("x2"));
  537. }
  538. fst.Close();
  539. return sBuilder.ToString().ToLower();
  540. }
  541. catch (Exception)
  542. {
  543. if (fst != null)
  544. fst.Close();
  545. if (File.Exists(strFileFullPath))
  546. return "conflict";
  547. return "";
  548. }
  549. finally
  550. {
  551. }
  552. }
  553. public static bool IsUserFile(string filename)
  554. {
  555. if (filename.Substring(filename.Length - 3, 3).Equals(".sh") || filename.Substring(filename.Length - 4, 4).Equals(".cmd"))
  556. return true;
  557. if (filename.Equals("AI.cpp") || filename.Equals("AI.py"))
  558. return true;
  559. return false;
  560. }
  561. public static UpdateInfo Check(SettingsModel.UsingOS OS)
  562. {
  563. string json, MD5, jsonName;
  564. int newFile = 0, updateFile = 0;
  565. newFileName.Clear();
  566. updateFileName.Clear();
  567. jsonName = "hash.json";
  568. UpdateInfo updateInfo;
  569. Tencent_cos_download Downloader = new Tencent_cos_download();
  570. try
  571. {
  572. // 如果json存在就删了重新下
  573. if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
  574. {
  575. File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
  576. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  577. }
  578. else
  579. {
  580. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  581. }
  582. }
  583. catch (CosClientException clientEx)
  584. {
  585. // 请求失败
  586. updateInfo.status = "ClientEx: " + clientEx.ToString();
  587. updateInfo.newFileCount = -1;
  588. updateInfo.changedFileCount = 0;
  589. return updateInfo;
  590. }
  591. catch (CosServerException serverEx)
  592. {
  593. // 请求失败
  594. updateInfo.status = "ServerEx: " + serverEx.ToString();
  595. updateInfo.newFileCount = -1;
  596. updateInfo.changedFileCount = 0;
  597. return updateInfo;
  598. }
  599. using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
  600. json = r.ReadToEnd();
  601. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  602. Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  603. string updatingFolder = "";
  604. switch (OS)
  605. {
  606. case SettingsModel.UsingOS.Win:
  607. updatingFolder = "THUAI6/win";
  608. break;
  609. case SettingsModel.UsingOS.Linux:
  610. updatingFolder = "THUAI6/lin";
  611. break;
  612. case SettingsModel.UsingOS.OSX:
  613. updatingFolder = "THUAI6/osx";
  614. break;
  615. }
  616. foreach (KeyValuePair<string, string> pair in jsonDict)
  617. {
  618. if (pair.Key.Length > 10 && (pair.Key.Substring(0, 10).Equals(updatingFolder)) || pair.Key.Substring(pair.Key.Length - 4, 4).Equals(".pdf"))
  619. {
  620. MD5 = GetFileMd5Hash(System.IO.Path.Combine(Data.FilePath, pair.Key.TrimStart(new char[] { '.', '/' })));
  621. if (MD5.Length == 0) // 文档不存在
  622. newFileName.Add(pair.Key);
  623. else if (MD5.Equals("conflict"))
  624. {
  625. if (pair.Key.Equals("THUAI6/win/CAPI/cpp/.vs/CAPI/v17/Browse.VC.db"))
  626. {
  627. MessageBox.Show($"visual studio未关闭:\n" +
  628. $"对于visual studio 2022,可以更新,更新会覆盖visual studio中已经打开的选手包;\n" +
  629. $"若使用其他版本的visual studio是继续更新出现问题,请汇报;\n" +
  630. $"若您自行修改了选手包,请注意备份;\n" +
  631. $"若关闭visual studio后仍弹出,请汇报。\n\n",
  632. "visual studio未关闭", MessageBoxButton.OK, MessageBoxImage.Information);
  633. }
  634. else
  635. MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
  636. }
  637. else if (!MD5.Equals(pair.Value) && !IsUserFile(System.IO.Path.GetFileName(pair.Key))) // MD5不匹配
  638. updateFileName.Add(pair.Key);
  639. }
  640. }
  641. newFile = newFileName.Count;
  642. updateFile = updateFileName.Count;
  643. filenum = newFile + updateFile;
  644. //Console.WriteLine("----------------------" + Environment.NewLine);
  645. if (newFile + updateFile == 0)
  646. {
  647. updateInfo.status = "latest";
  648. updateInfo.newFileCount = 0;
  649. updateInfo.changedFileCount = 0;
  650. newFileName.Clear();
  651. updateFileName.Clear();
  652. }
  653. else
  654. {
  655. updateInfo.status = "old";
  656. //TODO:获取版本号
  657. updateInfo.newFileCount = newFile;
  658. /*
  659. foreach (string filename in newFileName)
  660. {
  661. Console.WriteLine(filename);
  662. }
  663. */
  664. updateInfo.changedFileCount = updateFile;
  665. /*
  666. foreach (string filename in updateFileName)
  667. {
  668. Console.WriteLine(filename);
  669. }
  670. Console.Write(Environment.NewLine + "是否下载新文件? y/n:");
  671. if (Console.Read() != 'y')
  672. Console.WriteLine("下载取消!");
  673. else
  674. Download();
  675. */
  676. UpdatePlanned = true;
  677. }
  678. return updateInfo;
  679. }
  680. public static bool Update()
  681. {
  682. if (UpdatePlanned)
  683. {
  684. Download();
  685. if (updateFailed.Count == 0)
  686. return true;
  687. }
  688. return false;
  689. }
  690. private static void Download()
  691. {
  692. Tencent_cos_download Downloader = new Tencent_cos_download();
  693. int newFile = 0, updateFile = 0;
  694. int totalnew = newFileName.Count, totalupdate = updateFileName.Count;
  695. filenum = totalnew + totalupdate;
  696. updateFailed.Clear();
  697. if (newFileName.Count > 0 || updateFileName.Count > 0)
  698. {
  699. try
  700. {
  701. foreach (string filename in newFileName)
  702. {
  703. //Console.WriteLine(newFile + 1 + "/" + totalnew + ":开始下载" + filename);
  704. Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
  705. //Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
  706. newFile++;
  707. }
  708. foreach (string filename in updateFileName)
  709. {
  710. //Console.WriteLine(updateFile + 1 + "/" + totalupdate + ":开始下载" + filename);
  711. try
  712. {
  713. File.Delete(System.IO.Path.Combine(@Data.FilePath, filename));
  714. Downloader.download(System.IO.Path.Combine(@Data.FilePath, filename), filename.TrimStart(new char[] { '.', '/' }));
  715. }
  716. catch (System.IO.IOException)
  717. {
  718. updateFailed = updateFailed.Append(filename).ToList();
  719. }
  720. catch
  721. {
  722. if (filename.Substring(filename.Length - 4, 4).Equals(".pdf"))
  723. {
  724. MessageBox.Show($"由于曾经发生过的访问冲突,下载器无法更新{filename}\n"
  725. + $"请手动删除{filename},然后再试一次。");
  726. }
  727. else
  728. MessageBox.Show($"更新{filename}时遇到未知问题,请反馈");
  729. updateFailed = updateFailed.Append(filename).ToList();
  730. }
  731. //Console.WriteLine(filename + "下载完毕!" + Environment.NewLine);
  732. updateFile++;
  733. }
  734. if (updateFailed.Count == 0)
  735. UpdatePlanned = false;
  736. }
  737. catch (CosClientException clientEx)
  738. {
  739. // 请求失败
  740. MessageBox.Show("连接错误:" + clientEx.ToString());
  741. Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
  742. return;
  743. }
  744. catch (CosServerException serverEx)
  745. {
  746. // 请求失败
  747. MessageBox.Show("连接错误:" + serverEx.ToString());
  748. Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
  749. return;
  750. }
  751. catch (Exception)
  752. {
  753. MessageBox.Show("未知错误且无法定位到出错文件,请反馈");
  754. throw;
  755. }
  756. }
  757. else
  758. Console.WriteLine("当前平台已是最新版本!" + Environment.NewLine);
  759. newFileName.Clear();
  760. updateFileName.Clear();
  761. }
  762. public static bool CheckAlreadyDownload() // 检查是否已经下载
  763. {
  764. string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  765. if (!File.Exists(existpath)) // 文件不存在
  766. {
  767. using FileStream fs = new FileStream(existpath, FileMode.Create, FileAccess.ReadWrite);
  768. return false;
  769. }
  770. else // 文件存在
  771. {
  772. using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.Read);
  773. using StreamReader sr = new StreamReader(fs);
  774. string json = sr.ReadToEnd();
  775. if (json == null || json == "")
  776. {
  777. json += @"{""THUAI6""" + ":" + @"""2023""}";
  778. }
  779. var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  780. if (dict == null || !dict.ContainsKey("download") || "false" == dict["download"])
  781. {
  782. return false;
  783. }
  784. else if (dict["download"] == "true")
  785. {
  786. return true;
  787. }
  788. else
  789. {
  790. return false;
  791. }
  792. }
  793. }
  794. public static void DownloadAll() // 下载全部文件
  795. {
  796. string jsonName = "hash.json";
  797. string json;
  798. Tencent_cos_download Downloader = new Tencent_cos_download();
  799. try
  800. {
  801. // 如果json存在就删了重新下
  802. if (File.Exists(System.IO.Path.Combine(Data.FilePath, jsonName)))
  803. {
  804. File.Delete(System.IO.Path.Combine(Data.FilePath, jsonName));
  805. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  806. }
  807. else
  808. {
  809. Downloader.download(System.IO.Path.Combine(Data.FilePath, jsonName), jsonName);
  810. }
  811. }
  812. catch (CosClientException clientEx)
  813. {
  814. // 请求失败
  815. Console.WriteLine("CosClientException: " + clientEx.ToString() + Environment.NewLine);
  816. return;
  817. }
  818. catch (CosServerException serverEx)
  819. {
  820. // 请求失败
  821. Console.WriteLine("CosClientException: " + serverEx.ToString() + Environment.NewLine);
  822. return;
  823. }
  824. using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
  825. json = r.ReadToEnd();
  826. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  827. Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  828. newFileName.Clear();
  829. updateFileName.Clear();
  830. newFileName.Add("THUAI6.tar.gz");
  831. Download();
  832. Stream inStream = null;
  833. Stream gzipStream = null;
  834. TarArchive tarArchive = null;
  835. try
  836. {
  837. using (inStream = File.OpenRead(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz")))
  838. {
  839. using (gzipStream = new GZipInputStream(inStream))
  840. {
  841. tarArchive = TarArchive.CreateInputTarArchive(gzipStream);
  842. tarArchive.ExtractContents(Data.FilePath);
  843. tarArchive.Close();
  844. }
  845. }
  846. }
  847. catch (Exception ex)
  848. {
  849. //出错
  850. }
  851. finally
  852. {
  853. if (null != tarArchive) tarArchive.Close();
  854. if (null != gzipStream) gzipStream.Close();
  855. if (null != inStream) inStream.Close();
  856. }
  857. FileInfo fileInfo = new FileInfo(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz"));
  858. fileInfo.Delete();
  859. string json2;
  860. Dictionary<string, string> dict = new Dictionary<string, string>();
  861. string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  862. using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  863. using (StreamReader r = new StreamReader(fs))
  864. {
  865. json2 = r.ReadToEnd();
  866. if (json2 == null || json2 == "")
  867. {
  868. json2 += @"{""THUAI6""" + ":" + @"""2023""}";
  869. }
  870. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json2);
  871. if (dict == null || !dict.ContainsKey("download"))
  872. {
  873. dict?.Add("download", "true");
  874. }
  875. else
  876. {
  877. dict["download"] = "true";
  878. }
  879. }
  880. using FileStream fs2 = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  881. using StreamWriter sw = new StreamWriter(fs2);
  882. fs2.SetLength(0);
  883. sw.Write(JsonConvert.SerializeObject(dict));
  884. Check(SettingsModel.UsingOS.Win);
  885. Download();
  886. if (File.Exists(Data.FilePath + "/THUAI6/AI.cpp"))
  887. {
  888. FileInfo userCpp = new FileInfo((Data.FilePath + "/THUAI6/AI.cpp").Replace("/", "\\"));
  889. userCpp.MoveTo(Data.FilePath + "/THUAI6/win/CAPI/cpp/API/src/AI.cpp", true);
  890. }
  891. if (File.Exists(Data.FilePath + "/THUAI6/AI.py"))
  892. {
  893. FileInfo userCpp = new FileInfo((Data.FilePath + "/THUAI6/AI.py").Replace("/", "\\"));
  894. userCpp.MoveTo(Data.FilePath + "/THUAI6/win/CAPI/python/PyAPI/AI.cpp", true);
  895. }
  896. }
  897. public static void Change_all_hash(string topDir, Dictionary<string, string> jsonDict) // 更改HASH
  898. {
  899. DirectoryInfo theFolder = new DirectoryInfo(@topDir);
  900. bool ifexist = false;
  901. // 遍历文件
  902. foreach (FileInfo NextFile in theFolder.GetFiles())
  903. {
  904. string filepath = topDir + @"/" + NextFile.Name; // 文件路径
  905. //Console.WriteLine(filepath);
  906. foreach (KeyValuePair<string, string> pair in jsonDict)
  907. {
  908. if (System.IO.Path.Equals(filepath, System.IO.Path.Combine(Data.FilePath, pair.Key).Replace('\\', '/')))
  909. {
  910. ifexist = true;
  911. string MD5 = GetFileMd5Hash(filepath);
  912. jsonDict[pair.Key] = MD5;
  913. }
  914. }
  915. if (!ifexist && NextFile.Name != "hash.json")
  916. {
  917. string MD5 = GetFileMd5Hash(filepath);
  918. string relapath = filepath.Replace(Data.FilePath + '/', string.Empty);
  919. jsonDict.Add(relapath, MD5);
  920. }
  921. ifexist = false;
  922. }
  923. // 遍历文件夹
  924. foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
  925. {
  926. if (System.IO.Path.Equals(NextFolder.FullName, System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder))))
  927. {
  928. foreach (FileInfo NextFile in NextFolder.GetFiles())
  929. {
  930. if (NextFile.Name == "AI.cpp" || NextFile.Name == "AI.py")
  931. {
  932. string MD5 = GetFileMd5Hash(NextFile.FullName);
  933. string relapath = NextFile.FullName.Replace('\\', '/').Replace(Data.FilePath + '/', string.Empty);
  934. jsonDict.Add(relapath, MD5);
  935. }
  936. }
  937. continue; // 如果是选手文件夹就忽略
  938. }
  939. Change_all_hash(NextFolder.FullName.Replace('\\', '/'), jsonDict);
  940. }
  941. }
  942. public static void UpdateHash()
  943. {
  944. while (true)
  945. {
  946. if (Directory.Exists(Data.FilePath))
  947. {
  948. string json;
  949. if (!File.Exists(System.IO.Path.Combine(Data.FilePath, "hash.json")))
  950. {
  951. Console.WriteLine("hash.json文件丢失!即将重新下载该文件!");
  952. GetNewHash();
  953. }
  954. using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, "hash.json")))
  955. json = r.ReadToEnd();
  956. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("/", @"\\");
  957. Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  958. Change_all_hash(Data.FilePath, jsonDict);
  959. OverwriteHash(jsonDict);
  960. break;
  961. }
  962. else
  963. {
  964. Console.WriteLine("读取路径失败!请重新输入文件路径:");
  965. Data.ResetFilepath(Console.ReadLine());
  966. }
  967. }
  968. }
  969. public static int DeleteAll()
  970. {
  971. DirectoryInfo di = new DirectoryInfo(Data.FilePath + "/THUAI6");
  972. //DirectoryInfo player = new DirectoryInfo(System.IO.Path.GetFullPath(System.IO.Path.Combine(Data.FilePath, playerFolder)));
  973. FileInfo[] allfile = di.GetFiles();
  974. try
  975. {
  976. foreach (FileInfo file in allfile)
  977. {
  978. //if(file.Name == "AI.cpp" || file.Name == "AI.py")
  979. //{
  980. // string filename = System.IO.Path.GetFileName(file.FullName);
  981. // file.MoveTo(System.IO.Path.Combine(Data.FilePath, filename));
  982. // continue;
  983. //}
  984. file.Delete();
  985. }
  986. FileInfo userFileCpp = new FileInfo(Data.FilePath + "/THUAI6/win/CAPI/cpp/API/src/AI.cpp");
  987. FileInfo userFilePy = new FileInfo(Data.FilePath + "/THUAI6/win/CAPI/python/PyAPI/AI.py");
  988. userFileCpp.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", System.IO.Path.GetFileName(userFileCpp.FullName)));
  989. userFilePy.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", System.IO.Path.GetFileName(userFilePy.FullName)));
  990. foreach (DirectoryInfo subdi in di.GetDirectories())
  991. {
  992. subdi.Delete(true);
  993. }
  994. FileInfo hashFile = new FileInfo(Data.FilePath + "/hash.json");
  995. hashFile.Delete();
  996. }
  997. catch (UnauthorizedAccessException)
  998. {
  999. Console.WriteLine("权限不足,无法删除!");
  1000. return -2;
  1001. }
  1002. catch (DirectoryNotFoundException)
  1003. {
  1004. Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
  1005. return -3;
  1006. }
  1007. catch (IOException)
  1008. {
  1009. Console.WriteLine("文件已经打开,请关闭后再删除");
  1010. return -1;
  1011. }
  1012. string json2;
  1013. Dictionary<string, string> dict = new Dictionary<string, string>();
  1014. string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1015. using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  1016. using (StreamReader r = new StreamReader(fs))
  1017. {
  1018. json2 = r.ReadToEnd();
  1019. if (json2 == null || json2 == "")
  1020. {
  1021. json2 += @"{""THUAI6""" + ":" + @"""2023""}";
  1022. }
  1023. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json2);
  1024. if (dict == null || !dict.ContainsKey("download"))
  1025. {
  1026. dict?.Add("download", "false");
  1027. }
  1028. else
  1029. {
  1030. dict["download"] = "false";
  1031. }
  1032. }
  1033. using FileStream fs2 = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
  1034. using StreamWriter sw = new StreamWriter(fs2);
  1035. fs2.SetLength(0);
  1036. sw.Write(JsonConvert.SerializeObject(dict));
  1037. sw.Close();
  1038. fs2.Close();
  1039. try
  1040. {
  1041. File.Delete(Data.path);
  1042. }
  1043. catch (UnauthorizedAccessException)
  1044. {
  1045. Console.WriteLine("权限不足,无法删除!");
  1046. return -2;
  1047. }
  1048. catch (DirectoryNotFoundException)
  1049. {
  1050. Console.WriteLine("文件夹没有找到,请检查是否已经手动更改路径");
  1051. return -3;
  1052. }
  1053. catch (IOException)
  1054. {
  1055. Console.WriteLine("文件已经打开,请关闭后再删除");
  1056. return -1;
  1057. }
  1058. return 0;
  1059. }
  1060. public static void OverwriteHash(Dictionary<string, string> jsonDict)
  1061. {
  1062. string Contentjson = JsonConvert.SerializeObject(jsonDict);
  1063. Contentjson = Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/");
  1064. File.WriteAllText(@System.IO.Path.Combine(Data.FilePath, "hash.json"), Contentjson);
  1065. }
  1066. public static int MoveProgram(string newPath)
  1067. {
  1068. DirectoryInfo newdi = new DirectoryInfo(newPath + "/THUAI6");
  1069. DirectoryInfo olddi = new DirectoryInfo(Data.FilePath + "/THUAI6");
  1070. try
  1071. {
  1072. if (!Directory.Exists(newPath + "/THUAI6"))
  1073. Directory.CreateDirectory(newPath + "/THUAI6");
  1074. foreach (DirectoryInfo direct in olddi.GetDirectories())
  1075. {
  1076. direct.MoveTo(System.IO.Path.Combine(newPath + "/THUAI6", direct.Name));
  1077. }
  1078. foreach (FileInfo file in olddi.GetFiles())
  1079. {
  1080. file.MoveTo(System.IO.Path.Combine(newPath + "/THUAI6", file.Name));
  1081. }
  1082. olddi.Delete();
  1083. }
  1084. catch (DirectoryNotFoundException)
  1085. {
  1086. Console.WriteLine("原路径未找到!请检查文件是否损坏");
  1087. if (newdi.GetDirectories().Length != 0)
  1088. {
  1089. foreach (DirectoryInfo newdirect in newdi.GetDirectories())
  1090. {
  1091. newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", newdirect.Name));
  1092. }
  1093. }
  1094. if (newdi.GetFiles().Length != 0)
  1095. {
  1096. foreach (FileInfo file in newdi.GetFiles())
  1097. {
  1098. file.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", file.Name));
  1099. }
  1100. }
  1101. Console.WriteLine("移动失败!");
  1102. if (newdi.Exists)
  1103. newdi.Delete();
  1104. return -2;
  1105. }
  1106. catch (IOException)
  1107. {
  1108. Console.WriteLine("文件已打开或者目标路径下有同名文件!");
  1109. if (newdi.GetDirectories().Length != 0)
  1110. {
  1111. foreach (DirectoryInfo newdirect in newdi.GetDirectories())
  1112. {
  1113. newdirect.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", newdirect.Name));
  1114. }
  1115. }
  1116. if (newdi.GetFiles().Length != 0)
  1117. {
  1118. foreach (FileInfo file in newdi.GetFiles())
  1119. {
  1120. file.MoveTo(System.IO.Path.Combine(Data.FilePath + "/THUAI6", file.Name));
  1121. }
  1122. }
  1123. if (newdi.Exists)
  1124. newdi.Delete();
  1125. Console.WriteLine("移动失败!");
  1126. return -1;
  1127. }
  1128. FileInfo hashFile = new FileInfo(Data.FilePath + "/hash.json");
  1129. hashFile.MoveTo(newPath + "/hash.json");
  1130. Data.ResetFilepath(newPath);
  1131. Console.WriteLine("更改路径成功!");
  1132. return 0;
  1133. }
  1134. public static async Task main(string[] args)
  1135. {
  1136. var client = new HttpClient();
  1137. var web = new WebConnect.Web();
  1138. Data date = new Data("");
  1139. while (true)
  1140. {
  1141. Console.WriteLine($"1. 更新hash.json 2. 检查更新 3.下载{ProgramName} 4.删除{ProgramName} 5.启动进程 6.移动{ProgramName}到其它路径");
  1142. string choose = Console.ReadLine();
  1143. if (choose == "1")
  1144. {
  1145. if (!CheckAlreadyDownload())
  1146. {
  1147. Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
  1148. continue;
  1149. }
  1150. UpdateHash();
  1151. }
  1152. else if (choose == "2")
  1153. {
  1154. if (!CheckAlreadyDownload())
  1155. {
  1156. Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
  1157. continue;
  1158. }
  1159. while (true)
  1160. {
  1161. if (Data.FilePath != null && Directory.Exists(Data.FilePath))
  1162. {
  1163. Check(SettingsModel.UsingOS.Win);
  1164. break;
  1165. }
  1166. else
  1167. {
  1168. Console.WriteLine("读取路径失败!请重新输入文件路径:");
  1169. Data.ResetFilepath(Console.ReadLine());
  1170. }
  1171. }
  1172. }
  1173. else if (choose == "3")
  1174. {
  1175. if (CheckAlreadyDownload())
  1176. {
  1177. Console.WriteLine($"已经将{ProgramName}下载到{Data.FilePath}!若要重新下载请先完成删除操作!");
  1178. }
  1179. else
  1180. {
  1181. string newpath;
  1182. Console.WriteLine("请输入下载路径:");
  1183. newpath = Console.ReadLine();
  1184. Data.ResetFilepath(newpath);
  1185. DownloadAll();
  1186. }
  1187. }
  1188. else if (choose == "4")
  1189. {
  1190. DeleteAll();
  1191. }
  1192. else if (choose == "5")
  1193. {
  1194. if (CheckAlreadyDownload())
  1195. {
  1196. Process.Start(System.IO.Path.Combine(Data.FilePath, startName));
  1197. }
  1198. else
  1199. {
  1200. Console.WriteLine($"未下载{ProgramName},请先执行下载操作!");
  1201. }
  1202. }
  1203. else if (choose == "6")
  1204. {
  1205. string newPath;
  1206. newPath = Console.ReadLine();
  1207. MoveProgram(newPath);
  1208. }
  1209. else if (choose == "7")
  1210. {
  1211. Console.WriteLine("请输入email:");
  1212. string username = Console.ReadLine();
  1213. Console.WriteLine("请输入密码:");
  1214. string password = Console.ReadLine();
  1215. await web.LoginToEEsast(client, username, password);
  1216. }
  1217. else if (choose == "8")
  1218. {
  1219. await web.UserDetails(client);
  1220. }
  1221. else if (choose == "9")
  1222. {
  1223. await web.UploadFiles(client, "", "", "");
  1224. }
  1225. else if (choose == "exit")
  1226. {
  1227. return;
  1228. }
  1229. }
  1230. }
  1231. public static int CheckSelfVersion()
  1232. {
  1233. string keyHead = "Installer/";
  1234. Tencent_cos_download downloader = new Tencent_cos_download();
  1235. string hashName = "installerHash.json";
  1236. string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
  1237. int result = 0;
  1238. try
  1239. {
  1240. if (File.Exists(System.IO.Path.Combine(dir, hashName)))
  1241. File.Delete(System.IO.Path.Combine(dir, hashName));
  1242. downloader.download(System.IO.Path.Combine(dir, hashName), hashName);
  1243. }
  1244. catch
  1245. {
  1246. return -1;
  1247. }
  1248. string json;
  1249. using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, hashName)))
  1250. json = r.ReadToEnd();
  1251. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  1252. Dictionary<string, string> jsonDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  1253. string md5 = "";
  1254. List<string> awaitUpdate = new List<string>();
  1255. if (jsonDict != null)
  1256. {
  1257. foreach (KeyValuePair<string, string> pair in jsonDict)
  1258. {
  1259. md5 = GetFileMd5Hash(System.IO.Path.Combine(dir, pair.Key));
  1260. if (md5.Length == 0) // 文档不存在
  1261. {
  1262. downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key);
  1263. }
  1264. else if (md5.Equals("conflict"))
  1265. {
  1266. MessageBox.Show($"检查{pair.Key}更新时遇到问题,请反馈", "读取出错", MessageBoxButton.OK, MessageBoxImage.Error);
  1267. }
  1268. else if (md5 != pair.Value) // MD5不匹配
  1269. {
  1270. if (pair.Key.Substring(0, 12).Equals("InstallerUpd"))
  1271. {
  1272. File.Delete(System.IO.Path.Combine(dir, pair.Key));
  1273. downloader.download(System.IO.Path.Combine(dir, pair.Key), keyHead + pair.Key);
  1274. }
  1275. else
  1276. {
  1277. result = 1;
  1278. awaitUpdate = awaitUpdate.Append(pair.Key).ToList();
  1279. }
  1280. }
  1281. }
  1282. }
  1283. else
  1284. return -1;
  1285. string Contentjson = JsonConvert.SerializeObject(awaitUpdate);
  1286. Contentjson = Contentjson.Replace("\r", String.Empty).Replace("\n", String.Empty).Replace(@"\\", "/");
  1287. File.WriteAllText(@System.IO.Path.Combine(dir, "updateList.json"), Contentjson);
  1288. return result;
  1289. }
  1290. static public bool SelfUpdateDismissed()
  1291. {
  1292. string json;
  1293. string dir = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
  1294. if (!File.Exists(System.IO.Path.Combine(dir, "updateList.json")))
  1295. return false;
  1296. using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, "updateList.json")))
  1297. json = r.ReadToEnd();
  1298. json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
  1299. List<string> jsonList;
  1300. if (json != null)
  1301. jsonList = JsonConvert.DeserializeObject<List<string>>(json);
  1302. else
  1303. return false;
  1304. if (jsonList != null && jsonList.Contains("Dismiss"))
  1305. {
  1306. listJsonClear(System.IO.Path.Combine(dir, "updateList.json"));
  1307. return true;
  1308. }
  1309. return false;
  1310. }
  1311. static private void listJsonClear(string directory)
  1312. {
  1313. List<string> list = new List<string>();
  1314. list.Add("None");
  1315. StreamWriter sw = new StreamWriter(directory, false);
  1316. sw.WriteLine(JsonConvert.SerializeObject(list));
  1317. sw.Close();
  1318. }
  1319. }
  1320. }
  1321. }
  1322. namespace WebConnect
  1323. {
  1324. class Web
  1325. {
  1326. public enum language { cpp, py };
  1327. public static string logintoken = "";
  1328. async public Task<int> LoginToEEsast(HttpClient client, string useremail, string password)
  1329. {
  1330. string token = "";
  1331. try
  1332. {
  1333. using (var response = await client.PostAsync("https://api.eesast.com/users/login", JsonContent.Create(new
  1334. {
  1335. email = useremail,
  1336. password = password,
  1337. })))
  1338. {
  1339. switch (response.StatusCode)
  1340. {
  1341. case System.Net.HttpStatusCode.OK:
  1342. //Console.WriteLine("Success login");
  1343. token = (System.Text.Json.JsonSerializer.Deserialize(await response.Content.ReadAsStreamAsync(), typeof(LoginResponse), new JsonSerializerOptions()
  1344. {
  1345. PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
  1346. }) as LoginResponse)
  1347. ?.Token ??
  1348. throw new Exception("no token!");
  1349. logintoken = token;
  1350. SaveToken();
  1351. var info = JsonConvert.DeserializeObject<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
  1352. Downloader.UserInfo._id = info["_id"];
  1353. Downloader.UserInfo.email = info["email"];
  1354. break;
  1355. default:
  1356. int code = ((int)response.StatusCode);
  1357. //Console.WriteLine(code);
  1358. if (code == 401)
  1359. {
  1360. //Console.WriteLine("邮箱或密码错误!");
  1361. return -1;
  1362. }
  1363. break;
  1364. }
  1365. return 0;
  1366. }
  1367. }
  1368. catch
  1369. {
  1370. return -2;
  1371. }
  1372. }
  1373. /// <summary>
  1374. ///
  1375. /// </summary>
  1376. /// <param name="client">http client</param>
  1377. /// <param name="tarfile">代码源位置</param>
  1378. /// <param name="type">编程语言,格式为"cpp"或"python"</param>
  1379. /// <param name="plr">第x位玩家,格式为"player_x"</param>
  1380. /// <returns>-1:tokenFail;-2:FileNotExist;-3:CosFail;-4:loginTimeout;-5:Fail;-6:ReadFileFail;-7:networkError</returns>
  1381. async public Task<int> UploadFiles(HttpClient client, string tarfile, string type, string plr) //用来上传文件
  1382. {
  1383. if (!ReadToken()) //读取token失败
  1384. {
  1385. return -1;
  1386. }
  1387. try
  1388. {
  1389. string content;
  1390. client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken);
  1391. if (!File.Exists(tarfile))
  1392. {
  1393. //Console.WriteLine("文件不存在!");
  1394. return -2;
  1395. }
  1396. using FileStream fs = new FileStream(tarfile, FileMode.Open, FileAccess.Read);
  1397. using StreamReader sr = new StreamReader(fs);
  1398. content = sr.ReadToEnd();
  1399. string targetUrl = $"https://api.eesast.com/static/player?team_id={await GetTeamId()}";
  1400. using (var response = await client.GetAsync(targetUrl))
  1401. {
  1402. switch (response.StatusCode)
  1403. {
  1404. case System.Net.HttpStatusCode.OK:
  1405. var res = JsonConvert.DeserializeObject<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
  1406. string appid = "1255334966"; // 设置腾讯云账户的账户标识(APPID)
  1407. string region = "ap-beijing"; // 设置一个默认的存储桶地域
  1408. CosXmlConfig config = new CosXmlConfig.Builder()
  1409. .IsHttps(true) // 设置默认 HTTPS 请求
  1410. .SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
  1411. .SetRegion(region) // 设置一个默认的存储桶地域
  1412. .SetDebugLog(true) // 显示日志
  1413. .Build(); // 创建 CosXmlConfig 对象
  1414. string tmpSecretId = res["TmpSecretId"]; //"临时密钥 SecretId";
  1415. string tmpSecretKey = res["TmpSecretKey"]; //"临时密钥 SecretKey";
  1416. string tmpToken = res["SecurityToken"]; //"临时密钥 token";
  1417. long tmpExpiredTime = Convert.ToInt64(res["ExpiredTime"]);//临时密钥有效截止时间,精确到秒
  1418. QCloudCredentialProvider cosCredentialProvider = new DefaultSessionQCloudCredentialProvider(
  1419. tmpSecretId, tmpSecretKey, tmpExpiredTime, tmpToken
  1420. );
  1421. // 初始化 CosXmlServer
  1422. CosXmlServer cosXml = new CosXmlServer(config, cosCredentialProvider);
  1423. // 初始化 TransferConfig
  1424. TransferConfig transferConfig = new TransferConfig();
  1425. // 初始化 TransferManager
  1426. TransferManager transferManager = new TransferManager(cosXml, transferConfig);
  1427. string bucket = "eesast-1255334966"; //存储桶,格式:BucketName-APPID
  1428. string cosPath = $"/THUAI6/{GetTeamId()}/{type}/{plr}"; //对象在存储桶中的位置标识符,即称对象键
  1429. string srcPath = tarfile;//本地文件绝对路径
  1430. // 上传对象
  1431. COSXMLUploadTask uploadTask = new COSXMLUploadTask(bucket, cosPath);
  1432. uploadTask.SetSrcPath(srcPath);
  1433. uploadTask.progressCallback = delegate (long completed, long total)
  1434. {
  1435. //Console.WriteLine(string.Format("progress = {0:##.##}%", completed * 100.0 / total));
  1436. };
  1437. try
  1438. {
  1439. COSXMLUploadTask.UploadTaskResult result = await transferManager.UploadAsync(uploadTask);
  1440. //Console.WriteLine(result.GetResultInfo());
  1441. string eTag = result.eTag;
  1442. //到这里应该是成功了,但是因为我没有试过,也不知道具体情况,可能还要根据result的内容判断
  1443. }
  1444. catch (Exception)
  1445. {
  1446. return -3;
  1447. }
  1448. break;
  1449. case System.Net.HttpStatusCode.Unauthorized:
  1450. //Console.WriteLine("您未登录或登录过期,请先登录");
  1451. return -4;
  1452. default:
  1453. //Console.WriteLine("上传失败!");
  1454. return -5;
  1455. }
  1456. }
  1457. }
  1458. catch (IOException)
  1459. {
  1460. //Console.WriteLine("文件读取错误!请检查文件是否被其它应用占用!");
  1461. return -6;
  1462. }
  1463. catch
  1464. {
  1465. //Console.WriteLine("请求错误!请检查网络连接!");
  1466. return -7;
  1467. }
  1468. return 0;
  1469. }
  1470. async public Task UserDetails(HttpClient client) // 用来测试访问网站
  1471. {
  1472. if (!ReadToken()) // 读取token失败
  1473. {
  1474. return;
  1475. }
  1476. try
  1477. {
  1478. client.DefaultRequestHeaders.Authorization = new("Bearer", logintoken);
  1479. Console.WriteLine(logintoken);
  1480. using (var response = await client.GetAsync("https://api.eesast.com/application/info")) // JsonContent.Create(new
  1481. //{
  1482. //})))
  1483. {
  1484. switch (response.StatusCode)
  1485. {
  1486. case System.Net.HttpStatusCode.OK:
  1487. Console.WriteLine("Require OK");
  1488. Console.WriteLine(await response.Content.ReadAsStringAsync());
  1489. break;
  1490. default:
  1491. int code = ((int)response.StatusCode);
  1492. if (code == 401)
  1493. {
  1494. Console.WriteLine("您未登录或登录过期,请先登录");
  1495. }
  1496. return;
  1497. }
  1498. }
  1499. }
  1500. catch
  1501. {
  1502. Console.WriteLine("请求错误!请检查网络连接!");
  1503. }
  1504. }
  1505. public void SaveToken() // 保存token
  1506. {
  1507. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1508. try
  1509. {
  1510. string json;
  1511. Dictionary<string, string> dict = new Dictionary<string, string>();
  1512. using FileStream fs = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
  1513. using (StreamReader r = new StreamReader(fs))
  1514. {
  1515. json = r.ReadToEnd();
  1516. if (json == null || json == "")
  1517. {
  1518. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1519. }
  1520. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  1521. if (dict.ContainsKey("token"))
  1522. {
  1523. dict.Remove("token");
  1524. }
  1525. dict?.Add("token", logintoken);
  1526. }
  1527. using FileStream fs2 = new FileStream(savepath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
  1528. using StreamWriter sw = new StreamWriter(fs2);
  1529. fs2.SetLength(0);
  1530. sw.Write(JsonConvert.SerializeObject(dict)); //将token写入文件
  1531. }
  1532. catch (DirectoryNotFoundException)
  1533. {
  1534. Console.WriteLine("保存token时未找到下载器地址!请检查下载器是否被移动!");
  1535. }
  1536. catch (PathTooLongException)
  1537. {
  1538. Console.WriteLine("下载器的路径名太长!请尝试移动下载器!");
  1539. }
  1540. catch (ArgumentNullException)
  1541. {
  1542. Console.WriteLine("下载器路径初始化失败!");
  1543. }
  1544. catch (IOException)
  1545. {
  1546. Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!");
  1547. }
  1548. }
  1549. public static int WriteJson(string key, string data)
  1550. {
  1551. try
  1552. {
  1553. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1554. FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite);
  1555. StreamReader sr = new StreamReader(fs);
  1556. string json = sr.ReadToEnd();
  1557. if (json == null || json == "")
  1558. {
  1559. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1560. }
  1561. Dictionary<string, string> dict = new Dictionary<string, string>();
  1562. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  1563. if (!dict.ContainsKey(key))
  1564. {
  1565. dict.Add(key, data);
  1566. }
  1567. else
  1568. {
  1569. dict[key] = data;
  1570. }
  1571. sr.Close();
  1572. fs.Close();
  1573. FileStream fs2 = new FileStream(savepath, FileMode.Open, FileAccess.ReadWrite);
  1574. StreamWriter sw = new StreamWriter(fs2);
  1575. sw.WriteLine(JsonConvert.SerializeObject(dict));
  1576. sw.Close();
  1577. fs2.Close();
  1578. return 0;//成功
  1579. }
  1580. catch
  1581. {
  1582. return -1;//失败
  1583. }
  1584. }
  1585. public static string ReadJson(string key)
  1586. {
  1587. try
  1588. {
  1589. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1590. FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read);
  1591. StreamReader sr = new StreamReader(fs);
  1592. string json = sr.ReadToEnd();
  1593. Dictionary<string, string> dict = new Dictionary<string, string>();
  1594. if (json == null || json == "")
  1595. {
  1596. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1597. }
  1598. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  1599. fs.Close();
  1600. sr.Close();
  1601. return dict[key];
  1602. }
  1603. catch
  1604. {
  1605. return null; //文件不存在或者已被占用
  1606. }
  1607. }
  1608. public bool ReadToken() // 读取token
  1609. {
  1610. try
  1611. {
  1612. string json;
  1613. Dictionary<string, string> dict = new Dictionary<string, string>();
  1614. string savepath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
  1615. using FileStream fs = new FileStream(savepath, FileMode.Open, FileAccess.Read);
  1616. using StreamReader sr = new StreamReader(fs);
  1617. json = sr.ReadToEnd();
  1618. if (json == null || json == "")
  1619. {
  1620. json += @"{""THUAI6""" + ":" + @"""2023""}";
  1621. }
  1622. dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
  1623. if (!dict.ContainsKey("token"))
  1624. {
  1625. return false;
  1626. }
  1627. else
  1628. {
  1629. logintoken = dict["token"];
  1630. return true;
  1631. }
  1632. }
  1633. catch (DirectoryNotFoundException)
  1634. {
  1635. Console.WriteLine("读取token时未找到下载器地址!请检查下载器是否被移动!");
  1636. return false;
  1637. }
  1638. catch (FileNotFoundException)
  1639. {
  1640. //没有登陆
  1641. Console.WriteLine("请先登录!");
  1642. return false;
  1643. }
  1644. catch (PathTooLongException)
  1645. {
  1646. Console.WriteLine("下载器的路径名太长!请尝试移动下载器!");
  1647. return false;
  1648. }
  1649. catch (ArgumentNullException)
  1650. {
  1651. Console.WriteLine("下载器路径初始化失败!");
  1652. return false;
  1653. }
  1654. catch (IOException)
  1655. {
  1656. Console.WriteLine("写入token.dat发生冲突!请检查token.dat是否被其它程序占用!");
  1657. return false;
  1658. }
  1659. }
  1660. async public Task<string> GetTeamId()
  1661. {
  1662. var client = new HttpClient();
  1663. var request = new HttpRequestMessage(HttpMethod.Post, "https://api.eesast.com/dev/v1/graphql");
  1664. request.Headers.Add("x-hasura-admin-secret", "hasuraDevAdminSecret");
  1665. //var content = new StringContent($@"
  1666. // {{
  1667. // ""query"": ""query MyQuery {{contest_team_member(where: {{user_id: {{_eq: \""{Downloader.UserInfo._id}\""}}}}) {{ team_id }}}}"",
  1668. // ""variables"": {{}},
  1669. // }}", null, "application/json");
  1670. var content = new StringContent("{\"query\":\"query MyQuery {\\r\\n contest_team_member(where: {user_id: {_eq: \\\"" + Downloader.UserInfo._id + "\\\"}}) {\\r\\n team_id\\r\\n }\\r\\n}\",\"variables\":{}}", null, "application/json");
  1671. request.Content = content;
  1672. var response = await client.SendAsync(request);
  1673. response.EnsureSuccessStatusCode();
  1674. var info = await response.Content.ReadAsStringAsync();
  1675. var s1 = JsonConvert.DeserializeObject<Dictionary<string, object>>(info)["data"];
  1676. var s2 = JsonConvert.DeserializeObject<Dictionary<string, List<object>>>(s1.ToString())["contest_team_member"];
  1677. var sres = JsonConvert.DeserializeObject<Dictionary<string, string>>(s2[0].ToString())["team_id"];
  1678. return sres;
  1679. }
  1680. async public Task<string> GetUserId(string learnNumber)
  1681. {
  1682. var client = new HttpClient();
  1683. var request = new HttpRequestMessage(HttpMethod.Post, "https://api.eesast.com/dev/v1/graphql");
  1684. request.Headers.Add("x-hasura-admin-secret", "hasuraDevAdminSecret");
  1685. var content = new StringContent("{\"query\":\"query MyQuery {\r\n user(where: {id: {_eq: \""
  1686. + learnNumber + "\"}}) {\r\n _id\r\n }\r\n}\r\n\",\"variables\":{}}", null, "application/json");
  1687. request.Content = content;
  1688. var response = await client.SendAsync(request);
  1689. response.EnsureSuccessStatusCode();
  1690. return await response.Content.ReadAsStringAsync();
  1691. }
  1692. }
  1693. [Serializable]
  1694. record LoginResponse
  1695. {
  1696. // Map `Token` to `token` when serializing
  1697. public string Token { get; set; } = "";
  1698. }
  1699. }