Gamecraft-Discord connection. It can send and receive messages in a specific channel.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
6.2KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.Http;
  8. using System.Net.Mime;
  9. using System.Reflection;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using Discord;
  13. using Discord.WebSocket;
  14. using GamecraftModdingAPI.Utility;
  15. using Newtonsoft.Json;
  16. using Newtonsoft.Json.Linq;
  17. using RobocraftX.Common;
  18. using RobocraftX.Common.Input;
  19. using RobocraftX.Common.Utilities;
  20. using RobocraftX.SimulationModeState;
  21. using RobocraftX.StateSync;
  22. using Svelto.ECS;
  23. using Svelto.ECS.Experimental;
  24. using Unity.Jobs;
  25. using UnityEngine.Diagnostics;
  26. using uREPL;
  27. namespace GCDC
  28. {
  29. public class TextBlockUpdateEngine : IDeterministicSim, IInitializeOnBuildStart, IApiEngine
  30. {
  31. private string _token;
  32. private bool _running;
  33. private Thread _rect;
  34. public void Ready()
  35. {
  36. if (!RuntimeCommands.HasRegistered("dc"))
  37. RuntimeCommands.Register<string>("dc", SendMessage);
  38. if (!RuntimeCommands.HasRegistered("dcsetup"))
  39. RuntimeCommands.Register<string>("dcsetup", Setup,
  40. "Initial setup for GCDC. The argument is the channel ID first.");
  41. if (File.Exists("gcdc.json"))
  42. {
  43. var jo = JObject.Load(new JsonTextReader(File.OpenText("gcdc.json")));
  44. _token = jo["token"]?.Value<string>();
  45. }
  46. if (_token != null)
  47. Start();
  48. }
  49. public void Setup(string tokenOrChannel)
  50. {
  51. if (!tokenOrChannel.Contains("-"))
  52. {
  53. if (!int.TryParse(tokenOrChannel, out _))
  54. {
  55. Log.Error("Bad format for channel ID.");
  56. return;
  57. }
  58. Process.Start(
  59. "https://discordapp.com/oauth2/authorize?client_id=680138144812892371&redirect_uri=https%3A%2F%2Fgcdc.herokuapp.com%2Fapi%2Fusers%2Fregister&response_type=code&scope=identify&state=" +
  60. tokenOrChannel);
  61. Log.Output(
  62. "Please authorize the GCDC app on the page that should open. This connection is only used to avoid account spam and to display your Discord name.");
  63. }
  64. else
  65. {
  66. _token = tokenOrChannel;
  67. try
  68. {
  69. if (JObject.Parse(WebUtils.Request("users/get?token=" + tokenOrChannel))["response"].Value<string>() == "OK")
  70. {
  71. var jo = new JObject {["token"] = tokenOrChannel};
  72. File.WriteAllText("gcdc.json", jo.ToString());
  73. Start();
  74. Log.Output(
  75. "Successfully logged in. You can now use a text block named Discord and the dc command.");
  76. }
  77. else
  78. Log.Error("Failed to verify login. Please try again.");
  79. }
  80. catch (Exception e)
  81. {
  82. Log.Error("Failed to verify login. Please try again. (Error logged.)");
  83. Console.WriteLine(e);
  84. }
  85. }
  86. }
  87. public void SendMessage(string message)
  88. {
  89. if (!_running)
  90. {
  91. Log.Error("Run dcsetup first.");
  92. return;
  93. }
  94. try
  95. {
  96. var parameters = "token=" + _token + "&message=" + message;
  97. var resp = JObject.Parse(WebUtils.Request("messages/send?" + parameters, ""));
  98. if (resp["response"]
  99. .Value<string>() == "OK")
  100. {
  101. AddMessage("<nobr><" + resp["username"] + "> " + message);
  102. Log.Output("Message sent");
  103. }
  104. else
  105. Log.Error("Failed to send message");
  106. }
  107. catch (Exception e)
  108. {
  109. Log.Error("Failed to send message (error logged).");
  110. Console.WriteLine(e);
  111. }
  112. }
  113. public void Start()
  114. {
  115. if (_running) return;
  116. _running = true;
  117. _rect = new Thread(() =>
  118. {
  119. Console.WriteLine("Starting DC receiver thread...");
  120. while (_running)
  121. {
  122. try
  123. {
  124. string resp = WebUtils.Request("messages/get?token=" + _token);
  125. var jo = JObject.Parse(resp);
  126. AddMessage("<nobr><" + jo["username"] + "> " + jo["message"]);
  127. }
  128. catch (WebException)
  129. {
  130. // ignored
  131. }
  132. }
  133. }) {Name = "DC Receiver Thread"};
  134. _rect.Start();
  135. }
  136. public EntitiesDB entitiesDB { get; set; }
  137. public string name { get; } = "GCDC-TextUpdate";
  138. private volatile Queue<string> messages = new Queue<string>();
  139. private volatile bool updatedTextBlock;
  140. public JobHandle SimulatePhysicsStep(
  141. in float deltaTime,
  142. in PhysicsUtility utility,
  143. in PlayerInput[] playerInputs) //Gamecraft.Blocks.ConsoleBlock.dll
  144. {
  145. if (updatedTextBlock)
  146. return new JobHandle();
  147. var txt = messages.Count > 0 ? messages.Aggregate((current, msg) => current + "\n" + msg) : "<No messages yet>";
  148. RuntimeCommands.Call("ChangeTextBlockCommand", "Discord", txt);
  149. updatedTextBlock = true;
  150. return new JobHandle();
  151. }
  152. public void AddMessage(string message)
  153. {
  154. messages.Enqueue(message);
  155. if (messages.Count > 10)
  156. messages.Dequeue();
  157. updatedTextBlock = false;
  158. }
  159. public JobHandle OnInitializeBuildMode()
  160. {
  161. updatedTextBlock = false; //Update text block
  162. return new JobHandle();
  163. }
  164. public void Dispose()
  165. {
  166. _running = false;
  167. _rect.Interrupt();
  168. }
  169. public string Name { get; } = "GCDCEngine";
  170. }
  171. }