Files
tgstation-server/_discord_provider_8cs_source.html

1314 lines
256 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs Source File</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectalign">
<div id="projectname">tgstation-server<span id="projectnumber">&#160;6.19.3</span>
</div>
<div id="projectbrief">The /tg/station 13 server suite</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.8 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search/",'.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(document).ready(function() { init_codefold(0); });
/* @license-end */
</script>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<div id="MSearchResults">
<div class="SRPage">
<div id="SRIndex">
<div id="SRResults"></div>
<div class="SRStatus" id="Loading">Loading...</div>
<div class="SRStatus" id="Searching">Searching...</div>
<div class="SRStatus" id="NoMatches">No Matches</div>
</div>
</div>
</div>
</div>
<div id="nav-path" class="navpath">
<ul>
<li class="navelem"><a class="el" href="dir_68267d1309a1af8e8297ef4c3efbcdba.html">src</a></li><li class="navelem"><a class="el" href="dir_34761767c1c3cd212f9d2f80ea0828a8.html">Tgstation.Server.Host</a></li><li class="navelem"><a class="el" href="dir_7a3fd032a1362a6005a1fc9227a8dd86.html">Components</a></li><li class="navelem"><a class="el" href="dir_a44a562b5a12ef1c8495ac1a63e915ea.html">Chat</a></li><li class="navelem"><a class="el" href="dir_5e0b464d3b4be546c63c5188ffeb96e4.html">Providers</a></li> </ul>
</div>
</div><!-- top -->
<div class="header">
<div class="headertitle"><div class="title">DiscordProvider.cs</div></div>
</div><!--header-->
<div class="contents">
<a href="_discord_provider_8cs.html">Go to the documentation of this file.</a><div class="fragment"><div class="line"><a id="l00001" name="l00001"></a><span class="lineno"> 1</span><span class="keyword">using </span>System;</div>
<div class="line"><a id="l00002" name="l00002"></a><span class="lineno"> 2</span><span class="keyword">using </span>System.Collections.Concurrent;</div>
<div class="line"><a id="l00003" name="l00003"></a><span class="lineno"> 3</span><span class="keyword">using </span>System.Collections.Generic;</div>
<div class="line"><a id="l00004" name="l00004"></a><span class="lineno"> 4</span><span class="keyword">using </span>System.Drawing;</div>
<div class="line"><a id="l00005" name="l00005"></a><span class="lineno"> 5</span><span class="keyword">using </span>System.Globalization;</div>
<div class="line"><a id="l00006" name="l00006"></a><span class="lineno"> 6</span><span class="keyword">using </span>System.Linq;</div>
<div class="line"><a id="l00007" name="l00007"></a><span class="lineno"> 7</span><span class="keyword">using </span>System.Threading;</div>
<div class="line"><a id="l00008" name="l00008"></a><span class="lineno"> 8</span><span class="keyword">using </span>System.Threading.Tasks;</div>
<div class="line"><a id="l00009" name="l00009"></a><span class="lineno"> 9</span> </div>
<div class="line"><a id="l00010" name="l00010"></a><span class="lineno"> 10</span><span class="keyword">using </span>Microsoft.Extensions.DependencyInjection;</div>
<div class="line"><a id="l00011" name="l00011"></a><span class="lineno"> 11</span><span class="keyword">using </span>Microsoft.Extensions.Logging;</div>
<div class="line"><a id="l00012" name="l00012"></a><span class="lineno"> 12</span><span class="keyword">using </span>Microsoft.Extensions.Options;</div>
<div class="line"><a id="l00013" name="l00013"></a><span class="lineno"> 13</span> </div>
<div class="line"><a id="l00014" name="l00014"></a><span class="lineno"> 14</span><span class="keyword">using </span>Remora.Discord.API.Abstractions.Gateway.Commands;</div>
<div class="line"><a id="l00015" name="l00015"></a><span class="lineno"> 15</span><span class="keyword">using </span>Remora.Discord.API.Abstractions.Gateway.Events;</div>
<div class="line"><a id="l00016" name="l00016"></a><span class="lineno"> 16</span><span class="keyword">using </span>Remora.Discord.API.Abstractions.Objects;</div>
<div class="line"><a id="l00017" name="l00017"></a><span class="lineno"> 17</span><span class="keyword">using </span>Remora.Discord.API.Abstractions.Rest;</div>
<div class="line"><a id="l00018" name="l00018"></a><span class="lineno"> 18</span><span class="keyword">using </span>Remora.Discord.API.Abstractions.Results;</div>
<div class="line"><a id="l00019" name="l00019"></a><span class="lineno"> 19</span><span class="keyword">using </span>Remora.Discord.API.Objects;</div>
<div class="line"><a id="l00020" name="l00020"></a><span class="lineno"> 20</span><span class="keyword">using </span>Remora.Discord.Gateway;</div>
<div class="line"><a id="l00021" name="l00021"></a><span class="lineno"> 21</span><span class="keyword">using </span>Remora.Discord.Gateway.Extensions;</div>
<div class="line"><a id="l00022" name="l00022"></a><span class="lineno"> 22</span><span class="keyword">using </span>Remora.Rest.Core;</div>
<div class="line"><a id="l00023" name="l00023"></a><span class="lineno"> 23</span><span class="keyword">using </span>Remora.Rest.Results;</div>
<div class="line"><a id="l00024" name="l00024"></a><span class="lineno"> 24</span><span class="keyword">using </span>Remora.Results;</div>
<div class="line"><a id="l00025" name="l00025"></a><span class="lineno"> 25</span> </div>
<div class="line"><a id="l00026" name="l00026"></a><span class="lineno"> 26</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html">Tgstation.Server.Api.Models</a>;</div>
<div class="line"><a id="l00027" name="l00027"></a><span class="lineno"> 27</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal.html">Tgstation.Server.Api.Models.Internal</a>;</div>
<div class="line"><a id="l00028" name="l00028"></a><span class="lineno"> 28</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_common_1_1_extensions.html">Tgstation.Server.Common.Extensions</a>;</div>
<div class="line"><a id="l00029" name="l00029"></a><span class="lineno"> 29</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop.html">Tgstation.Server.Host.Components.Interop</a>;</div>
<div class="line"><a id="l00030" name="l00030"></a><span class="lineno"> 30</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_configuration.html">Tgstation.Server.Host.Configuration</a>;</div>
<div class="line"><a id="l00031" name="l00031"></a><span class="lineno"> 31</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_extensions.html">Tgstation.Server.Host.Extensions</a>;</div>
<div class="line"><a id="l00032" name="l00032"></a><span class="lineno"> 32</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_jobs.html">Tgstation.Server.Host.Jobs</a>;</div>
<div class="line"><a id="l00033" name="l00033"></a><span class="lineno"> 33</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_models.html">Tgstation.Server.Host.Models</a>;</div>
<div class="line"><a id="l00034" name="l00034"></a><span class="lineno"> 34</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_system.html">Tgstation.Server.Host.System</a>;</div>
<div class="line"><a id="l00035" name="l00035"></a><span class="lineno"> 35</span><span class="keyword">using </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_utils.html">Tgstation.Server.Host.Utils</a>;</div>
<div class="line"><a id="l00036" name="l00036"></a><span class="lineno"> 36</span> </div>
<div class="line"><a id="l00037" name="l00037"></a><span class="lineno"> 37</span><span class="keyword">namespace </span><a class="code hl_namespace" href="namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers.html">Tgstation.Server.Host.Components.Chat.Providers</a></div>
<div class="line"><a id="l00038" name="l00038"></a><span class="lineno"> 38</span>{</div>
<div class="line"><a id="l00042" name="l00042"></a><span class="lineno"> 42</span><span class="preprocessor"> #pragma warning disable CA1506</span></div>
<div class="foldopen" id="foldopen00043" data-start="{" data-end="};">
<div class="line"><a id="l00043" name="l00043"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html"> 43</a></span> <span class="keyword">sealed</span> <span class="keyword">class </span><a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html">DiscordProvider</a> : <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html">Provider</a>, <a class="code hl_interface" href="interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_discord_responders.html">IDiscordResponders</a></div>
<div class="line"><a id="l00044" name="l00044"></a><span class="lineno"> 44</span> {</div>
<div class="line"><a id="l00046" name="l00046"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac2744da20824177724b971eb20a6d5a0"> 46</a></span> <span class="keyword">public</span> <span class="keyword">override</span> <span class="keywordtype">bool</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac2744da20824177724b971eb20a6d5a0">Connected</a> =&gt; <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a968f8dd1140ebe40a77c774fe7f9019b">gatewayTask</a>?.IsCompleted == <span class="keyword">false</span>;</div>
<div class="line"><a id="l00047" name="l00047"></a><span class="lineno"> 47</span> </div>
<div class="foldopen" id="foldopen00049" data-start="{" data-end="};">
<div class="line"><a id="l00049" name="l00049"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#af40c0ea392de9986a4705d403674f61c"> 49</a></span> <span class="keyword">public</span> <span class="keyword">override</span> <span class="keywordtype">string</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#af40c0ea392de9986a4705d403674f61c">BotMention</a></div>
<div class="line"><a id="l00050" name="l00050"></a><span class="lineno"> 50</span> {</div>
<div class="line"><a id="l00051" name="l00051"></a><span class="lineno"> 51</span> <span class="keyword">get</span></div>
<div class="line"><a id="l00052" name="l00052"></a><span class="lineno"> 52</span> {</div>
<div class="line"><a id="l00053" name="l00053"></a><span class="lineno"> 53</span> <span class="keywordflow">if</span> (!<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac2744da20824177724b971eb20a6d5a0">Connected</a>)</div>
<div class="line"><a id="l00054" name="l00054"></a><span class="lineno"> 54</span> <span class="keywordflow">throw</span> <span class="keyword">new</span> InvalidOperationException(<span class="stringliteral">&quot;Provider not connected&quot;</span>);</div>
<div class="line"><a id="l00055" name="l00055"></a><span class="lineno"> 55</span> <span class="keywordflow">return</span> <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3cf5b9ba9079d6c9f582f61b5894f7c1">NormalizeMentions</a>($<span class="stringliteral">&quot;&lt;@{currentUserId}&gt;&quot;</span>);</div>
<div class="line"><a id="l00056" name="l00056"></a><span class="lineno"> 56</span> }</div>
<div class="line"><a id="l00057" name="l00057"></a><span class="lineno"> 57</span> }</div>
</div>
<div class="line"><a id="l00058" name="l00058"></a><span class="lineno"> 58</span> </div>
<div class="line"><a id="l00062" name="l00062"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1896b3a7ddd7b500c2624d3676b64eaf"> 62</a></span> <span class="keyword">static</span> readonly ChannelType[] <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1896b3a7ddd7b500c2624d3676b64eaf">SupportedGuildChannelTypes</a> =</div>
<div class="line"><a id="l00063" name="l00063"></a><span class="lineno"> 63</span> [</div>
<div class="line"><a id="l00064" name="l00064"></a><span class="lineno"> 64</span> ChannelType.GuildText,</div>
<div class="line"><a id="l00065" name="l00065"></a><span class="lineno"> 65</span> ChannelType.GuildAnnouncement,</div>
<div class="line"><a id="l00066" name="l00066"></a><span class="lineno"> 66</span> ChannelType.PrivateThread,</div>
<div class="line"><a id="l00067" name="l00067"></a><span class="lineno"> 67</span> ChannelType.PublicThread,</div>
<div class="line"><a id="l00068" name="l00068"></a><span class="lineno"> 68</span> ];</div>
<div class="line"><a id="l00069" name="l00069"></a><span class="lineno"> 69</span> </div>
<div class="line"><a id="l00073" name="l00073"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a73f7fae07fc8d7efc90b6464dc2eca79"> 73</a></span> readonly <a class="code hl_interface" href="interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider.html">IAssemblyInformationProvider</a> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a73f7fae07fc8d7efc90b6464dc2eca79">assemblyInformationProvider</a>;</div>
<div class="line"><a id="l00074" name="l00074"></a><span class="lineno"> 74</span> </div>
<div class="line"><a id="l00078" name="l00078"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac93400b45eefb577306a70a7a530147f"> 78</a></span> readonly IOptionsMonitor&lt;GeneralConfiguration&gt; <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac93400b45eefb577306a70a7a530147f">generalConfigurationOptions</a>;</div>
<div class="line"><a id="l00079" name="l00079"></a><span class="lineno"> 79</span> </div>
<div class="line"><a id="l00083" name="l00083"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92"> 83</a></span> readonly ServiceProvider <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>;</div>
<div class="line"><a id="l00084" name="l00084"></a><span class="lineno"> 84</span> </div>
<div class="line"><a id="l00088" name="l00088"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146"> 88</a></span> readonly List&lt;ulong&gt; <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>;</div>
<div class="line"><a id="l00089" name="l00089"></a><span class="lineno"> 89</span> </div>
<div class="line"><a id="l00093" name="l00093"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a01881ab9506db0431f75db21224bf7e6"> 93</a></span> readonly <span class="keywordtype">object</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a01881ab9506db0431f75db21224bf7e6">connectDisconnectLock</a>;</div>
<div class="line"><a id="l00094" name="l00094"></a><span class="lineno"> 94</span> </div>
<div class="line"><a id="l00098" name="l00098"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a182447c000f64abfb2e30336a6b9718f"> 98</a></span> readonly <span class="keywordtype">bool</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a182447c000f64abfb2e30336a6b9718f">deploymentBranding</a>;</div>
<div class="line"><a id="l00099" name="l00099"></a><span class="lineno"> 99</span> </div>
<div class="line"><a id="l00103" name="l00103"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a96681c4d5a393d80bd2ff022eed95ee5"> 103</a></span> readonly <a class="code hl_enumeration" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#af16952d12561118ecebc3d8ccf510221">DiscordDMOutputDisplayType</a> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a96681c4d5a393d80bd2ff022eed95ee5">outputDisplayType</a>;</div>
<div class="line"><a id="l00104" name="l00104"></a><span class="lineno"> 104</span> </div>
<div class="line"><a id="l00108" name="l00108"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6"> 108</a></span> CancellationTokenSource? <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">gatewayCts</a>;</div>
<div class="line"><a id="l00109" name="l00109"></a><span class="lineno"> 109</span> </div>
<div class="line"><a id="l00113" name="l00113"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3f81033139026af1ea3160ef0063e737"> 113</a></span> TaskCompletionSource? <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3f81033139026af1ea3160ef0063e737">gatewayReadyTcs</a>;</div>
<div class="line"><a id="l00114" name="l00114"></a><span class="lineno"> 114</span> </div>
<div class="line"><a id="l00118" name="l00118"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a968f8dd1140ebe40a77c774fe7f9019b"> 118</a></span> Task&lt;Result&gt;? <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a968f8dd1140ebe40a77c774fe7f9019b">gatewayTask</a>;</div>
<div class="line"><a id="l00119" name="l00119"></a><span class="lineno"> 119</span> </div>
<div class="line"><a id="l00123" name="l00123"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a38455db633742e90572b9a83aa681831"> 123</a></span> Snowflake <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a38455db633742e90572b9a83aa681831">currentUserId</a>;</div>
<div class="line"><a id="l00124" name="l00124"></a><span class="lineno"> 124</span> </div>
<div class="line"><a id="l00128" name="l00128"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a317ac4b2144b7b5d2764063b158c7f54"> 128</a></span> <span class="keywordtype">bool</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a317ac4b2144b7b5d2764063b158c7f54">disposing</a>;</div>
<div class="line"><a id="l00129" name="l00129"></a><span class="lineno"> 129</span> </div>
<div class="line"><a id="l00135" name="l00135"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3cf5b9ba9079d6c9f582f61b5894f7c1"> 135</a></span> <span class="keyword">static</span> <span class="keywordtype">string</span> <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3cf5b9ba9079d6c9f582f61b5894f7c1">NormalizeMentions</a>(<span class="keywordtype">string</span> fromDiscord) =&gt; fromDiscord.Replace(<span class="stringliteral">&quot;&lt;@!&quot;</span>, <span class="stringliteral">&quot;&lt;@&quot;</span>, StringComparison.Ordinal);</div>
<div class="line"><a id="l00136" name="l00136"></a><span class="lineno"> 136</span> </div>
<div class="foldopen" id="foldopen00146" data-start="{" data-end="}">
<div class="line"><a id="l00146" name="l00146"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab4076d0667f118cef056a4d3d5ab6b4a"> 146</a></span> <span class="keyword">public</span> <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab4076d0667f118cef056a4d3d5ab6b4a">DiscordProvider</a>(</div>
<div class="line"><a id="l00147" name="l00147"></a><span class="lineno"> 147</span> <a class="code hl_interface" href="interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html">IJobManager</a> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#aa36ffb34c69e4a990830e49f97b7c142">jobManager</a>,</div>
<div class="line"><a id="l00148" name="l00148"></a><span class="lineno"> 148</span> <a class="code hl_interface" href="interface_tgstation_1_1_server_1_1_host_1_1_utils_1_1_i_async_delayer.html">IAsyncDelayer</a> asyncDelayer,</div>
<div class="line"><a id="l00149" name="l00149"></a><span class="lineno"> 149</span> ILogger&lt;DiscordProvider&gt; logger,</div>
<div class="line"><a id="l00150" name="l00150"></a><span class="lineno"> 150</span> <a class="code hl_interface" href="interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider.html">IAssemblyInformationProvider</a> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a73f7fae07fc8d7efc90b6464dc2eca79">assemblyInformationProvider</a>,</div>
<div class="line"><a id="l00151" name="l00151"></a><span class="lineno"> 151</span> IOptionsMonitor&lt;GeneralConfiguration&gt; <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac93400b45eefb577306a70a7a530147f">generalConfigurationOptions</a>,</div>
<div class="line"><a id="l00152" name="l00152"></a><span class="lineno"> 152</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_models_1_1_chat_bot.html">ChatBot</a> chatBot)</div>
<div class="line"><a id="l00153" name="l00153"></a><span class="lineno"> 153</span> : base(<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#aa36ffb34c69e4a990830e49f97b7c142">jobManager</a>, asyncDelayer, logger, chatBot)</div>
<div class="line"><a id="l00154" name="l00154"></a><span class="lineno"> 154</span> {</div>
<div class="line"><a id="l00155" name="l00155"></a><span class="lineno"> 155</span> this.assemblyInformationProvider = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a73f7fae07fc8d7efc90b6464dc2eca79">assemblyInformationProvider</a> ?? <span class="keywordflow">throw</span> <span class="keyword">new</span> ArgumentNullException(nameof(<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a73f7fae07fc8d7efc90b6464dc2eca79">assemblyInformationProvider</a>));</div>
<div class="line"><a id="l00156" name="l00156"></a><span class="lineno"> 156</span> this.generalConfigurationOptions = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac93400b45eefb577306a70a7a530147f">generalConfigurationOptions</a> ?? <span class="keywordflow">throw</span> <span class="keyword">new</span> ArgumentNullException(nameof(<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac93400b45eefb577306a70a7a530147f">generalConfigurationOptions</a>));</div>
<div class="line"><a id="l00157" name="l00157"></a><span class="lineno"> 157</span> </div>
<div class="line"><a id="l00158" name="l00158"></a><span class="lineno"> 158</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a> = <span class="keyword">new</span> List&lt;ulong&gt;();</div>
<div class="line"><a id="l00159" name="l00159"></a><span class="lineno"> 159</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a01881ab9506db0431f75db21224bf7e6">connectDisconnectLock</a> = <span class="keyword">new</span> object();</div>
<div class="line"><a id="l00160" name="l00160"></a><span class="lineno"> 160</span> </div>
<div class="line"><a id="l00161" name="l00161"></a><span class="lineno"> 161</span> var csb = <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_discord_connection_string_builder.html">DiscordConnectionStringBuilder</a>(chatBot.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot_settings.html#acdc14bc7df5569305c8a5af42e61f1da">ConnectionString</a>!);</div>
<div class="line"><a id="l00162" name="l00162"></a><span class="lineno"> 162</span> var botToken = csb.BotToken!;</div>
<div class="line"><a id="l00163" name="l00163"></a><span class="lineno"> 163</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a96681c4d5a393d80bd2ff022eed95ee5">outputDisplayType</a> = csb.DMOutputDisplay;</div>
<div class="line"><a id="l00164" name="l00164"></a><span class="lineno"> 164</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a182447c000f64abfb2e30336a6b9718f">deploymentBranding</a> = csb.DeploymentBranding;</div>
<div class="line"><a id="l00165" name="l00165"></a><span class="lineno"> 165</span> </div>
<div class="line"><a id="l00166" name="l00166"></a><span class="lineno"> 166</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a> = <span class="keyword">new</span> ServiceCollection()</div>
<div class="line"><a id="l00167" name="l00167"></a><span class="lineno"> 167</span> .AddDiscordGateway(<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a> =&gt; botToken)</div>
<div class="line"><a id="l00168" name="l00168"></a><span class="lineno"> 168</span> .Configure&lt;DiscordGatewayClientOptions&gt;(options =&gt; options.Intents |= GatewayIntents.MessageContents)</div>
<div class="line"><a id="l00169" name="l00169"></a><span class="lineno"> 169</span> .AddSingleton(<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a> =&gt; (<a class="code hl_interface" href="interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_discord_responders.html">IDiscordResponders</a>)<span class="keyword">this</span>)</div>
<div class="line"><a id="l00170" name="l00170"></a><span class="lineno"> 170</span> .AddResponder&lt;DiscordForwardingResponder&gt;()</div>
<div class="line"><a id="l00171" name="l00171"></a><span class="lineno"> 171</span> .BuildServiceProvider();</div>
<div class="line"><a id="l00172" name="l00172"></a><span class="lineno"> 172</span> }</div>
</div>
<div class="line"><a id="l00173" name="l00173"></a><span class="lineno"> 173</span> </div>
<div class="foldopen" id="foldopen00175" data-start="{" data-end="}">
<div class="line"><a id="l00175" name="l00175"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab650903107863653f1b637562f4813b4"> 175</a></span> <span class="keyword">public</span> <span class="keyword">override</span> async ValueTask <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab650903107863653f1b637562f4813b4">DisposeAsync</a>()</div>
<div class="line"><a id="l00176" name="l00176"></a><span class="lineno"> 176</span> {</div>
<div class="line"><a id="l00177" name="l00177"></a><span class="lineno"> 177</span> lock (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>)</div>
<div class="line"><a id="l00178" name="l00178"></a><span class="lineno"> 178</span> {</div>
<div class="line"><a id="l00179" name="l00179"></a><span class="lineno"> 179</span> <span class="comment">// serviceProvider can recursively dispose us</span></div>
<div class="line"><a id="l00180" name="l00180"></a><span class="lineno"> 180</span> <span class="keywordflow">if</span> (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a317ac4b2144b7b5d2764063b158c7f54">disposing</a>)</div>
<div class="line"><a id="l00181" name="l00181"></a><span class="lineno"> 181</span> <span class="keywordflow">return</span>;</div>
<div class="line"><a id="l00182" name="l00182"></a><span class="lineno"> 182</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a317ac4b2144b7b5d2764063b158c7f54">disposing</a> = <span class="keyword">true</span>;</div>
<div class="line"><a id="l00183" name="l00183"></a><span class="lineno"> 183</span> }</div>
<div class="line"><a id="l00184" name="l00184"></a><span class="lineno"> 184</span> </div>
<div class="line"><a id="l00185" name="l00185"></a><span class="lineno"> 185</span> await base.DisposeAsync();</div>
<div class="line"><a id="l00186" name="l00186"></a><span class="lineno"> 186</span> </div>
<div class="line"><a id="l00187" name="l00187"></a><span class="lineno"> 187</span> await <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.DisposeAsync();</div>
<div class="line"><a id="l00188" name="l00188"></a><span class="lineno"> 188</span> </div>
<div class="line"><a id="l00189" name="l00189"></a><span class="lineno"> 189</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogTrace(<span class="stringliteral">&quot;ServiceProvider disposed&quot;</span>);</div>
<div class="line"><a id="l00190" name="l00190"></a><span class="lineno"> 190</span> </div>
<div class="line"><a id="l00191" name="l00191"></a><span class="lineno"> 191</span> <span class="comment">// this line is purely here to shutup CA2213. It should always be null</span></div>
<div class="line"><a id="l00192" name="l00192"></a><span class="lineno"> 192</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">gatewayCts</a>?.Dispose();</div>
<div class="line"><a id="l00193" name="l00193"></a><span class="lineno"> 193</span> </div>
<div class="line"><a id="l00194" name="l00194"></a><span class="lineno"> 194</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a317ac4b2144b7b5d2764063b158c7f54">disposing</a> = <span class="keyword">false</span>;</div>
<div class="line"><a id="l00195" name="l00195"></a><span class="lineno"> 195</span> }</div>
</div>
<div class="line"><a id="l00196" name="l00196"></a><span class="lineno"> 196</span> </div>
<div class="foldopen" id="foldopen00198" data-start="{" data-end="}">
<div class="line"><a id="l00198" name="l00198"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1494b2b91cc869199100c9338f91d864"> 198</a></span> <span class="keyword">public</span> <span class="keyword">override</span> async ValueTask <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1494b2b91cc869199100c9338f91d864">SendMessage</a>(<a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_message.html">Message</a>? replyTo, <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content.html">MessageContent</a> message, ulong channelId, CancellationToken cancellationToken)</div>
<div class="line"><a id="l00199" name="l00199"></a><span class="lineno"> 199</span> {</div>
<div class="line"><a id="l00200" name="l00200"></a><span class="lineno"> 200</span> ArgumentNullException.ThrowIfNull(message);</div>
<div class="line"><a id="l00201" name="l00201"></a><span class="lineno"> 201</span> </div>
<div class="line"><a id="l00202" name="l00202"></a><span class="lineno"> 202</span> Optional&lt;IMessageReference&gt; replyToReference = <span class="keywordflow">default</span>;</div>
<div class="line"><a id="l00203" name="l00203"></a><span class="lineno"> 203</span> Optional&lt;IAllowedMentions&gt; allowedMentions = <span class="keywordflow">default</span>;</div>
<div class="line"><a id="l00204" name="l00204"></a><span class="lineno"> 204</span> <span class="keywordflow">if</span> (replyTo != <span class="keyword">null</span> &amp;&amp; replyTo is <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_message.html">DiscordMessage</a> discordMessage)</div>
<div class="line"><a id="l00205" name="l00205"></a><span class="lineno"> 205</span> {</div>
<div class="line"><a id="l00206" name="l00206"></a><span class="lineno"> 206</span> replyToReference = discordMessage.MessageReference;</div>
<div class="line"><a id="l00207" name="l00207"></a><span class="lineno"> 207</span> allowedMentions = <span class="keyword">new</span> AllowedMentions(</div>
<div class="line"><a id="l00208" name="l00208"></a><span class="lineno"> 208</span> Parse: <span class="keyword">new</span> List&lt;MentionType&gt; <span class="comment">// reset settings back to how discord acts if this is not passed (which is different than the default if empty)</span></div>
<div class="line"><a id="l00209" name="l00209"></a><span class="lineno"> 209</span> {</div>
<div class="line"><a id="l00210" name="l00210"></a><span class="lineno"> 210</span> MentionType.Everyone,</div>
<div class="line"><a id="l00211" name="l00211"></a><span class="lineno"> 211</span> MentionType.Roles,</div>
<div class="line"><a id="l00212" name="l00212"></a><span class="lineno"> 212</span> MentionType.Users,</div>
<div class="line"><a id="l00213" name="l00213"></a><span class="lineno"> 213</span> },</div>
<div class="line"><a id="l00214" name="l00214"></a><span class="lineno"> 214</span> MentionRepliedUser: <span class="keyword">false</span>); <span class="comment">// disable reply mentions</span></div>
<div class="line"><a id="l00215" name="l00215"></a><span class="lineno"> 215</span> }</div>
<div class="line"><a id="l00216" name="l00216"></a><span class="lineno"> 216</span> </div>
<div class="line"><a id="l00217" name="l00217"></a><span class="lineno"> 217</span> var embeds = <a class="code hl_function" href="_discord_provider_8cs.html#a6faaab8be32021a7d88c1d1ac62162c8">ConvertEmbed</a>(message.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content.html#a60f2aaeaf7f59e642e62b322bb1bce63">Embed</a>);</div>
<div class="line"><a id="l00218" name="l00218"></a><span class="lineno"> 218</span> </div>
<div class="line"><a id="l00219" name="l00219"></a><span class="lineno"> 219</span> var channelsClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestChannelAPI&gt;();</div>
<div class="line"><a id="l00220" name="l00220"></a><span class="lineno"> 220</span> async ValueTask SendToChannel(Snowflake channelId)</div>
<div class="line"><a id="l00221" name="l00221"></a><span class="lineno"> 221</span> {</div>
<div class="line"><a id="l00222" name="l00222"></a><span class="lineno"> 222</span> <span class="keywordflow">if</span> (message.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content.html#acc847c3c842120dede3072ddb6e0c0cd">Text</a> == <span class="keyword">null</span>)</div>
<div class="line"><a id="l00223" name="l00223"></a><span class="lineno"> 223</span> {</div>
<div class="line"><a id="l00224" name="l00224"></a><span class="lineno"> 224</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00225" name="l00225"></a><span class="lineno"> 225</span> <span class="stringliteral">&quot;Failed to send to channel {channelId}: Message was null!&quot;</span>,</div>
<div class="line"><a id="l00226" name="l00226"></a><span class="lineno"> 226</span> channelId);</div>
<div class="line"><a id="l00227" name="l00227"></a><span class="lineno"> 227</span> </div>
<div class="line"><a id="l00228" name="l00228"></a><span class="lineno"> 228</span> await channelsClient.CreateMessageAsync(</div>
<div class="line"><a id="l00229" name="l00229"></a><span class="lineno"> 229</span> channelId,</div>
<div class="line"><a id="l00230" name="l00230"></a><span class="lineno"> 230</span> <span class="stringliteral">&quot;TGS: Could not send message to Discord. Message was `null`!&quot;</span>,</div>
<div class="line"><a id="l00231" name="l00231"></a><span class="lineno"> 231</span> messageReference: replyToReference,</div>
<div class="line"><a id="l00232" name="l00232"></a><span class="lineno"> 232</span> allowedMentions: allowedMentions,</div>
<div class="line"><a id="l00233" name="l00233"></a><span class="lineno"> 233</span> ct: cancellationToken);</div>
<div class="line"><a id="l00234" name="l00234"></a><span class="lineno"> 234</span> </div>
<div class="line"><a id="l00235" name="l00235"></a><span class="lineno"> 235</span> <span class="keywordflow">return</span>;</div>
<div class="line"><a id="l00236" name="l00236"></a><span class="lineno"> 236</span> }</div>
<div class="line"><a id="l00237" name="l00237"></a><span class="lineno"> 237</span> </div>
<div class="line"><a id="l00238" name="l00238"></a><span class="lineno"> 238</span> var result = await channelsClient.CreateMessageAsync(</div>
<div class="line"><a id="l00239" name="l00239"></a><span class="lineno"> 239</span> channelId,</div>
<div class="line"><a id="l00240" name="l00240"></a><span class="lineno"> 240</span> message.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content.html#acc847c3c842120dede3072ddb6e0c0cd">Text</a>,</div>
<div class="line"><a id="l00241" name="l00241"></a><span class="lineno"> 241</span> embeds: embeds,</div>
<div class="line"><a id="l00242" name="l00242"></a><span class="lineno"> 242</span> messageReference: replyToReference,</div>
<div class="line"><a id="l00243" name="l00243"></a><span class="lineno"> 243</span> allowedMentions: allowedMentions,</div>
<div class="line"><a id="l00244" name="l00244"></a><span class="lineno"> 244</span> ct: cancellationToken);</div>
<div class="line"><a id="l00245" name="l00245"></a><span class="lineno"> 245</span> </div>
<div class="line"><a id="l00246" name="l00246"></a><span class="lineno"> 246</span> <span class="keywordflow">if</span> (!result.IsSuccess)</div>
<div class="line"><a id="l00247" name="l00247"></a><span class="lineno"> 247</span> {</div>
<div class="line"><a id="l00248" name="l00248"></a><span class="lineno"> 248</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00249" name="l00249"></a><span class="lineno"> 249</span> <span class="stringliteral">&quot;Failed to send to channel {channelId}: {result}&quot;</span>,</div>
<div class="line"><a id="l00250" name="l00250"></a><span class="lineno"> 250</span> channelId,</div>
<div class="line"><a id="l00251" name="l00251"></a><span class="lineno"> 251</span> result.LogFormat());</div>
<div class="line"><a id="l00252" name="l00252"></a><span class="lineno"> 252</span> </div>
<div class="line"><a id="l00253" name="l00253"></a><span class="lineno"> 253</span> <span class="keywordflow">if</span> (result.Error is RestResultError&lt;RestError&gt; restError &amp;&amp; restError.Error.Code == DiscordError.InvalidFormBody)</div>
<div class="line"><a id="l00254" name="l00254"></a><span class="lineno"> 254</span> await channelsClient.CreateMessageAsync(</div>
<div class="line"><a id="l00255" name="l00255"></a><span class="lineno"> 255</span> channelId,</div>
<div class="line"><a id="l00256" name="l00256"></a><span class="lineno"> 256</span> <span class="stringliteral">&quot;TGS: Could not send message to Discord. Body was malformed or too long&quot;</span>,</div>
<div class="line"><a id="l00257" name="l00257"></a><span class="lineno"> 257</span> messageReference: replyToReference,</div>
<div class="line"><a id="l00258" name="l00258"></a><span class="lineno"> 258</span> allowedMentions: allowedMentions,</div>
<div class="line"><a id="l00259" name="l00259"></a><span class="lineno"> 259</span> ct: cancellationToken);</div>
<div class="line"><a id="l00260" name="l00260"></a><span class="lineno"> 260</span> }</div>
<div class="line"><a id="l00261" name="l00261"></a><span class="lineno"> 261</span> }</div>
<div class="line"><a id="l00262" name="l00262"></a><span class="lineno"> 262</span> </div>
<div class="line"><a id="l00263" name="l00263"></a><span class="lineno"> 263</span> <span class="keywordflow">try</span></div>
<div class="line"><a id="l00264" name="l00264"></a><span class="lineno"> 264</span> {</div>
<div class="line"><a id="l00265" name="l00265"></a><span class="lineno"> 265</span> <span class="keywordflow">if</span> (channelId == 0)</div>
<div class="line"><a id="l00266" name="l00266"></a><span class="lineno"> 266</span> {</div>
<div class="line"><a id="l00267" name="l00267"></a><span class="lineno"> 267</span> IEnumerable&lt;IChannel&gt; unmappedTextChannels;</div>
<div class="line"><a id="l00268" name="l00268"></a><span class="lineno"> 268</span> var allAccessibleTextChannels = await <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab92d4920074cec3e48fa204af595a498">GetAllAccessibleTextChannels</a>(cancellationToken);</div>
<div class="line"><a id="l00269" name="l00269"></a><span class="lineno"> 269</span> lock (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>)</div>
<div class="line"><a id="l00270" name="l00270"></a><span class="lineno"> 270</span> {</div>
<div class="line"><a id="l00271" name="l00271"></a><span class="lineno"> 271</span> unmappedTextChannels = allAccessibleTextChannels</div>
<div class="line"><a id="l00272" name="l00272"></a><span class="lineno"> 272</span> .Where(x =&gt; !<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>.Contains(x.ID.Value))</div>
<div class="line"><a id="l00273" name="l00273"></a><span class="lineno"> 273</span> .ToList();</div>
<div class="line"><a id="l00274" name="l00274"></a><span class="lineno"> 274</span> </div>
<div class="line"><a id="l00275" name="l00275"></a><span class="lineno"> 275</span> var remapRequired = unmappedTextChannels.Any()</div>
<div class="line"><a id="l00276" name="l00276"></a><span class="lineno"> 276</span> || <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>.Any(</div>
<div class="line"><a id="l00277" name="l00277"></a><span class="lineno"> 277</span> mappedChannel =&gt; !allAccessibleTextChannels.Any(</div>
<div class="line"><a id="l00278" name="l00278"></a><span class="lineno"> 278</span> accessibleTextChannel =&gt; accessibleTextChannel.ID == <span class="keyword">new</span> Snowflake(mappedChannel)));</div>
<div class="line"><a id="l00279" name="l00279"></a><span class="lineno"> 279</span> </div>
<div class="line"><a id="l00280" name="l00280"></a><span class="lineno"> 280</span> <span class="keywordflow">if</span> (remapRequired)</div>
<div class="line"><a id="l00281" name="l00281"></a><span class="lineno"> 281</span> <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#a6a6dd225ccb27e30c2cc06562b035ebe">EnqueueMessage</a>(<span class="keyword">null</span>);</div>
<div class="line"><a id="l00282" name="l00282"></a><span class="lineno"> 282</span> }</div>
<div class="line"><a id="l00283" name="l00283"></a><span class="lineno"> 283</span> </div>
<div class="line"><a id="l00284" name="l00284"></a><span class="lineno"> 284</span> <span class="comment">// discord API confirmed weak boned: https://stackoverflow.com/a/52462336</span></div>
<div class="line"><a id="l00285" name="l00285"></a><span class="lineno"> 285</span> <span class="keywordflow">if</span> (unmappedTextChannels.Any())</div>
<div class="line"><a id="l00286" name="l00286"></a><span class="lineno"> 286</span> {</div>
<div class="line"><a id="l00287" name="l00287"></a><span class="lineno"> 287</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogDebug(<span class="stringliteral">&quot;Dispatching to {count} unmapped channels...&quot;</span>, unmappedTextChannels.Count());</div>
<div class="line"><a id="l00288" name="l00288"></a><span class="lineno"> 288</span> await <a class="code hl_class" href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html">ValueTaskExtensions</a>.<a class="code hl_function" href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html#a58adbd94d764754bd3e6c566a5fe7fe3">WhenAll</a>(</div>
<div class="line"><a id="l00289" name="l00289"></a><span class="lineno"> 289</span> unmappedTextChannels.Select(</div>
<div class="line"><a id="l00290" name="l00290"></a><span class="lineno"> 290</span> x =&gt; SendToChannel(x.ID)));</div>
<div class="line"><a id="l00291" name="l00291"></a><span class="lineno"> 291</span> }</div>
<div class="line"><a id="l00292" name="l00292"></a><span class="lineno"> 292</span> </div>
<div class="line"><a id="l00293" name="l00293"></a><span class="lineno"> 293</span> <span class="keywordflow">return</span>;</div>
<div class="line"><a id="l00294" name="l00294"></a><span class="lineno"> 294</span> }</div>
<div class="line"><a id="l00295" name="l00295"></a><span class="lineno"> 295</span> </div>
<div class="line"><a id="l00296" name="l00296"></a><span class="lineno"> 296</span> await SendToChannel(<span class="keyword">new</span> Snowflake(channelId));</div>
<div class="line"><a id="l00297" name="l00297"></a><span class="lineno"> 297</span> }</div>
<div class="line"><a id="l00298" name="l00298"></a><span class="lineno"> 298</span> <span class="keywordflow">catch</span> (<a class="code hl_class" href="class_exception.html">Exception</a> e) when (e is not OperationCanceledException)</div>
<div class="line"><a id="l00299" name="l00299"></a><span class="lineno"> 299</span> {</div>
<div class="line"><a id="l00300" name="l00300"></a><span class="lineno"> 300</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(e, <span class="stringliteral">&quot;Error sending discord message!&quot;</span>);</div>
<div class="line"><a id="l00301" name="l00301"></a><span class="lineno"> 301</span> }</div>
<div class="line"><a id="l00302" name="l00302"></a><span class="lineno"> 302</span> }</div>
</div>
<div class="line"><a id="l00303" name="l00303"></a><span class="lineno"> 303</span> </div>
<div class="foldopen" id="foldopen00305" data-start="{" data-end="}">
<div class="line"><a id="l00305" name="l00305"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a6b14b94a01f2a1478f1ade14ef9a7471"> 305</a></span> <span class="keyword">public</span> <span class="keyword">override</span> async ValueTask&lt;Func&lt;string?, string, ValueTask&lt;Func&lt;bool, ValueTask&gt;&gt;&gt;&gt; <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a6b14b94a01f2a1478f1ade14ef9a7471">SendUpdateMessage</a>(</div>
<div class="line"><a id="l00306" name="l00306"></a><span class="lineno"> 306</span> Models.RevisionInformation revisionInformation,</div>
<div class="line"><a id="l00307" name="l00307"></a><span class="lineno"> 307</span> Models.RevisionInformation? previousRevisionInformation,</div>
<div class="line"><a id="l00308" name="l00308"></a><span class="lineno"> 308</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html">EngineVersion</a> engineVersion,</div>
<div class="line"><a id="l00309" name="l00309"></a><span class="lineno"> 309</span> DateTimeOffset? estimatedCompletionTime,</div>
<div class="line"><a id="l00310" name="l00310"></a><span class="lineno"> 310</span> <span class="keywordtype">string</span>? gitHubOwner,</div>
<div class="line"><a id="l00311" name="l00311"></a><span class="lineno"> 311</span> <span class="keywordtype">string</span>? gitHubRepo,</div>
<div class="line"><a id="l00312" name="l00312"></a><span class="lineno"> 312</span> ulong channelId,</div>
<div class="line"><a id="l00313" name="l00313"></a><span class="lineno"> 313</span> <span class="keywordtype">bool</span> localCommitPushed,</div>
<div class="line"><a id="l00314" name="l00314"></a><span class="lineno"> 314</span> CancellationToken cancellationToken)</div>
<div class="line"><a id="l00315" name="l00315"></a><span class="lineno"> 315</span> {</div>
<div class="line"><a id="l00316" name="l00316"></a><span class="lineno"> 316</span> ArgumentNullException.ThrowIfNull(revisionInformation);</div>
<div class="line"><a id="l00317" name="l00317"></a><span class="lineno"> 317</span> ArgumentNullException.ThrowIfNull(engineVersion);</div>
<div class="line"><a id="l00318" name="l00318"></a><span class="lineno"> 318</span> </div>
<div class="line"><a id="l00319" name="l00319"></a><span class="lineno"> 319</span> localCommitPushed |= revisionInformation.CommitSha == revisionInformation.OriginCommitSha;</div>
<div class="line"><a id="l00320" name="l00320"></a><span class="lineno"> 320</span> </div>
<div class="line"><a id="l00321" name="l00321"></a><span class="lineno"> 321</span> var fields = <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aa0b4853705d24be3e16314bf050f9e7c">BuildUpdateEmbedFields</a>(revisionInformation, previousRevisionInformation, engineVersion, gitHubOwner, gitHubRepo, localCommitPushed);</div>
<div class="line"><a id="l00322" name="l00322"></a><span class="lineno"> 322</span> Optional&lt;IEmbedAuthor&gt; author = <span class="keyword">new</span> EmbedAuthor(<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a73f7fae07fc8d7efc90b6464dc2eca79">assemblyInformationProvider</a>.<a class="code hl_property" href="interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider.html#ab2a2be82555afbf6ffb5b7ae3d90b7f0">VersionPrefix</a>)</div>
<div class="line"><a id="l00323" name="l00323"></a><span class="lineno"> 323</span> {</div>
<div class="line"><a id="l00324" name="l00324"></a><span class="lineno"> 324</span> Url = <span class="stringliteral">&quot;https://github.com/tgstation/tgstation-server&quot;</span>,</div>
<div class="line"><a id="l00325" name="l00325"></a><span class="lineno"> 325</span> IconUrl = <span class="stringliteral">&quot;https://cdn.discordapp.com/attachments/1114451486374637629/1151650846019432448/tgs.png&quot;</span>, <span class="comment">// 404&#39;s in browsers but works in Discord</span></div>
<div class="line"><a id="l00326" name="l00326"></a><span class="lineno"> 326</span> };</div>
<div class="line"><a id="l00327" name="l00327"></a><span class="lineno"> 327</span> var embed = <span class="keyword">new</span> Embed</div>
<div class="line"><a id="l00328" name="l00328"></a><span class="lineno"> 328</span> {</div>
<div class="line"><a id="l00329" name="l00329"></a><span class="lineno"> 329</span> Author = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a182447c000f64abfb2e30336a6b9718f">deploymentBranding</a> ? author : <span class="keywordflow">default</span>,</div>
<div class="line"><a id="l00330" name="l00330"></a><span class="lineno"> 330</span> Colour = Color.FromArgb(0xF1, 0xC4, 0x0F),</div>
<div class="line"><a id="l00331" name="l00331"></a><span class="lineno"> 331</span> Description = <span class="stringliteral">&quot;TGS has begun deploying active repository code to production.&quot;</span>,</div>
<div class="line"><a id="l00332" name="l00332"></a><span class="lineno"> 332</span> Fields = fields,</div>
<div class="line"><a id="l00333" name="l00333"></a><span class="lineno"> 333</span> Title = <span class="stringliteral">&quot;Code Deployment&quot;</span>,</div>
<div class="line"><a id="l00334" name="l00334"></a><span class="lineno"> 334</span> Footer = <span class="keyword">new</span> EmbedFooter(</div>
<div class="line"><a id="l00335" name="l00335"></a><span class="lineno"> 335</span> $<span class="stringliteral">&quot;In progress...{(estimatedCompletionTime.HasValue ? &quot;</span> ETA<span class="stringliteral">&quot; : String.Empty)}&quot;</span>),</div>
<div class="line"><a id="l00336" name="l00336"></a><span class="lineno"> 336</span> Timestamp = estimatedCompletionTime ?? <span class="keywordflow">default</span>,</div>
<div class="line"><a id="l00337" name="l00337"></a><span class="lineno"> 337</span> };</div>
<div class="line"><a id="l00338" name="l00338"></a><span class="lineno"> 338</span> </div>
<div class="line"><a id="l00339" name="l00339"></a><span class="lineno"> 339</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogTrace(<span class="stringliteral">&quot;Attempting to post deploy embed to channel {channelId}...&quot;</span>, channelId);</div>
<div class="line"><a id="l00340" name="l00340"></a><span class="lineno"> 340</span> var channelsClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestChannelAPI&gt;();</div>
<div class="line"><a id="l00341" name="l00341"></a><span class="lineno"> 341</span> </div>
<div class="line"><a id="l00342" name="l00342"></a><span class="lineno"> 342</span> var prefix = <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#a838ad29e96221a58a71b29358c086c0c">GetEngineCompilerPrefix</a>(engineVersion.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html#ae13db4c5dbd6b06c79d37ad9afd25af2">Engine</a>!.Value);</div>
<div class="line"><a id="l00343" name="l00343"></a><span class="lineno"> 343</span> var messageResponse = await channelsClient.CreateMessageAsync(</div>
<div class="line"><a id="l00344" name="l00344"></a><span class="lineno"> 344</span> <span class="keyword">new</span> Snowflake(channelId),</div>
<div class="line"><a id="l00345" name="l00345"></a><span class="lineno"> 345</span> $<span class="stringliteral">&quot;{prefix}: Deployment in progress...&quot;</span>,</div>
<div class="line"><a id="l00346" name="l00346"></a><span class="lineno"> 346</span> embeds: <span class="keyword">new</span> List&lt;IEmbed&gt; { embed },</div>
<div class="line"><a id="l00347" name="l00347"></a><span class="lineno"> 347</span> ct: cancellationToken);</div>
<div class="line"><a id="l00348" name="l00348"></a><span class="lineno"> 348</span> </div>
<div class="line"><a id="l00349" name="l00349"></a><span class="lineno"> 349</span> <span class="keywordflow">if</span> (!messageResponse.IsSuccess)</div>
<div class="line"><a id="l00350" name="l00350"></a><span class="lineno"> 350</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(<span class="stringliteral">&quot;Failed to post deploy embed to channel {channelId}: {result}&quot;</span>, channelId, messageResponse.LogFormat());</div>
<div class="line"><a id="l00351" name="l00351"></a><span class="lineno"> 351</span> </div>
<div class="line"><a id="l00352" name="l00352"></a><span class="lineno"> 352</span> <span class="keywordflow">return</span> async (errorMessage, dreamMakerOutput) =&gt;</div>
<div class="line"><a id="l00353" name="l00353"></a><span class="lineno"> 353</span> {</div>
<div class="line"><a id="l00354" name="l00354"></a><span class="lineno"> 354</span> var completionString = errorMessage == <span class="keyword">null</span> ? <span class="stringliteral">&quot;Pending&quot;</span> : <span class="stringliteral">&quot;Failed&quot;</span>;</div>
<div class="line"><a id="l00355" name="l00355"></a><span class="lineno"> 355</span> </div>
<div class="line"><a id="l00356" name="l00356"></a><span class="lineno"> 356</span> Embed CreateUpdatedEmbed(<span class="keywordtype">string</span> message, Color color) =&gt; <span class="keyword">new</span>()</div>
<div class="line"><a id="l00357" name="l00357"></a><span class="lineno"> 357</span> {</div>
<div class="line"><a id="l00358" name="l00358"></a><span class="lineno"> 358</span> Author = embed.Author,</div>
<div class="line"><a id="l00359" name="l00359"></a><span class="lineno"> 359</span> Colour = color,</div>
<div class="line"><a id="l00360" name="l00360"></a><span class="lineno"> 360</span> Description = message,</div>
<div class="line"><a id="l00361" name="l00361"></a><span class="lineno"> 361</span> Fields = fields,</div>
<div class="line"><a id="l00362" name="l00362"></a><span class="lineno"> 362</span> Title = embed.Title,</div>
<div class="line"><a id="l00363" name="l00363"></a><span class="lineno"> 363</span> Footer = <span class="keyword">new</span> EmbedFooter(</div>
<div class="line"><a id="l00364" name="l00364"></a><span class="lineno"> 364</span> completionString),</div>
<div class="line"><a id="l00365" name="l00365"></a><span class="lineno"> 365</span> Timestamp = DateTimeOffset.UtcNow,</div>
<div class="line"><a id="l00366" name="l00366"></a><span class="lineno"> 366</span> };</div>
<div class="line"><a id="l00367" name="l00367"></a><span class="lineno"> 367</span> </div>
<div class="line"><a id="l00368" name="l00368"></a><span class="lineno"> 368</span> <span class="keywordflow">if</span> (errorMessage == <span class="keyword">null</span>)</div>
<div class="line"><a id="l00369" name="l00369"></a><span class="lineno"> 369</span> embed = CreateUpdatedEmbed(</div>
<div class="line"><a id="l00370" name="l00370"></a><span class="lineno"> 370</span> <span class="stringliteral">&quot;The deployment completed successfully and will be available at the next server reboot.&quot;</span>,</div>
<div class="line"><a id="l00371" name="l00371"></a><span class="lineno"> 371</span> Color.Blue);</div>
<div class="line"><a id="l00372" name="l00372"></a><span class="lineno"> 372</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l00373" name="l00373"></a><span class="lineno"> 373</span> embed = CreateUpdatedEmbed(</div>
<div class="line"><a id="l00374" name="l00374"></a><span class="lineno"> 374</span> <span class="stringliteral">&quot;The deployment failed.&quot;</span>,</div>
<div class="line"><a id="l00375" name="l00375"></a><span class="lineno"> 375</span> Color.Red);</div>
<div class="line"><a id="l00376" name="l00376"></a><span class="lineno"> 376</span> </div>
<div class="line"><a id="l00377" name="l00377"></a><span class="lineno"> 377</span> var showDMOutput = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a96681c4d5a393d80bd2ff022eed95ee5">outputDisplayType</a> <span class="keywordflow">switch</span></div>
<div class="line"><a id="l00378" name="l00378"></a><span class="lineno"> 378</span> {</div>
<div class="line"><a id="l00379" name="l00379"></a><span class="lineno"> 379</span> DiscordDMOutputDisplayType.Always =&gt; <span class="keyword">true</span>,</div>
<div class="line"><a id="l00380" name="l00380"></a><span class="lineno"> 380</span> DiscordDMOutputDisplayType.Never =&gt; <span class="keyword">false</span>,</div>
<div class="line"><a id="l00381" name="l00381"></a><span class="lineno"> 381</span> DiscordDMOutputDisplayType.OnError =&gt; errorMessage != <span class="keyword">null</span>,</div>
<div class="line"><a id="l00382" name="l00382"></a><span class="lineno"> 382</span> _ =&gt; <span class="keywordflow">throw</span> <span class="keyword">new</span> InvalidOperationException($<span class="stringliteral">&quot;Invalid DiscordDMOutputDisplayType: {outputDisplayType}&quot;</span>),</div>
<div class="line"><a id="l00383" name="l00383"></a><span class="lineno"> 383</span> };</div>
<div class="line"><a id="l00384" name="l00384"></a><span class="lineno"> 384</span> </div>
<div class="line"><a id="l00385" name="l00385"></a><span class="lineno"> 385</span> <span class="keywordflow">if</span> (dreamMakerOutput != <span class="keyword">null</span>)</div>
<div class="line"><a id="l00386" name="l00386"></a><span class="lineno"> 386</span> {</div>
<div class="line"><a id="l00387" name="l00387"></a><span class="lineno"> 387</span> <span class="comment">// https://github.com/discord-net/Discord.Net/blob/8349cd7e1eb92e9a3baff68082c30a7b43e8e9b7/src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs#L431</span></div>
<div class="line"><a id="l00388" name="l00388"></a><span class="lineno"> 388</span> <span class="keyword">const</span> <span class="keywordtype">int</span> MaxFieldValueLength = 1024;</div>
<div class="line"><a id="l00389" name="l00389"></a><span class="lineno"> 389</span> showDMOutput = showDMOutput &amp;&amp; dreamMakerOutput.Length &lt; MaxFieldValueLength - (6 + Environment.NewLine.Length);</div>
<div class="line"><a id="l00390" name="l00390"></a><span class="lineno"> 390</span> <span class="keywordflow">if</span> (showDMOutput)</div>
<div class="line"><a id="l00391" name="l00391"></a><span class="lineno"> 391</span> fields.Add(<span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00392" name="l00392"></a><span class="lineno"> 392</span> <span class="stringliteral">&quot;Compiler Output&quot;</span>,</div>
<div class="line"><a id="l00393" name="l00393"></a><span class="lineno"> 393</span> $<span class="stringliteral">&quot;```{Environment.NewLine}{dreamMakerOutput}{Environment.NewLine}```&quot;</span>,</div>
<div class="line"><a id="l00394" name="l00394"></a><span class="lineno"> 394</span> <span class="keyword">false</span>));</div>
<div class="line"><a id="l00395" name="l00395"></a><span class="lineno"> 395</span> }</div>
<div class="line"><a id="l00396" name="l00396"></a><span class="lineno"> 396</span> </div>
<div class="line"><a id="l00397" name="l00397"></a><span class="lineno"> 397</span> <span class="keywordflow">if</span> (errorMessage != <span class="keyword">null</span>)</div>
<div class="line"><a id="l00398" name="l00398"></a><span class="lineno"> 398</span> fields.Add(<span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00399" name="l00399"></a><span class="lineno"> 399</span> <span class="stringliteral">&quot;Error Message&quot;</span>,</div>
<div class="line"><a id="l00400" name="l00400"></a><span class="lineno"> 400</span> errorMessage,</div>
<div class="line"><a id="l00401" name="l00401"></a><span class="lineno"> 401</span> <span class="keyword">false</span>));</div>
<div class="line"><a id="l00402" name="l00402"></a><span class="lineno"> 402</span> </div>
<div class="line"><a id="l00403" name="l00403"></a><span class="lineno"> 403</span> var updatedMessageText = errorMessage == <span class="keyword">null</span> ? $<span class="stringliteral">&quot;{prefix}: Deployment pending reboot...&quot;</span> : $<span class="stringliteral">&quot;{prefix}: Deployment failed!&quot;</span>;</div>
<div class="line"><a id="l00404" name="l00404"></a><span class="lineno"> 404</span> </div>
<div class="line"><a id="l00405" name="l00405"></a><span class="lineno"> 405</span> IMessage? updatedMessage = <span class="keyword">null</span>;</div>
<div class="line"><a id="l00406" name="l00406"></a><span class="lineno"> 406</span> async ValueTask CreateUpdatedMessage()</div>
<div class="line"><a id="l00407" name="l00407"></a><span class="lineno"> 407</span> {</div>
<div class="line"><a id="l00408" name="l00408"></a><span class="lineno"> 408</span> var createUpdatedMessageResponse = await channelsClient.CreateMessageAsync(</div>
<div class="line"><a id="l00409" name="l00409"></a><span class="lineno"> 409</span> <span class="keyword">new</span> Snowflake(channelId),</div>
<div class="line"><a id="l00410" name="l00410"></a><span class="lineno"> 410</span> updatedMessageText,</div>
<div class="line"><a id="l00411" name="l00411"></a><span class="lineno"> 411</span> embeds: <span class="keyword">new</span> List&lt;IEmbed&gt; { embed },</div>
<div class="line"><a id="l00412" name="l00412"></a><span class="lineno"> 412</span> ct: cancellationToken);</div>
<div class="line"><a id="l00413" name="l00413"></a><span class="lineno"> 413</span> </div>
<div class="line"><a id="l00414" name="l00414"></a><span class="lineno"> 414</span> <span class="keywordflow">if</span> (!createUpdatedMessageResponse.IsSuccess)</div>
<div class="line"><a id="l00415" name="l00415"></a><span class="lineno"> 415</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00416" name="l00416"></a><span class="lineno"> 416</span> <span class="stringliteral">&quot;Creating updated deploy embed failed: {result}&quot;</span>,</div>
<div class="line"><a id="l00417" name="l00417"></a><span class="lineno"> 417</span> createUpdatedMessageResponse.LogFormat());</div>
<div class="line"><a id="l00418" name="l00418"></a><span class="lineno"> 418</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l00419" name="l00419"></a><span class="lineno"> 419</span> updatedMessage = createUpdatedMessageResponse.Entity;</div>
<div class="line"><a id="l00420" name="l00420"></a><span class="lineno"> 420</span> }</div>
<div class="line"><a id="l00421" name="l00421"></a><span class="lineno"> 421</span> </div>
<div class="line"><a id="l00422" name="l00422"></a><span class="lineno"> 422</span> <span class="keywordflow">if</span> (!messageResponse.IsSuccess)</div>
<div class="line"><a id="l00423" name="l00423"></a><span class="lineno"> 423</span> await CreateUpdatedMessage();</div>
<div class="line"><a id="l00424" name="l00424"></a><span class="lineno"> 424</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l00425" name="l00425"></a><span class="lineno"> 425</span> {</div>
<div class="line"><a id="l00426" name="l00426"></a><span class="lineno"> 426</span> var editResponse = await channelsClient.EditMessageAsync(</div>
<div class="line"><a id="l00427" name="l00427"></a><span class="lineno"> 427</span> <span class="keyword">new</span> Snowflake(channelId),</div>
<div class="line"><a id="l00428" name="l00428"></a><span class="lineno"> 428</span> messageResponse.Entity.ID,</div>
<div class="line"><a id="l00429" name="l00429"></a><span class="lineno"> 429</span> updatedMessageText,</div>
<div class="line"><a id="l00430" name="l00430"></a><span class="lineno"> 430</span> embeds: <span class="keyword">new</span> List&lt;IEmbed&gt; { embed },</div>
<div class="line"><a id="l00431" name="l00431"></a><span class="lineno"> 431</span> ct: cancellationToken);</div>
<div class="line"><a id="l00432" name="l00432"></a><span class="lineno"> 432</span> </div>
<div class="line"><a id="l00433" name="l00433"></a><span class="lineno"> 433</span> <span class="keywordflow">if</span> (!editResponse.IsSuccess)</div>
<div class="line"><a id="l00434" name="l00434"></a><span class="lineno"> 434</span> {</div>
<div class="line"><a id="l00435" name="l00435"></a><span class="lineno"> 435</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00436" name="l00436"></a><span class="lineno"> 436</span> <span class="stringliteral">&quot;Updating deploy embed {messageId} failed, attempting new post: {result}&quot;</span>,</div>
<div class="line"><a id="l00437" name="l00437"></a><span class="lineno"> 437</span> messageResponse.Entity.ID,</div>
<div class="line"><a id="l00438" name="l00438"></a><span class="lineno"> 438</span> editResponse.LogFormat());</div>
<div class="line"><a id="l00439" name="l00439"></a><span class="lineno"> 439</span> await CreateUpdatedMessage();</div>
<div class="line"><a id="l00440" name="l00440"></a><span class="lineno"> 440</span> }</div>
<div class="line"><a id="l00441" name="l00441"></a><span class="lineno"> 441</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l00442" name="l00442"></a><span class="lineno"> 442</span> updatedMessage = editResponse.Entity;</div>
<div class="line"><a id="l00443" name="l00443"></a><span class="lineno"> 443</span> }</div>
<div class="line"><a id="l00444" name="l00444"></a><span class="lineno"> 444</span> </div>
<div class="line"><a id="l00445" name="l00445"></a><span class="lineno"> 445</span> <span class="keywordflow">return</span> async (active) =&gt;</div>
<div class="line"><a id="l00446" name="l00446"></a><span class="lineno"> 446</span> {</div>
<div class="line"><a id="l00447" name="l00447"></a><span class="lineno"> 447</span> <span class="keywordflow">if</span> (updatedMessage == <span class="keyword">null</span> || errorMessage != <span class="keyword">null</span>)</div>
<div class="line"><a id="l00448" name="l00448"></a><span class="lineno"> 448</span> <span class="keywordflow">return</span>;</div>
<div class="line"><a id="l00449" name="l00449"></a><span class="lineno"> 449</span> </div>
<div class="line"><a id="l00450" name="l00450"></a><span class="lineno"> 450</span> <span class="keywordflow">if</span> (active)</div>
<div class="line"><a id="l00451" name="l00451"></a><span class="lineno"> 451</span> {</div>
<div class="line"><a id="l00452" name="l00452"></a><span class="lineno"> 452</span> completionString = <span class="stringliteral">&quot;Succeeded&quot;</span>;</div>
<div class="line"><a id="l00453" name="l00453"></a><span class="lineno"> 453</span> updatedMessageText = $<span class="stringliteral">&quot;{prefix}: Deployment succeeded!&quot;</span>;</div>
<div class="line"><a id="l00454" name="l00454"></a><span class="lineno"> 454</span> embed = CreateUpdatedEmbed(</div>
<div class="line"><a id="l00455" name="l00455"></a><span class="lineno"> 455</span> <span class="stringliteral">&quot;The deployment completed successfully and was applied to server.&quot;</span>,</div>
<div class="line"><a id="l00456" name="l00456"></a><span class="lineno"> 456</span> Color.Green);</div>
<div class="line"><a id="l00457" name="l00457"></a><span class="lineno"> 457</span> }</div>
<div class="line"><a id="l00458" name="l00458"></a><span class="lineno"> 458</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l00459" name="l00459"></a><span class="lineno"> 459</span> {</div>
<div class="line"><a id="l00460" name="l00460"></a><span class="lineno"> 460</span> completionString = <span class="stringliteral">&quot;Inactive&quot;</span>;</div>
<div class="line"><a id="l00461" name="l00461"></a><span class="lineno"> 461</span> embed = CreateUpdatedEmbed(</div>
<div class="line"><a id="l00462" name="l00462"></a><span class="lineno"> 462</span> <span class="stringliteral">&quot;This deployment has been superceeded by a new one.&quot;</span>,</div>
<div class="line"><a id="l00463" name="l00463"></a><span class="lineno"> 463</span> Color.Gray);</div>
<div class="line"><a id="l00464" name="l00464"></a><span class="lineno"> 464</span> }</div>
<div class="line"><a id="l00465" name="l00465"></a><span class="lineno"> 465</span> </div>
<div class="line"><a id="l00466" name="l00466"></a><span class="lineno"> 466</span> var editResponse = await channelsClient.EditMessageAsync(</div>
<div class="line"><a id="l00467" name="l00467"></a><span class="lineno"> 467</span> <span class="keyword">new</span> Snowflake(channelId),</div>
<div class="line"><a id="l00468" name="l00468"></a><span class="lineno"> 468</span> updatedMessage.ID,</div>
<div class="line"><a id="l00469" name="l00469"></a><span class="lineno"> 469</span> updatedMessageText,</div>
<div class="line"><a id="l00470" name="l00470"></a><span class="lineno"> 470</span> embeds: <span class="keyword">new</span> List&lt;IEmbed&gt; { embed },</div>
<div class="line"><a id="l00471" name="l00471"></a><span class="lineno"> 471</span> ct: cancellationToken);</div>
<div class="line"><a id="l00472" name="l00472"></a><span class="lineno"> 472</span> </div>
<div class="line"><a id="l00473" name="l00473"></a><span class="lineno"> 473</span> <span class="keywordflow">if</span> (!editResponse.IsSuccess)</div>
<div class="line"><a id="l00474" name="l00474"></a><span class="lineno"> 474</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00475" name="l00475"></a><span class="lineno"> 475</span> <span class="stringliteral">&quot;Finalizing deploy embed {messageId} failed: {result}&quot;</span>,</div>
<div class="line"><a id="l00476" name="l00476"></a><span class="lineno"> 476</span> messageResponse.Entity.ID,</div>
<div class="line"><a id="l00477" name="l00477"></a><span class="lineno"> 477</span> editResponse.LogFormat());</div>
<div class="line"><a id="l00478" name="l00478"></a><span class="lineno"> 478</span> };</div>
<div class="line"><a id="l00479" name="l00479"></a><span class="lineno"> 479</span> };</div>
<div class="line"><a id="l00480" name="l00480"></a><span class="lineno"> 480</span> }</div>
</div>
<div class="line"><a id="l00481" name="l00481"></a><span class="lineno"> 481</span> </div>
<div class="foldopen" id="foldopen00483" data-start="{" data-end="}">
<div class="line"><a id="l00483" name="l00483"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a8d7bbc5ddb64df2800554c354ff1974a"> 483</a></span> <span class="keyword">public</span> async Task&lt;Result&gt; <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a8d7bbc5ddb64df2800554c354ff1974a">RespondAsync</a>(IMessageCreate messageCreateEvent, CancellationToken cancellationToken)</div>
<div class="line"><a id="l00484" name="l00484"></a><span class="lineno"> 484</span> {</div>
<div class="line"><a id="l00485" name="l00485"></a><span class="lineno"> 485</span> ArgumentNullException.ThrowIfNull(messageCreateEvent);</div>
<div class="line"><a id="l00486" name="l00486"></a><span class="lineno"> 486</span> </div>
<div class="line"><a id="l00487" name="l00487"></a><span class="lineno"> 487</span> <span class="keywordflow">if</span> ((messageCreateEvent.Type != MessageType.Default</div>
<div class="line"><a id="l00488" name="l00488"></a><span class="lineno"> 488</span> &amp;&amp; messageCreateEvent.Type != MessageType.InlineReply)</div>
<div class="line"><a id="l00489" name="l00489"></a><span class="lineno"> 489</span> || messageCreateEvent.Author.ID == <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a38455db633742e90572b9a83aa681831">currentUserId</a>)</div>
<div class="line"><a id="l00490" name="l00490"></a><span class="lineno"> 490</span> <span class="keywordflow">return</span> Result.FromSuccess();</div>
<div class="line"><a id="l00491" name="l00491"></a><span class="lineno"> 491</span> </div>
<div class="line"><a id="l00492" name="l00492"></a><span class="lineno"> 492</span> var messageReference = <span class="keyword">new</span> MessageReference</div>
<div class="line"><a id="l00493" name="l00493"></a><span class="lineno"> 493</span> {</div>
<div class="line"><a id="l00494" name="l00494"></a><span class="lineno"> 494</span> ChannelID = messageCreateEvent.ChannelID,</div>
<div class="line"><a id="l00495" name="l00495"></a><span class="lineno"> 495</span> GuildID = messageCreateEvent.GuildID,</div>
<div class="line"><a id="l00496" name="l00496"></a><span class="lineno"> 496</span> MessageID = messageCreateEvent.ID,</div>
<div class="line"><a id="l00497" name="l00497"></a><span class="lineno"> 497</span> FailIfNotExists = <span class="keyword">false</span>,</div>
<div class="line"><a id="l00498" name="l00498"></a><span class="lineno"> 498</span> };</div>
<div class="line"><a id="l00499" name="l00499"></a><span class="lineno"> 499</span> </div>
<div class="line"><a id="l00500" name="l00500"></a><span class="lineno"> 500</span> var channelsClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestChannelAPI&gt;();</div>
<div class="line"><a id="l00501" name="l00501"></a><span class="lineno"> 501</span> var channelResponse = await channelsClient.GetChannelAsync(messageCreateEvent.ChannelID, cancellationToken);</div>
<div class="line"><a id="l00502" name="l00502"></a><span class="lineno"> 502</span> <span class="keywordflow">if</span> (!channelResponse.IsSuccess)</div>
<div class="line"><a id="l00503" name="l00503"></a><span class="lineno"> 503</span> {</div>
<div class="line"><a id="l00504" name="l00504"></a><span class="lineno"> 504</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00505" name="l00505"></a><span class="lineno"> 505</span> <span class="stringliteral">&quot;Failed to get channel {channelId} in response to message {messageId}!&quot;</span>,</div>
<div class="line"><a id="l00506" name="l00506"></a><span class="lineno"> 506</span> messageCreateEvent.ChannelID,</div>
<div class="line"><a id="l00507" name="l00507"></a><span class="lineno"> 507</span> messageCreateEvent.ID);</div>
<div class="line"><a id="l00508" name="l00508"></a><span class="lineno"> 508</span> </div>
<div class="line"><a id="l00509" name="l00509"></a><span class="lineno"> 509</span> <span class="comment">// we&#39;ll handle the errors ourselves</span></div>
<div class="line"><a id="l00510" name="l00510"></a><span class="lineno"> 510</span> <span class="keywordflow">return</span> Result.FromSuccess();</div>
<div class="line"><a id="l00511" name="l00511"></a><span class="lineno"> 511</span> }</div>
<div class="line"><a id="l00512" name="l00512"></a><span class="lineno"> 512</span> </div>
<div class="line"><a id="l00513" name="l00513"></a><span class="lineno"> 513</span> var pm = channelResponse.Entity.Type == ChannelType.DM || channelResponse.Entity.Type == ChannelType.GroupDM;</div>
<div class="line"><a id="l00514" name="l00514"></a><span class="lineno"> 514</span> var shouldNotAnswer = !pm;</div>
<div class="line"><a id="l00515" name="l00515"></a><span class="lineno"> 515</span> <span class="keywordflow">if</span> (shouldNotAnswer)</div>
<div class="line"><a id="l00516" name="l00516"></a><span class="lineno"> 516</span> lock (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>)</div>
<div class="line"><a id="l00517" name="l00517"></a><span class="lineno"> 517</span> shouldNotAnswer = !<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>.Contains(messageCreateEvent.ChannelID.Value) &amp;&amp; !<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>.Contains(0);</div>
<div class="line"><a id="l00518" name="l00518"></a><span class="lineno"> 518</span> </div>
<div class="line"><a id="l00519" name="l00519"></a><span class="lineno"> 519</span> var content = <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3cf5b9ba9079d6c9f582f61b5894f7c1">NormalizeMentions</a>(messageCreateEvent.Content);</div>
<div class="line"><a id="l00520" name="l00520"></a><span class="lineno"> 520</span> var mentionedUs = messageCreateEvent.Mentions.Any(x =&gt; x.ID == <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a38455db633742e90572b9a83aa681831">currentUserId</a>)</div>
<div class="line"><a id="l00521" name="l00521"></a><span class="lineno"> 521</span> || (!shouldNotAnswer &amp;&amp; content.Split(<span class="charliteral">&#39; &#39;</span>).First().Equals(<a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_manager.html">ChatManager</a>.<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_manager.html#a0b5b0d03d129b21de29dc2c2bbf17edf">CommonMention</a>, StringComparison.OrdinalIgnoreCase));</div>
<div class="line"><a id="l00522" name="l00522"></a><span class="lineno"> 522</span> </div>
<div class="line"><a id="l00523" name="l00523"></a><span class="lineno"> 523</span> <span class="keywordflow">if</span> (shouldNotAnswer)</div>
<div class="line"><a id="l00524" name="l00524"></a><span class="lineno"> 524</span> {</div>
<div class="line"><a id="l00525" name="l00525"></a><span class="lineno"> 525</span> <span class="keywordflow">if</span> (mentionedUs)</div>
<div class="line"><a id="l00526" name="l00526"></a><span class="lineno"> 526</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogTrace(</div>
<div class="line"><a id="l00527" name="l00527"></a><span class="lineno"> 527</span> <span class="stringliteral">&quot;Ignoring mention from {channelId} ({channelName}) by {authorId} ({authorName}). Channel not mapped!&quot;</span>,</div>
<div class="line"><a id="l00528" name="l00528"></a><span class="lineno"> 528</span> messageCreateEvent.ChannelID,</div>
<div class="line"><a id="l00529" name="l00529"></a><span class="lineno"> 529</span> channelResponse.Entity.Name,</div>
<div class="line"><a id="l00530" name="l00530"></a><span class="lineno"> 530</span> messageCreateEvent.Author.ID,</div>
<div class="line"><a id="l00531" name="l00531"></a><span class="lineno"> 531</span> messageCreateEvent.Author.Username);</div>
<div class="line"><a id="l00532" name="l00532"></a><span class="lineno"> 532</span> </div>
<div class="line"><a id="l00533" name="l00533"></a><span class="lineno"> 533</span> <span class="keywordflow">return</span> Result.FromSuccess();</div>
<div class="line"><a id="l00534" name="l00534"></a><span class="lineno"> 534</span> }</div>
<div class="line"><a id="l00535" name="l00535"></a><span class="lineno"> 535</span> </div>
<div class="line"><a id="l00536" name="l00536"></a><span class="lineno"> 536</span> <span class="keywordtype">string</span> guildName = <span class="stringliteral">&quot;UNKNOWN&quot;</span>;</div>
<div class="line"><a id="l00537" name="l00537"></a><span class="lineno"> 537</span> <span class="keywordflow">if</span> (!pm)</div>
<div class="line"><a id="l00538" name="l00538"></a><span class="lineno"> 538</span> {</div>
<div class="line"><a id="l00539" name="l00539"></a><span class="lineno"> 539</span> var guildsClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestGuildAPI&gt;();</div>
<div class="line"><a id="l00540" name="l00540"></a><span class="lineno"> 540</span> var messageGuildResponse = await guildsClient.GetGuildAsync(messageCreateEvent.GuildID.Value, <span class="keyword">false</span>, cancellationToken);</div>
<div class="line"><a id="l00541" name="l00541"></a><span class="lineno"> 541</span> <span class="keywordflow">if</span> (messageGuildResponse.IsSuccess)</div>
<div class="line"><a id="l00542" name="l00542"></a><span class="lineno"> 542</span> guildName = messageGuildResponse.Entity.Name;</div>
<div class="line"><a id="l00543" name="l00543"></a><span class="lineno"> 543</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l00544" name="l00544"></a><span class="lineno"> 544</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00545" name="l00545"></a><span class="lineno"> 545</span> <span class="stringliteral">&quot;Failed to get channel {channelID} in response to message {messageID}: {result}&quot;</span>,</div>
<div class="line"><a id="l00546" name="l00546"></a><span class="lineno"> 546</span> messageCreateEvent.ChannelID,</div>
<div class="line"><a id="l00547" name="l00547"></a><span class="lineno"> 547</span> messageCreateEvent.ID,</div>
<div class="line"><a id="l00548" name="l00548"></a><span class="lineno"> 548</span> messageGuildResponse.LogFormat());</div>
<div class="line"><a id="l00549" name="l00549"></a><span class="lineno"> 549</span> }</div>
<div class="line"><a id="l00550" name="l00550"></a><span class="lineno"> 550</span> </div>
<div class="line"><a id="l00551" name="l00551"></a><span class="lineno"> 551</span> var result = <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_message.html">DiscordMessage</a>(</div>
<div class="line"><a id="l00552" name="l00552"></a><span class="lineno"> 552</span> <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_user.html">ChatUser</a>(</div>
<div class="line"><a id="l00553" name="l00553"></a><span class="lineno"> 553</span> <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html">ChannelRepresentation</a>(</div>
<div class="line"><a id="l00554" name="l00554"></a><span class="lineno"> 554</span> pm ? messageCreateEvent.Author.Username : guildName,</div>
<div class="line"><a id="l00555" name="l00555"></a><span class="lineno"> 555</span> channelResponse.Entity.Name.Value!,</div>
<div class="line"><a id="l00556" name="l00556"></a><span class="lineno"> 556</span> messageCreateEvent.ChannelID.Value)</div>
<div class="line"><a id="l00557" name="l00557"></a><span class="lineno"> 557</span> {</div>
<div class="line"><a id="l00558" name="l00558"></a><span class="lineno"> 558</span> IsPrivateChannel = pm,</div>
<div class="line"><a id="l00559" name="l00559"></a><span class="lineno"> 559</span> EmbedsSupported = <span class="keyword">true</span>,</div>
<div class="line"><a id="l00560" name="l00560"></a><span class="lineno"> 560</span> </div>
<div class="line"><a id="l00561" name="l00561"></a><span class="lineno"> 561</span> <span class="comment">// isAdmin and Tag populated by manager</span></div>
<div class="line"><a id="l00562" name="l00562"></a><span class="lineno"> 562</span> },</div>
<div class="line"><a id="l00563" name="l00563"></a><span class="lineno"> 563</span> messageCreateEvent.Author.Username,</div>
<div class="line"><a id="l00564" name="l00564"></a><span class="lineno"> 564</span> <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3cf5b9ba9079d6c9f582f61b5894f7c1">NormalizeMentions</a>($<span class="stringliteral">&quot;&lt;@{messageCreateEvent.Author.ID}&gt;&quot;</span>),</div>
<div class="line"><a id="l00565" name="l00565"></a><span class="lineno"> 565</span> messageCreateEvent.Author.ID.Value),</div>
<div class="line"><a id="l00566" name="l00566"></a><span class="lineno"> 566</span> content,</div>
<div class="line"><a id="l00567" name="l00567"></a><span class="lineno"> 567</span> messageReference);</div>
<div class="line"><a id="l00568" name="l00568"></a><span class="lineno"> 568</span> </div>
<div class="line"><a id="l00569" name="l00569"></a><span class="lineno"> 569</span> <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#a6a6dd225ccb27e30c2cc06562b035ebe">EnqueueMessage</a>(result);</div>
<div class="line"><a id="l00570" name="l00570"></a><span class="lineno"> 570</span> <span class="keywordflow">return</span> Result.FromSuccess();</div>
<div class="line"><a id="l00571" name="l00571"></a><span class="lineno"> 571</span> }</div>
</div>
<div class="line"><a id="l00572" name="l00572"></a><span class="lineno"> 572</span> </div>
<div class="foldopen" id="foldopen00574" data-start="{" data-end="}">
<div class="line"><a id="l00574" name="l00574"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#addfb0baffffb90712e76e9bfc1800a15"> 574</a></span> <span class="keyword">public</span> Task&lt;Result&gt; <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#addfb0baffffb90712e76e9bfc1800a15">RespondAsync</a>(IReady readyEvent, CancellationToken cancellationToken)</div>
<div class="line"><a id="l00575" name="l00575"></a><span class="lineno"> 575</span> {</div>
<div class="line"><a id="l00576" name="l00576"></a><span class="lineno"> 576</span> ArgumentNullException.ThrowIfNull(readyEvent);</div>
<div class="line"><a id="l00577" name="l00577"></a><span class="lineno"> 577</span> </div>
<div class="line"><a id="l00578" name="l00578"></a><span class="lineno"> 578</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogTrace(<span class="stringliteral">&quot;Gatway ready. Version: {version}&quot;</span>, readyEvent.Version);</div>
<div class="line"><a id="l00579" name="l00579"></a><span class="lineno"> 579</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3f81033139026af1ea3160ef0063e737">gatewayReadyTcs</a>?.TrySetResult();</div>
<div class="line"><a id="l00580" name="l00580"></a><span class="lineno"> 580</span> <span class="keywordflow">return</span> Task.FromResult(Result.FromSuccess());</div>
<div class="line"><a id="l00581" name="l00581"></a><span class="lineno"> 581</span> }</div>
</div>
<div class="line"><a id="l00582" name="l00582"></a><span class="lineno"> 582</span> </div>
<div class="foldopen" id="foldopen00584" data-start="{" data-end="}">
<div class="line"><a id="l00584" name="l00584"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3fd130f635e4577bedefa9926a4e2c73"> 584</a></span> <span class="keyword">protected</span> <span class="keyword">override</span> async ValueTask <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3fd130f635e4577bedefa9926a4e2c73">Connect</a>(CancellationToken cancellationToken)</div>
<div class="line"><a id="l00585" name="l00585"></a><span class="lineno"> 585</span> {</div>
<div class="line"><a id="l00586" name="l00586"></a><span class="lineno"> 586</span> <span class="keywordflow">try</span></div>
<div class="line"><a id="l00587" name="l00587"></a><span class="lineno"> 587</span> {</div>
<div class="line"><a id="l00588" name="l00588"></a><span class="lineno"> 588</span> lock (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a01881ab9506db0431f75db21224bf7e6">connectDisconnectLock</a>)</div>
<div class="line"><a id="l00589" name="l00589"></a><span class="lineno"> 589</span> {</div>
<div class="line"><a id="l00590" name="l00590"></a><span class="lineno"> 590</span> <span class="keywordflow">if</span> (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">gatewayCts</a> != <span class="keyword">null</span>)</div>
<div class="line"><a id="l00591" name="l00591"></a><span class="lineno"> 591</span> <span class="keywordflow">throw</span> <span class="keyword">new</span> InvalidOperationException(<span class="stringliteral">&quot;Discord gateway still active!&quot;</span>);</div>
<div class="line"><a id="l00592" name="l00592"></a><span class="lineno"> 592</span> </div>
<div class="line"><a id="l00593" name="l00593"></a><span class="lineno"> 593</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">gatewayCts</a> = <span class="keyword">new</span> CancellationTokenSource();</div>
<div class="line"><a id="l00594" name="l00594"></a><span class="lineno"> 594</span> }</div>
<div class="line"><a id="l00595" name="l00595"></a><span class="lineno"> 595</span> </div>
<div class="line"><a id="l00596" name="l00596"></a><span class="lineno"> 596</span> var gatewayCancellationToken = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">gatewayCts</a>.Token;</div>
<div class="line"><a id="l00597" name="l00597"></a><span class="lineno"> 597</span> var gatewayClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;DiscordGatewayClient&gt;();</div>
<div class="line"><a id="l00598" name="l00598"></a><span class="lineno"> 598</span> </div>
<div class="line"><a id="l00599" name="l00599"></a><span class="lineno"> 599</span> Task&lt;Result&gt; localGatewayTask;</div>
<div class="line"><a id="l00600" name="l00600"></a><span class="lineno"> 600</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3f81033139026af1ea3160ef0063e737">gatewayReadyTcs</a> = <span class="keyword">new</span> TaskCompletionSource();</div>
<div class="line"><a id="l00601" name="l00601"></a><span class="lineno"> 601</span> </div>
<div class="line"><a id="l00602" name="l00602"></a><span class="lineno"> 602</span> <span class="keyword">using </span>var gatewayConnectionAbortRegistration = cancellationToken.Register(() =&gt; <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3f81033139026af1ea3160ef0063e737">gatewayReadyTcs</a>.TrySetCanceled(cancellationToken));</div>
<div class="line"><a id="l00603" name="l00603"></a><span class="lineno"> 603</span> gatewayCancellationToken.Register(() =&gt; <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogTrace(<span class="stringliteral">&quot;Stopping gateway client...&quot;</span>));</div>
<div class="line"><a id="l00604" name="l00604"></a><span class="lineno"> 604</span> </div>
<div class="line"><a id="l00605" name="l00605"></a><span class="lineno"> 605</span> <span class="comment">// reconnects keep happening until we stop or it faults, our auto-reconnector will handle the latter</span></div>
<div class="line"><a id="l00606" name="l00606"></a><span class="lineno"> 606</span> localGatewayTask = gatewayClient.RunAsync(gatewayCancellationToken);</div>
<div class="line"><a id="l00607" name="l00607"></a><span class="lineno"> 607</span> <span class="keywordflow">try</span></div>
<div class="line"><a id="l00608" name="l00608"></a><span class="lineno"> 608</span> {</div>
<div class="line"><a id="l00609" name="l00609"></a><span class="lineno"> 609</span> await Task.WhenAny(<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3f81033139026af1ea3160ef0063e737">gatewayReadyTcs</a>.Task, localGatewayTask);</div>
<div class="line"><a id="l00610" name="l00610"></a><span class="lineno"> 610</span> </div>
<div class="line"><a id="l00611" name="l00611"></a><span class="lineno"> 611</span> cancellationToken.ThrowIfCancellationRequested();</div>
<div class="line"><a id="l00612" name="l00612"></a><span class="lineno"> 612</span> <span class="keywordflow">if</span> (localGatewayTask.IsCompleted)</div>
<div class="line"><a id="l00613" name="l00613"></a><span class="lineno"> 613</span> <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(<a class="code hl_enumeration" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.ChatCannotConnectProvider);</div>
<div class="line"><a id="l00614" name="l00614"></a><span class="lineno"> 614</span> </div>
<div class="line"><a id="l00615" name="l00615"></a><span class="lineno"> 615</span> var userClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestUserAPI&gt;();</div>
<div class="line"><a id="l00616" name="l00616"></a><span class="lineno"> 616</span> </div>
<div class="line"><a id="l00617" name="l00617"></a><span class="lineno"> 617</span> <span class="keyword">using </span>var localCombinedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, gatewayCancellationToken);</div>
<div class="line"><a id="l00618" name="l00618"></a><span class="lineno"> 618</span> var localCombinedCancellationToken = localCombinedCts.Token;</div>
<div class="line"><a id="l00619" name="l00619"></a><span class="lineno"> 619</span> var currentUserResult = await userClient.GetCurrentUserAsync(localCombinedCancellationToken);</div>
<div class="line"><a id="l00620" name="l00620"></a><span class="lineno"> 620</span> <span class="keywordflow">if</span> (!currentUserResult.IsSuccess)</div>
<div class="line"><a id="l00621" name="l00621"></a><span class="lineno"> 621</span> {</div>
<div class="line"><a id="l00622" name="l00622"></a><span class="lineno"> 622</span> localCombinedCancellationToken.ThrowIfCancellationRequested();</div>
<div class="line"><a id="l00623" name="l00623"></a><span class="lineno"> 623</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(<span class="stringliteral">&quot;Unable to retrieve current user: {result}&quot;</span>, currentUserResult.LogFormat());</div>
<div class="line"><a id="l00624" name="l00624"></a><span class="lineno"> 624</span> <span class="keywordflow">throw</span> <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">JobException</a>(<a class="code hl_enumeration" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">ErrorCode</a>.ChatCannotConnectProvider);</div>
<div class="line"><a id="l00625" name="l00625"></a><span class="lineno"> 625</span> }</div>
<div class="line"><a id="l00626" name="l00626"></a><span class="lineno"> 626</span> </div>
<div class="line"><a id="l00627" name="l00627"></a><span class="lineno"> 627</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a38455db633742e90572b9a83aa681831">currentUserId</a> = currentUserResult.Entity.ID;</div>
<div class="line"><a id="l00628" name="l00628"></a><span class="lineno"> 628</span> }</div>
<div class="line"><a id="l00629" name="l00629"></a><span class="lineno"> 629</span> <span class="keywordflow">finally</span></div>
<div class="line"><a id="l00630" name="l00630"></a><span class="lineno"> 630</span> {</div>
<div class="line"><a id="l00631" name="l00631"></a><span class="lineno"> 631</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a968f8dd1140ebe40a77c774fe7f9019b">gatewayTask</a> = localGatewayTask;</div>
<div class="line"><a id="l00632" name="l00632"></a><span class="lineno"> 632</span> }</div>
<div class="line"><a id="l00633" name="l00633"></a><span class="lineno"> 633</span> }</div>
<div class="line"><a id="l00634" name="l00634"></a><span class="lineno"> 634</span> <span class="keywordflow">catch</span></div>
<div class="line"><a id="l00635" name="l00635"></a><span class="lineno"> 635</span> {</div>
<div class="line"><a id="l00636" name="l00636"></a><span class="lineno"> 636</span> <span class="comment">// will handle cleanup</span></div>
<div class="line"><a id="l00637" name="l00637"></a><span class="lineno"> 637</span> <span class="comment">// DCT: Musn&#39;t abort</span></div>
<div class="line"><a id="l00638" name="l00638"></a><span class="lineno"> 638</span> await <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a9998d613750e44e779ae89931f7cfd98">DisconnectImpl</a>(CancellationToken.None);</div>
<div class="line"><a id="l00639" name="l00639"></a><span class="lineno"> 639</span> <span class="keywordflow">throw</span>;</div>
<div class="line"><a id="l00640" name="l00640"></a><span class="lineno"> 640</span> }</div>
<div class="line"><a id="l00641" name="l00641"></a><span class="lineno"> 641</span> }</div>
</div>
<div class="line"><a id="l00642" name="l00642"></a><span class="lineno"> 642</span> </div>
<div class="foldopen" id="foldopen00644" data-start="{" data-end="}">
<div class="line"><a id="l00644" name="l00644"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a9998d613750e44e779ae89931f7cfd98"> 644</a></span> <span class="keyword">protected</span> <span class="keyword">override</span> async ValueTask <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a9998d613750e44e779ae89931f7cfd98">DisconnectImpl</a>(CancellationToken cancellationToken)</div>
<div class="line"><a id="l00645" name="l00645"></a><span class="lineno"> 645</span> {</div>
<div class="line"><a id="l00646" name="l00646"></a><span class="lineno"> 646</span> Task&lt;Result&gt; localGatewayTask;</div>
<div class="line"><a id="l00647" name="l00647"></a><span class="lineno"> 647</span> CancellationTokenSource localGatewayCts;</div>
<div class="line"><a id="l00648" name="l00648"></a><span class="lineno"> 648</span> lock (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a01881ab9506db0431f75db21224bf7e6">connectDisconnectLock</a>)</div>
<div class="line"><a id="l00649" name="l00649"></a><span class="lineno"> 649</span> {</div>
<div class="line"><a id="l00650" name="l00650"></a><span class="lineno"> 650</span> localGatewayTask = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a968f8dd1140ebe40a77c774fe7f9019b">gatewayTask</a>!;</div>
<div class="line"><a id="l00651" name="l00651"></a><span class="lineno"> 651</span> localGatewayCts = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">gatewayCts</a>!;</div>
<div class="line"><a id="l00652" name="l00652"></a><span class="lineno"> 652</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a968f8dd1140ebe40a77c774fe7f9019b">gatewayTask</a> = <span class="keyword">null</span>;</div>
<div class="line"><a id="l00653" name="l00653"></a><span class="lineno"> 653</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">gatewayCts</a> = <span class="keyword">null</span>;</div>
<div class="line"><a id="l00654" name="l00654"></a><span class="lineno"> 654</span> <span class="keywordflow">if</span> (localGatewayTask == <span class="keyword">null</span>)</div>
<div class="line"><a id="l00655" name="l00655"></a><span class="lineno"> 655</span> <span class="keywordflow">return</span>;</div>
<div class="line"><a id="l00656" name="l00656"></a><span class="lineno"> 656</span> }</div>
<div class="line"><a id="l00657" name="l00657"></a><span class="lineno"> 657</span> </div>
<div class="line"><a id="l00658" name="l00658"></a><span class="lineno"> 658</span> localGatewayCts.Cancel();</div>
<div class="line"><a id="l00659" name="l00659"></a><span class="lineno"> 659</span> var gatewayResult = await localGatewayTask;</div>
<div class="line"><a id="l00660" name="l00660"></a><span class="lineno"> 660</span> </div>
<div class="line"><a id="l00661" name="l00661"></a><span class="lineno"> 661</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogTrace(<span class="stringliteral">&quot;Gateway task complete&quot;</span>);</div>
<div class="line"><a id="l00662" name="l00662"></a><span class="lineno"> 662</span> <span class="keywordflow">if</span> (!gatewayResult.IsSuccess)</div>
<div class="line"><a id="l00663" name="l00663"></a><span class="lineno"> 663</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(<span class="stringliteral">&quot;Gateway issue: {result}&quot;</span>, gatewayResult.LogFormat());</div>
<div class="line"><a id="l00664" name="l00664"></a><span class="lineno"> 664</span> </div>
<div class="line"><a id="l00665" name="l00665"></a><span class="lineno"> 665</span> localGatewayCts.Dispose();</div>
<div class="line"><a id="l00666" name="l00666"></a><span class="lineno"> 666</span> }</div>
</div>
<div class="line"><a id="l00667" name="l00667"></a><span class="lineno"> 667</span> </div>
<div class="foldopen" id="foldopen00669" data-start="{" data-end="}">
<div class="line"><a id="l00669" name="l00669"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a48adcd32348dbab4150bd2c8087623e0"> 669</a></span> <span class="keyword">protected</span> <span class="keyword">override</span> async ValueTask&lt;Dictionary&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;&gt; <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a48adcd32348dbab4150bd2c8087623e0">MapChannelsImpl</a>(IEnumerable&lt;Models.ChatChannel&gt; channels, CancellationToken cancellationToken)</div>
<div class="line"><a id="l00670" name="l00670"></a><span class="lineno"> 670</span> {</div>
<div class="line"><a id="l00671" name="l00671"></a><span class="lineno"> 671</span> ArgumentNullException.ThrowIfNull(channels);</div>
<div class="line"><a id="l00672" name="l00672"></a><span class="lineno"> 672</span> </div>
<div class="line"><a id="l00673" name="l00673"></a><span class="lineno"> 673</span> var remapRequired = <span class="keyword">false</span>;</div>
<div class="line"><a id="l00674" name="l00674"></a><span class="lineno"> 674</span> var guildsClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestGuildAPI&gt;();</div>
<div class="line"><a id="l00675" name="l00675"></a><span class="lineno"> 675</span> var guildTasks = <span class="keyword">new</span> ConcurrentDictionary&lt;Snowflake, Task&lt;Result&lt;IGuild&gt;&gt;&gt;();</div>
<div class="line"><a id="l00676" name="l00676"></a><span class="lineno"> 676</span> </div>
<div class="line"><a id="l00677" name="l00677"></a><span class="lineno"> 677</span> async ValueTask&lt;Tuple&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;?&gt; GetModelChannelFromDBChannel(Models.ChatChannel channelFromDB)</div>
<div class="line"><a id="l00678" name="l00678"></a><span class="lineno"> 678</span> {</div>
<div class="line"><a id="l00679" name="l00679"></a><span class="lineno"> 679</span> <span class="keywordflow">if</span> (!channelFromDB.DiscordChannelId.HasValue)</div>
<div class="line"><a id="l00680" name="l00680"></a><span class="lineno"> 680</span> <span class="keywordflow">throw</span> <span class="keyword">new</span> InvalidOperationException(<span class="stringliteral">&quot;ChatChannel missing DiscordChannelId!&quot;</span>);</div>
<div class="line"><a id="l00681" name="l00681"></a><span class="lineno"> 681</span> </div>
<div class="line"><a id="l00682" name="l00682"></a><span class="lineno"> 682</span> var channelId = channelFromDB.DiscordChannelId.Value;</div>
<div class="line"><a id="l00683" name="l00683"></a><span class="lineno"> 683</span> var channelsClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestChannelAPI&gt;();</div>
<div class="line"><a id="l00684" name="l00684"></a><span class="lineno"> 684</span> var discordChannelResponse = await channelsClient.GetChannelAsync(<span class="keyword">new</span> Snowflake(channelId), cancellationToken);</div>
<div class="line"><a id="l00685" name="l00685"></a><span class="lineno"> 685</span> <span class="keywordflow">if</span> (!discordChannelResponse.IsSuccess)</div>
<div class="line"><a id="l00686" name="l00686"></a><span class="lineno"> 686</span> {</div>
<div class="line"><a id="l00687" name="l00687"></a><span class="lineno"> 687</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00688" name="l00688"></a><span class="lineno"> 688</span> <span class="stringliteral">&quot;Error retrieving discord channel {channelId}: {result}&quot;</span>,</div>
<div class="line"><a id="l00689" name="l00689"></a><span class="lineno"> 689</span> channelId,</div>
<div class="line"><a id="l00690" name="l00690"></a><span class="lineno"> 690</span> discordChannelResponse.LogFormat());</div>
<div class="line"><a id="l00691" name="l00691"></a><span class="lineno"> 691</span> </div>
<div class="line"><a id="l00692" name="l00692"></a><span class="lineno"> 692</span> var remapConditional = !(discordChannelResponse.Error is RestResultError&lt;RestError&gt; restResultError</div>
<div class="line"><a id="l00693" name="l00693"></a><span class="lineno"> 693</span> &amp;&amp; (restResultError.Error?.Code == DiscordError.MissingAccess</div>
<div class="line"><a id="l00694" name="l00694"></a><span class="lineno"> 694</span> || restResultError.Error?.Code == DiscordError.UnknownChannel));</div>
<div class="line"><a id="l00695" name="l00695"></a><span class="lineno"> 695</span> </div>
<div class="line"><a id="l00696" name="l00696"></a><span class="lineno"> 696</span> <span class="keywordflow">if</span> (remapConditional)</div>
<div class="line"><a id="l00697" name="l00697"></a><span class="lineno"> 697</span> {</div>
<div class="line"><a id="l00698" name="l00698"></a><span class="lineno"> 698</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.Log(</div>
<div class="line"><a id="l00699" name="l00699"></a><span class="lineno"> 699</span> remapRequired</div>
<div class="line"><a id="l00700" name="l00700"></a><span class="lineno"> 700</span> ? LogLevel.Trace</div>
<div class="line"><a id="l00701" name="l00701"></a><span class="lineno"> 701</span> : LogLevel.Debug,</div>
<div class="line"><a id="l00702" name="l00702"></a><span class="lineno"> 702</span> <span class="stringliteral">&quot;Error on channel {channelId} is not an access/thread issue. Will retry remap...&quot;</span>,</div>
<div class="line"><a id="l00703" name="l00703"></a><span class="lineno"> 703</span> channelId);</div>
<div class="line"><a id="l00704" name="l00704"></a><span class="lineno"> 704</span> remapRequired = <span class="keyword">true</span>;</div>
<div class="line"><a id="l00705" name="l00705"></a><span class="lineno"> 705</span> }</div>
<div class="line"><a id="l00706" name="l00706"></a><span class="lineno"> 706</span> </div>
<div class="line"><a id="l00707" name="l00707"></a><span class="lineno"> 707</span> <span class="keywordflow">return</span> <span class="keyword">null</span>;</div>
<div class="line"><a id="l00708" name="l00708"></a><span class="lineno"> 708</span> }</div>
<div class="line"><a id="l00709" name="l00709"></a><span class="lineno"> 709</span> </div>
<div class="line"><a id="l00710" name="l00710"></a><span class="lineno"> 710</span> var channelType = discordChannelResponse.Entity.Type;</div>
<div class="line"><a id="l00711" name="l00711"></a><span class="lineno"> 711</span> <span class="keywordflow">if</span> (!<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1896b3a7ddd7b500c2624d3676b64eaf">SupportedGuildChannelTypes</a>.Contains(channelType))</div>
<div class="line"><a id="l00712" name="l00712"></a><span class="lineno"> 712</span> {</div>
<div class="line"><a id="l00713" name="l00713"></a><span class="lineno"> 713</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(<span class="stringliteral">&quot;Cound not map channel {channelId}! Incorrect type: {channelType}&quot;</span>, channelId, discordChannelResponse.Entity.Type);</div>
<div class="line"><a id="l00714" name="l00714"></a><span class="lineno"> 714</span> <span class="keywordflow">return</span> <span class="keyword">null</span>;</div>
<div class="line"><a id="l00715" name="l00715"></a><span class="lineno"> 715</span> }</div>
<div class="line"><a id="l00716" name="l00716"></a><span class="lineno"> 716</span> </div>
<div class="line"><a id="l00717" name="l00717"></a><span class="lineno"> 717</span> var guildId = discordChannelResponse.Entity.GuildID.Value;</div>
<div class="line"><a id="l00718" name="l00718"></a><span class="lineno"> 718</span> </div>
<div class="line"><a id="l00719" name="l00719"></a><span class="lineno"> 719</span> var added = <span class="keyword">false</span>;</div>
<div class="line"><a id="l00720" name="l00720"></a><span class="lineno"> 720</span> var guildsResponse = await guildTasks.GetOrAdd(</div>
<div class="line"><a id="l00721" name="l00721"></a><span class="lineno"> 721</span> guildId,</div>
<div class="line"><a id="l00722" name="l00722"></a><span class="lineno"> 722</span> localGuildId =&gt;</div>
<div class="line"><a id="l00723" name="l00723"></a><span class="lineno"> 723</span> {</div>
<div class="line"><a id="l00724" name="l00724"></a><span class="lineno"> 724</span> added = <span class="keyword">true</span>;</div>
<div class="line"><a id="l00725" name="l00725"></a><span class="lineno"> 725</span> <span class="keywordflow">return</span> guildsClient.GetGuildAsync(</div>
<div class="line"><a id="l00726" name="l00726"></a><span class="lineno"> 726</span> localGuildId,</div>
<div class="line"><a id="l00727" name="l00727"></a><span class="lineno"> 727</span> <span class="keyword">false</span>,</div>
<div class="line"><a id="l00728" name="l00728"></a><span class="lineno"> 728</span> cancellationToken);</div>
<div class="line"><a id="l00729" name="l00729"></a><span class="lineno"> 729</span> });</div>
<div class="line"><a id="l00730" name="l00730"></a><span class="lineno"> 730</span> <span class="keywordflow">if</span> (!guildsResponse.IsSuccess)</div>
<div class="line"><a id="l00731" name="l00731"></a><span class="lineno"> 731</span> {</div>
<div class="line"><a id="l00732" name="l00732"></a><span class="lineno"> 732</span> <span class="keywordflow">if</span> (added)</div>
<div class="line"><a id="l00733" name="l00733"></a><span class="lineno"> 733</span> {</div>
<div class="line"><a id="l00734" name="l00734"></a><span class="lineno"> 734</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00735" name="l00735"></a><span class="lineno"> 735</span> <span class="stringliteral">&quot;Error retrieving discord guild {guildID}: {result}&quot;</span>,</div>
<div class="line"><a id="l00736" name="l00736"></a><span class="lineno"> 736</span> guildId,</div>
<div class="line"><a id="l00737" name="l00737"></a><span class="lineno"> 737</span> guildsResponse.LogFormat());</div>
<div class="line"><a id="l00738" name="l00738"></a><span class="lineno"> 738</span> remapRequired = <span class="keyword">true</span>;</div>
<div class="line"><a id="l00739" name="l00739"></a><span class="lineno"> 739</span> }</div>
<div class="line"><a id="l00740" name="l00740"></a><span class="lineno"> 740</span> </div>
<div class="line"><a id="l00741" name="l00741"></a><span class="lineno"> 741</span> <span class="keywordflow">return</span> <span class="keyword">null</span>;</div>
<div class="line"><a id="l00742" name="l00742"></a><span class="lineno"> 742</span> }</div>
<div class="line"><a id="l00743" name="l00743"></a><span class="lineno"> 743</span> </div>
<div class="line"><a id="l00744" name="l00744"></a><span class="lineno"> 744</span> var connectionName = guildsResponse.Entity.Name;</div>
<div class="line"><a id="l00745" name="l00745"></a><span class="lineno"> 745</span> </div>
<div class="line"><a id="l00746" name="l00746"></a><span class="lineno"> 746</span> var channelModel = <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html">ChannelRepresentation</a>(</div>
<div class="line"><a id="l00747" name="l00747"></a><span class="lineno"> 747</span> guildsResponse.Entity.Name,</div>
<div class="line"><a id="l00748" name="l00748"></a><span class="lineno"> 748</span> discordChannelResponse.Entity.Name.Value!,</div>
<div class="line"><a id="l00749" name="l00749"></a><span class="lineno"> 749</span> channelId)</div>
<div class="line"><a id="l00750" name="l00750"></a><span class="lineno"> 750</span> {</div>
<div class="line"><a id="l00751" name="l00751"></a><span class="lineno"> 751</span> IsAdminChannel = channelFromDB.IsAdminChannel == <span class="keyword">true</span>,</div>
<div class="line"><a id="l00752" name="l00752"></a><span class="lineno"> 752</span> IsPrivateChannel = <span class="keyword">false</span>,</div>
<div class="line"><a id="l00753" name="l00753"></a><span class="lineno"> 753</span> Tag = channelFromDB.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html#ad5ca4b4a856afa45b02ba2ed9c324fce">Tag</a>,</div>
<div class="line"><a id="l00754" name="l00754"></a><span class="lineno"> 754</span> EmbedsSupported = <span class="keyword">true</span>,</div>
<div class="line"><a id="l00755" name="l00755"></a><span class="lineno"> 755</span> };</div>
<div class="line"><a id="l00756" name="l00756"></a><span class="lineno"> 756</span> </div>
<div class="line"><a id="l00757" name="l00757"></a><span class="lineno"> 757</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogTrace(<span class="stringliteral">&quot;Mapped channel {realId}: {friendlyName}&quot;</span>, channelModel.RealId, channelModel.FriendlyName);</div>
<div class="line"><a id="l00758" name="l00758"></a><span class="lineno"> 758</span> <span class="keywordflow">return</span> Tuple.Create&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;(</div>
<div class="line"><a id="l00759" name="l00759"></a><span class="lineno"> 759</span> channelFromDB,</div>
<div class="line"><a id="l00760" name="l00760"></a><span class="lineno"> 760</span> <span class="keyword">new</span> List&lt;ChannelRepresentation&gt; { channelModel });</div>
<div class="line"><a id="l00761" name="l00761"></a><span class="lineno"> 761</span> }</div>
<div class="line"><a id="l00762" name="l00762"></a><span class="lineno"> 762</span> </div>
<div class="line"><a id="l00763" name="l00763"></a><span class="lineno"> 763</span> var tasks = channels</div>
<div class="line"><a id="l00764" name="l00764"></a><span class="lineno"> 764</span> .Where(x =&gt; x.DiscordChannelId != 0)</div>
<div class="line"><a id="l00765" name="l00765"></a><span class="lineno"> 765</span> .Select(GetModelChannelFromDBChannel);</div>
<div class="line"><a id="l00766" name="l00766"></a><span class="lineno"> 766</span> </div>
<div class="line"><a id="l00767" name="l00767"></a><span class="lineno"> 767</span> var channelTuples = await <a class="code hl_class" href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html">ValueTaskExtensions</a>.<a class="code hl_function" href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html#a58adbd94d764754bd3e6c566a5fe7fe3">WhenAll</a>(tasks.ToList());</div>
<div class="line"><a id="l00768" name="l00768"></a><span class="lineno"> 768</span> </div>
<div class="line"><a id="l00769" name="l00769"></a><span class="lineno"> 769</span> var list = channelTuples</div>
<div class="line"><a id="l00770" name="l00770"></a><span class="lineno"> 770</span> .Where(x =&gt; x != <span class="keyword">null</span>)</div>
<div class="line"><a id="l00771" name="l00771"></a><span class="lineno"> 771</span> .Cast&lt;Tuple&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;&gt;() <span class="comment">// NRT my beloathed</span></div>
<div class="line"><a id="l00772" name="l00772"></a><span class="lineno"> 772</span> .ToList();</div>
<div class="line"><a id="l00773" name="l00773"></a><span class="lineno"> 773</span> </div>
<div class="line"><a id="l00774" name="l00774"></a><span class="lineno"> 774</span> var channelIdZeroModel = channels.FirstOrDefault(x =&gt; x.DiscordChannelId == 0);</div>
<div class="line"><a id="l00775" name="l00775"></a><span class="lineno"> 775</span> <span class="keywordflow">if</span> (channelIdZeroModel != <span class="keyword">null</span>)</div>
<div class="line"><a id="l00776" name="l00776"></a><span class="lineno"> 776</span> {</div>
<div class="line"><a id="l00777" name="l00777"></a><span class="lineno"> 777</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogInformation(<span class="stringliteral">&quot;Mapping ALL additional accessible text channels&quot;</span>);</div>
<div class="line"><a id="l00778" name="l00778"></a><span class="lineno"> 778</span> var allAccessibleChannels = await <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab92d4920074cec3e48fa204af595a498">GetAllAccessibleTextChannels</a>(cancellationToken);</div>
<div class="line"><a id="l00779" name="l00779"></a><span class="lineno"> 779</span> var unmappedTextChannels = allAccessibleChannels</div>
<div class="line"><a id="l00780" name="l00780"></a><span class="lineno"> 780</span> .Where(x =&gt; !tasks.Any(task =&gt; task.Result != <span class="keyword">null</span> &amp;&amp; <span class="keyword">new</span> Snowflake(task.Result.Item1.DiscordChannelId!.Value) == x.ID));</div>
<div class="line"><a id="l00781" name="l00781"></a><span class="lineno"> 781</span> </div>
<div class="line"><a id="l00782" name="l00782"></a><span class="lineno"> 782</span> async ValueTask&lt;Tuple&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;&gt; CreateMappingsForUnmappedChannels()</div>
<div class="line"><a id="l00783" name="l00783"></a><span class="lineno"> 783</span> {</div>
<div class="line"><a id="l00784" name="l00784"></a><span class="lineno"> 784</span> var unmappedTasks =</div>
<div class="line"><a id="l00785" name="l00785"></a><span class="lineno"> 785</span> unmappedTextChannels.Select(</div>
<div class="line"><a id="l00786" name="l00786"></a><span class="lineno"> 786</span> async unmappedTextChannel =&gt;</div>
<div class="line"><a id="l00787" name="l00787"></a><span class="lineno"> 787</span> {</div>
<div class="line"><a id="l00788" name="l00788"></a><span class="lineno"> 788</span> var fakeChannelModel = <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_models_1_1_chat_channel.html">Models.ChatChannel</a></div>
<div class="line"><a id="l00789" name="l00789"></a><span class="lineno"> 789</span> {</div>
<div class="line"><a id="l00790" name="l00790"></a><span class="lineno"> 790</span> DiscordChannelId = unmappedTextChannel.ID.Value,</div>
<div class="line"><a id="l00791" name="l00791"></a><span class="lineno"> 791</span> IsAdminChannel = channelIdZeroModel.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_channel_base.html#af9afe694fd82c175dd24e8a0303ee8cf">IsAdminChannel</a>,</div>
<div class="line"><a id="l00792" name="l00792"></a><span class="lineno"> 792</span> Tag = channelIdZeroModel.Tag,</div>
<div class="line"><a id="l00793" name="l00793"></a><span class="lineno"> 793</span> };</div>
<div class="line"><a id="l00794" name="l00794"></a><span class="lineno"> 794</span> </div>
<div class="line"><a id="l00795" name="l00795"></a><span class="lineno"> 795</span> var tuple = await GetModelChannelFromDBChannel(fakeChannelModel);</div>
<div class="line"><a id="l00796" name="l00796"></a><span class="lineno"> 796</span> <span class="keywordflow">return</span> tuple?.Item2.First();</div>
<div class="line"><a id="l00797" name="l00797"></a><span class="lineno"> 797</span> })</div>
<div class="line"><a id="l00798" name="l00798"></a><span class="lineno"> 798</span> .ToList();</div>
<div class="line"><a id="l00799" name="l00799"></a><span class="lineno"> 799</span> </div>
<div class="line"><a id="l00800" name="l00800"></a><span class="lineno"> 800</span> <span class="comment">// Add catch-all channel</span></div>
<div class="line"><a id="l00801" name="l00801"></a><span class="lineno"> 801</span> unmappedTasks.Add(Task.FromResult&lt;<a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html">ChannelRepresentation</a>?&gt;(</div>
<div class="line"><a id="l00802" name="l00802"></a><span class="lineno"> 802</span> <span class="keyword">new</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html">ChannelRepresentation</a>(</div>
<div class="line"><a id="l00803" name="l00803"></a><span class="lineno"> 803</span> <span class="stringliteral">&quot;(Unknown Discord Guilds)&quot;</span>,</div>
<div class="line"><a id="l00804" name="l00804"></a><span class="lineno"> 804</span> <span class="stringliteral">&quot;(Unknown Discord Channels)&quot;</span>,</div>
<div class="line"><a id="l00805" name="l00805"></a><span class="lineno"> 805</span> 0)</div>
<div class="line"><a id="l00806" name="l00806"></a><span class="lineno"> 806</span> {</div>
<div class="line"><a id="l00807" name="l00807"></a><span class="lineno"> 807</span> IsAdminChannel = channelIdZeroModel.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html#a5e3306682c350b0cfac4507762b6d8b1">IsAdminChannel</a>!.Value,</div>
<div class="line"><a id="l00808" name="l00808"></a><span class="lineno"> 808</span> EmbedsSupported = <span class="keyword">true</span>,</div>
<div class="line"><a id="l00809" name="l00809"></a><span class="lineno"> 809</span> Tag = channelIdZeroModel.Tag,</div>
<div class="line"><a id="l00810" name="l00810"></a><span class="lineno"> 810</span> }));</div>
<div class="line"><a id="l00811" name="l00811"></a><span class="lineno"> 811</span> </div>
<div class="line"><a id="l00812" name="l00812"></a><span class="lineno"> 812</span> await Task.WhenAll(unmappedTasks);</div>
<div class="line"><a id="l00813" name="l00813"></a><span class="lineno"> 813</span> <span class="keywordflow">return</span> Tuple.Create&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;(</div>
<div class="line"><a id="l00814" name="l00814"></a><span class="lineno"> 814</span> channelIdZeroModel,</div>
<div class="line"><a id="l00815" name="l00815"></a><span class="lineno"> 815</span> unmappedTasks</div>
<div class="line"><a id="l00816" name="l00816"></a><span class="lineno"> 816</span> .Select(x =&gt; x.Result)</div>
<div class="line"><a id="l00817" name="l00817"></a><span class="lineno"> 817</span> .Where(x =&gt; x != <span class="keyword">null</span>)</div>
<div class="line"><a id="l00818" name="l00818"></a><span class="lineno"> 818</span> .Cast&lt;<a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html">ChannelRepresentation</a>&gt;() <span class="comment">// NRT my beloathed</span></div>
<div class="line"><a id="l00819" name="l00819"></a><span class="lineno"> 819</span> .ToList());</div>
<div class="line"><a id="l00820" name="l00820"></a><span class="lineno"> 820</span> }</div>
<div class="line"><a id="l00821" name="l00821"></a><span class="lineno"> 821</span> </div>
<div class="line"><a id="l00822" name="l00822"></a><span class="lineno"> 822</span> var task = CreateMappingsForUnmappedChannels();</div>
<div class="line"><a id="l00823" name="l00823"></a><span class="lineno"> 823</span> var tuple = await task;</div>
<div class="line"><a id="l00824" name="l00824"></a><span class="lineno"> 824</span> list.Add(tuple);</div>
<div class="line"><a id="l00825" name="l00825"></a><span class="lineno"> 825</span> }</div>
<div class="line"><a id="l00826" name="l00826"></a><span class="lineno"> 826</span> </div>
<div class="line"><a id="l00827" name="l00827"></a><span class="lineno"> 827</span> lock (<a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>)</div>
<div class="line"><a id="l00828" name="l00828"></a><span class="lineno"> 828</span> {</div>
<div class="line"><a id="l00829" name="l00829"></a><span class="lineno"> 829</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>.Clear();</div>
<div class="line"><a id="l00830" name="l00830"></a><span class="lineno"> 830</span> <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">mappedChannels</a>.AddRange(list.SelectMany(x =&gt; x.Item2).Select(x =&gt; x.RealId));</div>
<div class="line"><a id="l00831" name="l00831"></a><span class="lineno"> 831</span> }</div>
<div class="line"><a id="l00832" name="l00832"></a><span class="lineno"> 832</span> </div>
<div class="line"><a id="l00833" name="l00833"></a><span class="lineno"> 833</span> <span class="keywordflow">if</span> (remapRequired)</div>
<div class="line"><a id="l00834" name="l00834"></a><span class="lineno"> 834</span> {</div>
<div class="line"><a id="l00835" name="l00835"></a><span class="lineno"> 835</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(<span class="stringliteral">&quot;Some channels failed to load with unknown errors. We will request that these be remapped, but it may result in communication spam. Please check prior logs and report an issue if this occurs.&quot;</span>);</div>
<div class="line"><a id="l00836" name="l00836"></a><span class="lineno"> 836</span> <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#a6a6dd225ccb27e30c2cc06562b035ebe">EnqueueMessage</a>(<span class="keyword">null</span>);</div>
<div class="line"><a id="l00837" name="l00837"></a><span class="lineno"> 837</span> }</div>
<div class="line"><a id="l00838" name="l00838"></a><span class="lineno"> 838</span> </div>
<div class="line"><a id="l00839" name="l00839"></a><span class="lineno"> 839</span> <span class="keywordflow">return</span> <span class="keyword">new</span> Dictionary&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;(list.Select(x =&gt; <span class="keyword">new</span> KeyValuePair&lt;Models.ChatChannel, IEnumerable&lt;ChannelRepresentation&gt;&gt;(x.Item1, x.Item2)));</div>
<div class="line"><a id="l00840" name="l00840"></a><span class="lineno"> 840</span> }</div>
</div>
<div class="line"><a id="l00841" name="l00841"></a><span class="lineno"> 841</span> </div>
<div class="foldopen" id="foldopen00847" data-start="{" data-end="}">
<div class="line"><a id="l00847" name="l00847"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab92d4920074cec3e48fa204af595a498"> 847</a></span> async ValueTask&lt;IEnumerable&lt;IChannel&gt;&gt; <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab92d4920074cec3e48fa204af595a498">GetAllAccessibleTextChannels</a>(CancellationToken cancellationToken)</div>
<div class="line"><a id="l00848" name="l00848"></a><span class="lineno"> 848</span> {</div>
<div class="line"><a id="l00849" name="l00849"></a><span class="lineno"> 849</span> var usersClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestUserAPI&gt;();</div>
<div class="line"><a id="l00850" name="l00850"></a><span class="lineno"> 850</span> var currentGuildsResponse = await usersClient.GetCurrentUserGuildsAsync(ct: cancellationToken);</div>
<div class="line"><a id="l00851" name="l00851"></a><span class="lineno"> 851</span> <span class="keywordflow">if</span> (!currentGuildsResponse.IsSuccess)</div>
<div class="line"><a id="l00852" name="l00852"></a><span class="lineno"> 852</span> {</div>
<div class="line"><a id="l00853" name="l00853"></a><span class="lineno"> 853</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00854" name="l00854"></a><span class="lineno"> 854</span> <span class="stringliteral">&quot;Error retrieving current discord guilds: {result}&quot;</span>,</div>
<div class="line"><a id="l00855" name="l00855"></a><span class="lineno"> 855</span> currentGuildsResponse.LogFormat());</div>
<div class="line"><a id="l00856" name="l00856"></a><span class="lineno"> 856</span> <span class="keywordflow">return</span> Enumerable.Empty&lt;IChannel&gt;();</div>
<div class="line"><a id="l00857" name="l00857"></a><span class="lineno"> 857</span> }</div>
<div class="line"><a id="l00858" name="l00858"></a><span class="lineno"> 858</span> </div>
<div class="line"><a id="l00859" name="l00859"></a><span class="lineno"> 859</span> var guildsClient = <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">serviceProvider</a>.GetRequiredService&lt;IDiscordRestGuildAPI&gt;();</div>
<div class="line"><a id="l00860" name="l00860"></a><span class="lineno"> 860</span> </div>
<div class="line"><a id="l00861" name="l00861"></a><span class="lineno"> 861</span> async ValueTask&lt;IEnumerable&lt;IChannel&gt;&gt; GetGuildChannels(IPartialGuild guild)</div>
<div class="line"><a id="l00862" name="l00862"></a><span class="lineno"> 862</span> {</div>
<div class="line"><a id="l00863" name="l00863"></a><span class="lineno"> 863</span> var channelsTask = guildsClient.GetGuildChannelsAsync(guild.ID.Value, cancellationToken);</div>
<div class="line"><a id="l00864" name="l00864"></a><span class="lineno"> 864</span> var threads = await guildsClient.ListActiveGuildThreadsAsync(guild.ID.Value, cancellationToken);</div>
<div class="line"><a id="l00865" name="l00865"></a><span class="lineno"> 865</span> <span class="keywordflow">if</span> (!threads.IsSuccess)</div>
<div class="line"><a id="l00866" name="l00866"></a><span class="lineno"> 866</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00867" name="l00867"></a><span class="lineno"> 867</span> <span class="stringliteral">&quot;Error retrieving discord guild threads {guildId} ({guildName}): {result}&quot;</span>,</div>
<div class="line"><a id="l00868" name="l00868"></a><span class="lineno"> 868</span> guild.ID,</div>
<div class="line"><a id="l00869" name="l00869"></a><span class="lineno"> 869</span> guild.Name,</div>
<div class="line"><a id="l00870" name="l00870"></a><span class="lineno"> 870</span> threads.LogFormat());</div>
<div class="line"><a id="l00871" name="l00871"></a><span class="lineno"> 871</span> </div>
<div class="line"><a id="l00872" name="l00872"></a><span class="lineno"> 872</span> var channels = await channelsTask;</div>
<div class="line"><a id="l00873" name="l00873"></a><span class="lineno"> 873</span> <span class="keywordflow">if</span> (!channels.IsSuccess)</div>
<div class="line"><a id="l00874" name="l00874"></a><span class="lineno"> 874</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogWarning(</div>
<div class="line"><a id="l00875" name="l00875"></a><span class="lineno"> 875</span> <span class="stringliteral">&quot;Error retrieving discord guild channels {guildId} ({guildName}): {result}&quot;</span>,</div>
<div class="line"><a id="l00876" name="l00876"></a><span class="lineno"> 876</span> guild.ID,</div>
<div class="line"><a id="l00877" name="l00877"></a><span class="lineno"> 877</span> guild.Name,</div>
<div class="line"><a id="l00878" name="l00878"></a><span class="lineno"> 878</span> channels.LogFormat());</div>
<div class="line"><a id="l00879" name="l00879"></a><span class="lineno"> 879</span> </div>
<div class="line"><a id="l00880" name="l00880"></a><span class="lineno"> 880</span> <span class="keywordflow">if</span> (!channels.IsSuccess &amp;&amp; !threads.IsSuccess)</div>
<div class="line"><a id="l00881" name="l00881"></a><span class="lineno"> 881</span> <span class="keywordflow">return</span> Enumerable.Empty&lt;IChannel&gt;();</div>
<div class="line"><a id="l00882" name="l00882"></a><span class="lineno"> 882</span> </div>
<div class="line"><a id="l00883" name="l00883"></a><span class="lineno"> 883</span> <span class="keywordflow">if</span> (channels.IsSuccess &amp;&amp; threads.IsSuccess)</div>
<div class="line"><a id="l00884" name="l00884"></a><span class="lineno"> 884</span> <span class="keywordflow">return</span> channels.Entity.Concat(threads.Entity.Threads ?? Enumerable.Empty&lt;IChannel&gt;());</div>
<div class="line"><a id="l00885" name="l00885"></a><span class="lineno"> 885</span> </div>
<div class="line"><a id="l00886" name="l00886"></a><span class="lineno"> 886</span> <span class="keywordflow">return</span> channels.Entity ?? threads.Entity?.Threads ?? Enumerable.Empty&lt;IChannel&gt;();</div>
<div class="line"><a id="l00887" name="l00887"></a><span class="lineno"> 887</span> }</div>
<div class="line"><a id="l00888" name="l00888"></a><span class="lineno"> 888</span> </div>
<div class="line"><a id="l00889" name="l00889"></a><span class="lineno"> 889</span> var guildsChannelsTasks = currentGuildsResponse.Entity</div>
<div class="line"><a id="l00890" name="l00890"></a><span class="lineno"> 890</span> .Select(GetGuildChannels);</div>
<div class="line"><a id="l00891" name="l00891"></a><span class="lineno"> 891</span> </div>
<div class="line"><a id="l00892" name="l00892"></a><span class="lineno"> 892</span> var guildsChannels = await <a class="code hl_class" href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html">ValueTaskExtensions</a>.<a class="code hl_function" href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html#a58adbd94d764754bd3e6c566a5fe7fe3">WhenAll</a>(guildsChannelsTasks, currentGuildsResponse.Entity.Count);</div>
<div class="line"><a id="l00893" name="l00893"></a><span class="lineno"> 893</span> </div>
<div class="line"><a id="l00894" name="l00894"></a><span class="lineno"> 894</span> var allAccessibleChannels = guildsChannels</div>
<div class="line"><a id="l00895" name="l00895"></a><span class="lineno"> 895</span> .SelectMany(channels =&gt; channels)</div>
<div class="line"><a id="l00896" name="l00896"></a><span class="lineno"> 896</span> .Where(guildChannel =&gt; <a class="code hl_variable" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1896b3a7ddd7b500c2624d3676b64eaf">SupportedGuildChannelTypes</a>.Contains(guildChannel.Type));</div>
<div class="line"><a id="l00897" name="l00897"></a><span class="lineno"> 897</span> </div>
<div class="line"><a id="l00898" name="l00898"></a><span class="lineno"> 898</span> <span class="keywordflow">return</span> allAccessibleChannels;</div>
<div class="line"><a id="l00899" name="l00899"></a><span class="lineno"> 899</span> }</div>
</div>
<div class="line"><a id="l00900" name="l00900"></a><span class="lineno"> 900</span> </div>
<div class="foldopen" id="foldopen00911" data-start="{" data-end="}">
<div class="line"><a id="l00911" name="l00911"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aa0b4853705d24be3e16314bf050f9e7c"> 911</a></span> List&lt;IEmbedField&gt; <a class="code hl_function" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aa0b4853705d24be3e16314bf050f9e7c">BuildUpdateEmbedFields</a>(</div>
<div class="line"><a id="l00912" name="l00912"></a><span class="lineno"> 912</span> Models.RevisionInformation revisionInformation,</div>
<div class="line"><a id="l00913" name="l00913"></a><span class="lineno"> 913</span> Models.RevisionInformation? previousRevisionInformation,</div>
<div class="line"><a id="l00914" name="l00914"></a><span class="lineno"> 914</span> <a class="code hl_class" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html">EngineVersion</a> engineVersion,</div>
<div class="line"><a id="l00915" name="l00915"></a><span class="lineno"> 915</span> <span class="keywordtype">string</span>? gitHubOwner,</div>
<div class="line"><a id="l00916" name="l00916"></a><span class="lineno"> 916</span> <span class="keywordtype">string</span>? gitHubRepo,</div>
<div class="line"><a id="l00917" name="l00917"></a><span class="lineno"> 917</span> <span class="keywordtype">bool</span> localCommitPushed)</div>
<div class="line"><a id="l00918" name="l00918"></a><span class="lineno"> 918</span> {</div>
<div class="line"><a id="l00919" name="l00919"></a><span class="lineno"> 919</span> <span class="keywordtype">bool</span> gitHub = gitHubOwner != <span class="keyword">null</span> &amp;&amp; gitHubRepo != <span class="keyword">null</span>;</div>
<div class="line"><a id="l00920" name="l00920"></a><span class="lineno"> 920</span> var engineField = engineVersion.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html#ae13db4c5dbd6b06c79d37ad9afd25af2">Engine</a>!.Value <span class="keywordflow">switch</span></div>
<div class="line"><a id="l00921" name="l00921"></a><span class="lineno"> 921</span> {</div>
<div class="line"><a id="l00922" name="l00922"></a><span class="lineno"> 922</span> EngineType.Byond =&gt; <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00923" name="l00923"></a><span class="lineno"> 923</span> <span class="stringliteral">&quot;BYOND Version&quot;</span>,</div>
<div class="line"><a id="l00924" name="l00924"></a><span class="lineno"> 924</span> $<span class="stringliteral">&quot;{engineVersion.Version!.Major}.{engineVersion.Version.Minor}{(engineVersion.CustomIteration.HasValue ? $&quot;</span>.{engineVersion.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html#af9d95aff0fd29f0d587bdc78b4969a77">CustomIteration</a>.Value}<span class="stringliteral">&quot; : String.Empty)}&quot;</span>,</div>
<div class="line"><a id="l00925" name="l00925"></a><span class="lineno"> 925</span> <span class="keyword">true</span>),</div>
<div class="line"><a id="l00926" name="l00926"></a><span class="lineno"> 926</span> <a class="code hl_enumeration" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#ad8fb60934662752c4bbed899440208ea">EngineType</a>.OpenDream =&gt; <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00927" name="l00927"></a><span class="lineno"> 927</span> <span class="stringliteral">&quot;OpenDream Version&quot;</span>,</div>
<div class="line"><a id="l00928" name="l00928"></a><span class="lineno"> 928</span> $<span class="stringliteral">&quot;[{engineVersion.SourceSHA![..7]}]({generalConfigurationOptions.CurrentValue.OpenDreamGitUrl}/commit/{engineVersion.SourceSHA})&quot;</span>,</div>
<div class="line"><a id="l00929" name="l00929"></a><span class="lineno"> 929</span> <span class="keyword">true</span>),</div>
<div class="line"><a id="l00930" name="l00930"></a><span class="lineno"> 930</span> _ =&gt; <span class="keywordflow">throw</span> <span class="keyword">new</span> InvalidOperationException($<span class="stringliteral">&quot;Invaild EngineType: {engineVersion.Engine.Value}&quot;</span>),</div>
<div class="line"><a id="l00931" name="l00931"></a><span class="lineno"> 931</span> };</div>
<div class="line"><a id="l00932" name="l00932"></a><span class="lineno"> 932</span> </div>
<div class="line"><a id="l00933" name="l00933"></a><span class="lineno"> 933</span> var revisionSha = revisionInformation.CommitSha!;</div>
<div class="line"><a id="l00934" name="l00934"></a><span class="lineno"> 934</span> var revisionOriginSha = revisionInformation.OriginCommitSha!;</div>
<div class="line"><a id="l00935" name="l00935"></a><span class="lineno"> 935</span> var fields = <span class="keyword">new</span> List&lt;IEmbedField&gt;</div>
<div class="line"><a id="l00936" name="l00936"></a><span class="lineno"> 936</span> {</div>
<div class="line"><a id="l00937" name="l00937"></a><span class="lineno"> 937</span> engineField,</div>
<div class="line"><a id="l00938" name="l00938"></a><span class="lineno"> 938</span> };</div>
<div class="line"><a id="l00939" name="l00939"></a><span class="lineno"> 939</span> </div>
<div class="line"><a id="l00940" name="l00940"></a><span class="lineno"> 940</span> <span class="keywordflow">if</span> (gitHubOwner == <span class="keyword">null</span> || gitHubRepo == <span class="keyword">null</span>)</div>
<div class="line"><a id="l00941" name="l00941"></a><span class="lineno"> 941</span> <span class="keywordflow">return</span> fields;</div>
<div class="line"><a id="l00942" name="l00942"></a><span class="lineno"> 942</span> </div>
<div class="line"><a id="l00943" name="l00943"></a><span class="lineno"> 943</span> var previousTestMerges = (IEnumerable&lt;RevInfoTestMerge&gt;?)previousRevisionInformation?.ActiveTestMerges ?? Enumerable.Empty&lt;<a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_models_1_1_rev_info_test_merge.html">RevInfoTestMerge</a>&gt;();</div>
<div class="line"><a id="l00944" name="l00944"></a><span class="lineno"> 944</span> var currentTestMerges = (IEnumerable&lt;RevInfoTestMerge&gt;?)revisionInformation.ActiveTestMerges ?? Enumerable.Empty&lt;<a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_models_1_1_rev_info_test_merge.html">RevInfoTestMerge</a>&gt;();</div>
<div class="line"><a id="l00945" name="l00945"></a><span class="lineno"> 945</span> </div>
<div class="line"><a id="l00946" name="l00946"></a><span class="lineno"> 946</span> <span class="comment">// determine what TMs were changed and how</span></div>
<div class="line"><a id="l00947" name="l00947"></a><span class="lineno"> 947</span> var addedTestMerges = currentTestMerges</div>
<div class="line"><a id="l00948" name="l00948"></a><span class="lineno"> 948</span> .Select(x =&gt; x.TestMerge)</div>
<div class="line"><a id="l00949" name="l00949"></a><span class="lineno"> 949</span> .Where(x =&gt; !previousTestMerges</div>
<div class="line"><a id="l00950" name="l00950"></a><span class="lineno"> 950</span> .Any(y =&gt; y.TestMerge.Number == x.Number))</div>
<div class="line"><a id="l00951" name="l00951"></a><span class="lineno"> 951</span> .ToList();</div>
<div class="line"><a id="l00952" name="l00952"></a><span class="lineno"> 952</span> var removedTestMerges = previousTestMerges</div>
<div class="line"><a id="l00953" name="l00953"></a><span class="lineno"> 953</span> .Select(x =&gt; x.TestMerge)</div>
<div class="line"><a id="l00954" name="l00954"></a><span class="lineno"> 954</span> .Where(x =&gt; !currentTestMerges</div>
<div class="line"><a id="l00955" name="l00955"></a><span class="lineno"> 955</span> .Any(y =&gt; y.TestMerge.Number == x.Number))</div>
<div class="line"><a id="l00956" name="l00956"></a><span class="lineno"> 956</span> .ToList();</div>
<div class="line"><a id="l00957" name="l00957"></a><span class="lineno"> 957</span> var updatedTestMerges = currentTestMerges</div>
<div class="line"><a id="l00958" name="l00958"></a><span class="lineno"> 958</span> .Select(x =&gt; x.TestMerge)</div>
<div class="line"><a id="l00959" name="l00959"></a><span class="lineno"> 959</span> .Where(x =&gt; previousTestMerges</div>
<div class="line"><a id="l00960" name="l00960"></a><span class="lineno"> 960</span> .Any(y =&gt; y.TestMerge.Number == x.Number &amp;&amp; y.TestMerge.TargetCommitSha != x.TargetCommitSha))</div>
<div class="line"><a id="l00961" name="l00961"></a><span class="lineno"> 961</span> .ToList();</div>
<div class="line"><a id="l00962" name="l00962"></a><span class="lineno"> 962</span> var unchangedTestMerges = currentTestMerges</div>
<div class="line"><a id="l00963" name="l00963"></a><span class="lineno"> 963</span> .Select(x =&gt; x.TestMerge)</div>
<div class="line"><a id="l00964" name="l00964"></a><span class="lineno"> 964</span> .Where(x =&gt; previousTestMerges</div>
<div class="line"><a id="l00965" name="l00965"></a><span class="lineno"> 965</span> .Any(y =&gt; y.TestMerge.Number == x.Number &amp;&amp; y.TestMerge.TargetCommitSha == x.TargetCommitSha))</div>
<div class="line"><a id="l00966" name="l00966"></a><span class="lineno"> 966</span> .ToList();</div>
<div class="line"><a id="l00967" name="l00967"></a><span class="lineno"> 967</span> </div>
<div class="line"><a id="l00968" name="l00968"></a><span class="lineno"> 968</span> fields.Add(</div>
<div class="line"><a id="l00969" name="l00969"></a><span class="lineno"> 969</span> <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00970" name="l00970"></a><span class="lineno"> 970</span> <span class="stringliteral">&quot;Local Commit&quot;</span>,</div>
<div class="line"><a id="l00971" name="l00971"></a><span class="lineno"> 971</span> localCommitPushed &amp;&amp; gitHub</div>
<div class="line"><a id="l00972" name="l00972"></a><span class="lineno"> 972</span> ? $<span class="stringliteral">&quot;[{revisionSha[..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{revisionSha})&quot;</span></div>
<div class="line"><a id="l00973" name="l00973"></a><span class="lineno"> 973</span> : revisionSha[..7],</div>
<div class="line"><a id="l00974" name="l00974"></a><span class="lineno"> 974</span> <span class="keyword">true</span>));</div>
<div class="line"><a id="l00975" name="l00975"></a><span class="lineno"> 975</span> </div>
<div class="line"><a id="l00976" name="l00976"></a><span class="lineno"> 976</span> fields.Add(</div>
<div class="line"><a id="l00977" name="l00977"></a><span class="lineno"> 977</span> <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00978" name="l00978"></a><span class="lineno"> 978</span> <span class="stringliteral">&quot;Branch Commit&quot;</span>,</div>
<div class="line"><a id="l00979" name="l00979"></a><span class="lineno"> 979</span> gitHub</div>
<div class="line"><a id="l00980" name="l00980"></a><span class="lineno"> 980</span> ? $<span class="stringliteral">&quot;[{revisionOriginSha[..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{revisionOriginSha})&quot;</span></div>
<div class="line"><a id="l00981" name="l00981"></a><span class="lineno"> 981</span> : revisionOriginSha[..7],</div>
<div class="line"><a id="l00982" name="l00982"></a><span class="lineno"> 982</span> <span class="keyword">true</span>));</div>
<div class="line"><a id="l00983" name="l00983"></a><span class="lineno"> 983</span> </div>
<div class="line"><a id="l00984" name="l00984"></a><span class="lineno"> 984</span> fields.AddRange(addedTestMerges</div>
<div class="line"><a id="l00985" name="l00985"></a><span class="lineno"> 985</span> .Select(x =&gt; <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00986" name="l00986"></a><span class="lineno"> 986</span> $<span class="stringliteral">&quot;#{x.Number} (Added)&quot;</span>,</div>
<div class="line"><a id="l00987" name="l00987"></a><span class="lineno"> 987</span> $<span class="stringliteral">&quot;[{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_{Environment.NewLine}Commit: [{x.TargetCommitSha![..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{x.TargetCommitSha}){(String.IsNullOrWhiteSpace(x.Comment) ? String.Empty : $&quot;</span>{Environment.NewLine}_**{x.Comment}**_<span class="stringliteral">&quot;)}&quot;</span>,</div>
</div>
<div class="line"><a id="l00988" name="l00988"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a6551c929800df136bef095841ea8fd09"> 988</a></span> <span class="keyword">false</span>)));</div>
<div class="line"><a id="l00989" name="l00989"></a><span class="lineno"> 989</span> </div>
<div class="line"><a id="l00990" name="l00990"></a><span class="lineno"><a class="line" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a029782485a4021dec502e3e798eea6f0"> 990</a></span> fields.AddRange(updatedTestMerges</div>
<div class="line"><a id="l00991" name="l00991"></a><span class="lineno"> 991</span> .Select(x =&gt; <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00992" name="l00992"></a><span class="lineno"> 992</span> $<span class="stringliteral">&quot;#{x.Number} (Updated)&quot;</span>,</div>
<div class="line"><a id="l00993" name="l00993"></a><span class="lineno"> 993</span> $<span class="stringliteral">&quot;[{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_{Environment.NewLine}Commit: [{x.TargetCommitSha![..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{x.TargetCommitSha}){(String.IsNullOrWhiteSpace(x.Comment) ? String.Empty : $&quot;</span>{Environment.NewLine}_**{x.Comment}**_<span class="stringliteral">&quot;)}&quot;</span>,</div>
<div class="line"><a id="l00994" name="l00994"></a><span class="lineno"> 994</span> <span class="keyword">false</span>)));</div>
<div class="line"><a id="l00995" name="l00995"></a><span class="lineno"> 995</span> </div>
<div class="line"><a id="l00996" name="l00996"></a><span class="lineno"> 996</span> fields.AddRange(unchangedTestMerges</div>
<div class="line"><a id="l00997" name="l00997"></a><span class="lineno"> 997</span> .Select(x =&gt; <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l00998" name="l00998"></a><span class="lineno"> 998</span> $<span class="stringliteral">&quot;#{x.Number}&quot;</span>,</div>
<div class="line"><a id="l00999" name="l00999"></a><span class="lineno"> 999</span> $<span class="stringliteral">&quot;[{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_{Environment.NewLine}Commit: [{x.TargetCommitSha![..7]}](https://github.com/{gitHubOwner}/{gitHubRepo}/commit/{x.TargetCommitSha}){(String.IsNullOrWhiteSpace(x.Comment) ? String.Empty : $&quot;</span>{Environment.NewLine}_**{x.Comment}**_<span class="stringliteral">&quot;)}&quot;</span>,</div>
</div>
<div class="line"><a id="l01000" name="l01000"></a><span class="lineno"><a class="line" href="namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers.html#af4b5f6ad734602f75d059267687ca3dd"> 1000</a></span> <span class="keyword">false</span>)));</div>
<div class="line"><a id="l01001" name="l01001"></a><span class="lineno"> 1001</span> </div>
<div class="foldopen" id="foldopen01002" data-start="{" data-end="}">
<div class="line"><a id="l01002" name="l01002"></a><span class="lineno"><a class="line" href="namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers.html#a9d269b6c0deb19a29d4631459082fe20"> 1002</a></span> <span class="keywordflow">if</span> (removedTestMerges.Count != 0)</div>
<div class="line"><a id="l01003" name="l01003"></a><span class="lineno"> 1003</span> fields.Add(</div>
<div class="line"><a id="l01004" name="l01004"></a><span class="lineno"> 1004</span> <span class="keyword">new</span> EmbedField(</div>
<div class="line"><a id="l01005" name="l01005"></a><span class="lineno"> 1005</span> <span class="stringliteral">&quot;Removed:&quot;</span>,</div>
<div class="line"><a id="l01006" name="l01006"></a><span class="lineno"> 1006</span> String.Join(</div>
<div class="line"><a id="l01007" name="l01007"></a><span class="lineno"> 1007</span> Environment.NewLine,</div>
<div class="line"><a id="l01008" name="l01008"></a><span class="lineno"> 1008</span> removedTestMerges</div>
<div class="line"><a id="l01009" name="l01009"></a><span class="lineno"> 1009</span> .Select(x =&gt; $<span class="stringliteral">&quot;- #{x.Number} [{x.TitleAtMerge}]({x.Url}) by _[@{x.Author}](https://github.com/{x.Author})_&quot;</span>))));</div>
</div>
<div class="line"><a id="l01010" name="l01010"></a><span class="lineno"> 1010</span> </div>
<div class="line"><a id="l01011" name="l01011"></a><span class="lineno"> 1011</span> <span class="keywordflow">return</span> fields;</div>
<div class="line"><a id="l01012" name="l01012"></a><span class="lineno"> 1012</span> }</div>
<div class="line"><a id="l01013" name="l01013"></a><span class="lineno"> 1013</span> </div>
<div class="line"><a id="l01019" name="l01019"></a><span class="lineno"> 1019</span><span class="preprocessor">#pragma warning disable CA1502</span></div>
<div class="foldopen" id="foldopen01020" data-start="{" data-end="}">
<div class="line"><a id="l01020" name="l01020"></a><span class="lineno"><a class="line" href="_discord_provider_8cs.html#a6faaab8be32021a7d88c1d1ac62162c8"> 1020</a></span> Optional&lt;IReadOnlyList&lt;IEmbed&gt;&gt; <a class="code hl_function" href="_discord_provider_8cs.html#a6faaab8be32021a7d88c1d1ac62162c8">ConvertEmbed</a>(<a class="code hl_class" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html">ChatEmbed</a>? embed)</div>
<div class="line"><a id="l01021" name="l01021"></a><span class="lineno"> 1021</span> {</div>
<div class="line"><a id="l01022" name="l01022"></a><span class="lineno"> 1022</span> <span class="keywordflow">if</span> (embed == <span class="keyword">null</span>)</div>
<div class="line"><a id="l01023" name="l01023"></a><span class="lineno"> 1023</span> <span class="keywordflow">return</span> <span class="keywordflow">default</span>;</div>
<div class="line"><a id="l01024" name="l01024"></a><span class="lineno"> 1024</span> </div>
<div class="line"><a id="l01025" name="l01025"></a><span class="lineno"> 1025</span> var embedErrors = <span class="keyword">new</span> List&lt;string&gt;();</div>
<div class="line"><a id="l01026" name="l01026"></a><span class="lineno"> 1026</span> Optional&lt;Color&gt; colour = <span class="keywordflow">default</span>;</div>
<div class="line"><a id="l01027" name="l01027"></a><span class="lineno"> 1027</span> <span class="keywordflow">if</span> (embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#ab1a422f0ae51751307a024c69c80de92">Colour</a> != <span class="keyword">null</span>)</div>
<div class="line"><a id="l01028" name="l01028"></a><span class="lineno"> 1028</span> <span class="keywordflow">if</span> (Int32.TryParse(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#ab1a422f0ae51751307a024c69c80de92">Colour</a>[1..], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var argb))</div>
<div class="line"><a id="l01029" name="l01029"></a><span class="lineno"> 1029</span> colour = Color.FromArgb(argb);</div>
<div class="line"><a id="l01030" name="l01030"></a><span class="lineno"> 1030</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l01031" name="l01031"></a><span class="lineno"> 1031</span> embedErrors.Add(</div>
<div class="line"><a id="l01032" name="l01032"></a><span class="lineno"> 1032</span> String.Format(</div>
<div class="line"><a id="l01033" name="l01033"></a><span class="lineno"> 1033</span> CultureInfo.InvariantCulture,</div>
<div class="line"><a id="l01034" name="l01034"></a><span class="lineno"> 1034</span> <span class="stringliteral">&quot;Invalid embed colour: {0}&quot;</span>,</div>
<div class="line"><a id="l01035" name="l01035"></a><span class="lineno"> 1035</span> embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#ab1a422f0ae51751307a024c69c80de92">Colour</a>));</div>
<div class="line"><a id="l01036" name="l01036"></a><span class="lineno"> 1036</span> </div>
<div class="line"><a id="l01037" name="l01037"></a><span class="lineno"> 1037</span> <span class="keywordflow">if</span> (embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#acf2a8d23747fbdf8349687db989857df">Author</a> != <span class="keyword">null</span> &amp;&amp; String.IsNullOrWhiteSpace(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#acf2a8d23747fbdf8349687db989857df">Author</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_provider.html#a7d29bec0678fbbf1e1e87478bb36d897">Name</a>))</div>
<div class="line"><a id="l01038" name="l01038"></a><span class="lineno"> 1038</span> {</div>
<div class="line"><a id="l01039" name="l01039"></a><span class="lineno"> 1039</span> embedErrors.Add(<span class="stringliteral">&quot;Null or whitespace embed author name!&quot;</span>);</div>
<div class="line"><a id="l01040" name="l01040"></a><span class="lineno"> 1040</span> embed.Author = <span class="keyword">null</span>;</div>
<div class="line"><a id="l01041" name="l01041"></a><span class="lineno"> 1041</span> }</div>
<div class="line"><a id="l01042" name="l01042"></a><span class="lineno"> 1042</span> </div>
<div class="line"><a id="l01043" name="l01043"></a><span class="lineno"> 1043</span> List&lt;IEmbedField&gt;? fields = <span class="keyword">null</span>;</div>
<div class="line"><a id="l01044" name="l01044"></a><span class="lineno"> 1044</span> <span class="keywordflow">if</span> (embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#aaa3ea3f3ef8e52643d39711e0cf21090">Fields</a> != <span class="keyword">null</span>)</div>
<div class="line"><a id="l01045" name="l01045"></a><span class="lineno"> 1045</span> {</div>
<div class="line"><a id="l01046" name="l01046"></a><span class="lineno"> 1046</span> fields = <span class="keyword">new</span> List&lt;IEmbedField&gt;();</div>
<div class="line"><a id="l01047" name="l01047"></a><span class="lineno"> 1047</span> var i = -1;</div>
<div class="line"><a id="l01048" name="l01048"></a><span class="lineno"> 1048</span> <span class="keywordflow">foreach</span> (var field <span class="keywordflow">in</span> embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#aaa3ea3f3ef8e52643d39711e0cf21090">Fields</a>)</div>
<div class="line"><a id="l01049" name="l01049"></a><span class="lineno"> 1049</span> {</div>
<div class="line"><a id="l01050" name="l01050"></a><span class="lineno"> 1050</span> ++i;</div>
<div class="line"><a id="l01051" name="l01051"></a><span class="lineno"> 1051</span> var invalid = <span class="keyword">false</span>;</div>
<div class="line"><a id="l01052" name="l01052"></a><span class="lineno"> 1052</span> <span class="keywordflow">if</span> (String.IsNullOrWhiteSpace(field.Name))</div>
<div class="line"><a id="l01053" name="l01053"></a><span class="lineno"> 1053</span> {</div>
<div class="line"><a id="l01054" name="l01054"></a><span class="lineno"> 1054</span> embedErrors.Add(</div>
<div class="line"><a id="l01055" name="l01055"></a><span class="lineno"> 1055</span> String.Format(</div>
<div class="line"><a id="l01056" name="l01056"></a><span class="lineno"> 1056</span> CultureInfo.InvariantCulture,</div>
<div class="line"><a id="l01057" name="l01057"></a><span class="lineno"> 1057</span> <span class="stringliteral">&quot;Null or whitespace field name at index {0}!&quot;</span>,</div>
<div class="line"><a id="l01058" name="l01058"></a><span class="lineno"> 1058</span> i));</div>
<div class="line"><a id="l01059" name="l01059"></a><span class="lineno"> 1059</span> invalid = <span class="keyword">true</span>;</div>
<div class="line"><a id="l01060" name="l01060"></a><span class="lineno"> 1060</span> }</div>
<div class="line"><a id="l01061" name="l01061"></a><span class="lineno"> 1061</span> </div>
<div class="line"><a id="l01062" name="l01062"></a><span class="lineno"> 1062</span> <span class="keywordflow">if</span> (String.IsNullOrWhiteSpace(field.Value))</div>
<div class="line"><a id="l01063" name="l01063"></a><span class="lineno"> 1063</span> {</div>
<div class="line"><a id="l01064" name="l01064"></a><span class="lineno"> 1064</span> embedErrors.Add(</div>
<div class="line"><a id="l01065" name="l01065"></a><span class="lineno"> 1065</span> String.Format(</div>
<div class="line"><a id="l01066" name="l01066"></a><span class="lineno"> 1066</span> CultureInfo.InvariantCulture,</div>
<div class="line"><a id="l01067" name="l01067"></a><span class="lineno"> 1067</span> <span class="stringliteral">&quot;Null or whitespace field value at index {0}!&quot;</span>,</div>
<div class="line"><a id="l01068" name="l01068"></a><span class="lineno"> 1068</span> i));</div>
<div class="line"><a id="l01069" name="l01069"></a><span class="lineno"> 1069</span> invalid = <span class="keyword">true</span>;</div>
<div class="line"><a id="l01070" name="l01070"></a><span class="lineno"> 1070</span> }</div>
<div class="line"><a id="l01071" name="l01071"></a><span class="lineno"> 1071</span> </div>
<div class="line"><a id="l01072" name="l01072"></a><span class="lineno"> 1072</span> <span class="keywordflow">if</span> (invalid)</div>
<div class="line"><a id="l01073" name="l01073"></a><span class="lineno"> 1073</span> <span class="keywordflow">continue</span>;</div>
<div class="line"><a id="l01074" name="l01074"></a><span class="lineno"> 1074</span> </div>
<div class="line"><a id="l01075" name="l01075"></a><span class="lineno"> 1075</span> fields.Add(<span class="keyword">new</span> EmbedField(field.Name!, field.Value!)</div>
<div class="line"><a id="l01076" name="l01076"></a><span class="lineno"> 1076</span> {</div>
<div class="line"><a id="l01077" name="l01077"></a><span class="lineno"> 1077</span> IsInline = field.IsInline ?? default(Optional&lt;bool&gt;),</div>
<div class="line"><a id="l01078" name="l01078"></a><span class="lineno"> 1078</span> });</div>
<div class="line"><a id="l01079" name="l01079"></a><span class="lineno"> 1079</span> }</div>
<div class="line"><a id="l01080" name="l01080"></a><span class="lineno"> 1080</span> }</div>
<div class="line"><a id="l01081" name="l01081"></a><span class="lineno"> 1081</span> </div>
<div class="line"><a id="l01082" name="l01082"></a><span class="lineno"> 1082</span> <span class="keywordflow">if</span> (embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a43303379f4417e94d9cf6b284dae031d">Footer</a> != <span class="keyword">null</span> &amp;&amp; String.IsNullOrWhiteSpace(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a43303379f4417e94d9cf6b284dae031d">Footer</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_footer.html#a9d96e0c77d06d84dd00fda1451807370">Text</a>))</div>
<div class="line"><a id="l01083" name="l01083"></a><span class="lineno"> 1083</span> {</div>
<div class="line"><a id="l01084" name="l01084"></a><span class="lineno"> 1084</span> embedErrors.Add(<span class="stringliteral">&quot;Null or whitespace embed footer text!&quot;</span>);</div>
<div class="line"><a id="l01085" name="l01085"></a><span class="lineno"> 1085</span> embed.Footer = <span class="keyword">null</span>;</div>
<div class="line"><a id="l01086" name="l01086"></a><span class="lineno"> 1086</span> }</div>
<div class="line"><a id="l01087" name="l01087"></a><span class="lineno"> 1087</span> </div>
<div class="line"><a id="l01088" name="l01088"></a><span class="lineno"> 1088</span> <span class="keywordflow">if</span> (embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a3863a450e43588c18e28ea2f23c5131b">Image</a> != <span class="keyword">null</span> &amp;&amp; String.IsNullOrWhiteSpace(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a3863a450e43588c18e28ea2f23c5131b">Image</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_media.html#a3b31d2e65dd3361c1a318db4ab7c6757">Url</a>))</div>
<div class="line"><a id="l01089" name="l01089"></a><span class="lineno"> 1089</span> {</div>
<div class="line"><a id="l01090" name="l01090"></a><span class="lineno"> 1090</span> embedErrors.Add(<span class="stringliteral">&quot;Null or whitespace embed image url!&quot;</span>);</div>
<div class="line"><a id="l01091" name="l01091"></a><span class="lineno"> 1091</span> embed.Image = <span class="keyword">null</span>;</div>
<div class="line"><a id="l01092" name="l01092"></a><span class="lineno"> 1092</span> }</div>
<div class="line"><a id="l01093" name="l01093"></a><span class="lineno"> 1093</span> </div>
<div class="line"><a id="l01094" name="l01094"></a><span class="lineno"> 1094</span> <span class="keywordflow">if</span> (embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a576730e6f32d18333550f8a393331f91">Thumbnail</a> != <span class="keyword">null</span> &amp;&amp; String.IsNullOrWhiteSpace(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a576730e6f32d18333550f8a393331f91">Thumbnail</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_media.html#a3b31d2e65dd3361c1a318db4ab7c6757">Url</a>))</div>
<div class="line"><a id="l01095" name="l01095"></a><span class="lineno"> 1095</span> {</div>
<div class="line"><a id="l01096" name="l01096"></a><span class="lineno"> 1096</span> embedErrors.Add(<span class="stringliteral">&quot;Null or whitespace embed thumbnail url!&quot;</span>);</div>
<div class="line"><a id="l01097" name="l01097"></a><span class="lineno"> 1097</span> embed.Thumbnail = <span class="keyword">null</span>;</div>
<div class="line"><a id="l01098" name="l01098"></a><span class="lineno"> 1098</span> }</div>
<div class="line"><a id="l01099" name="l01099"></a><span class="lineno"> 1099</span> </div>
<div class="line"><a id="l01100" name="l01100"></a><span class="lineno"> 1100</span> Optional&lt;DateTimeOffset&gt; timestampOptional = <span class="keywordflow">default</span>;</div>
<div class="line"><a id="l01101" name="l01101"></a><span class="lineno"> 1101</span> <span class="keywordflow">if</span> (embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a12270babc71891c5a8781910cfa71ddd">Timestamp</a> != <span class="keyword">null</span>)</div>
<div class="line"><a id="l01102" name="l01102"></a><span class="lineno"> 1102</span> <span class="keywordflow">if</span> (DateTimeOffset.TryParse(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a12270babc71891c5a8781910cfa71ddd">Timestamp</a>, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var timestamp))</div>
<div class="line"><a id="l01103" name="l01103"></a><span class="lineno"> 1103</span> timestampOptional = timestamp.ToUniversalTime();</div>
<div class="line"><a id="l01104" name="l01104"></a><span class="lineno"> 1104</span> <span class="keywordflow">else</span></div>
<div class="line"><a id="l01105" name="l01105"></a><span class="lineno"> 1105</span> embedErrors.Add(</div>
<div class="line"><a id="l01106" name="l01106"></a><span class="lineno"> 1106</span> String.Format(</div>
<div class="line"><a id="l01107" name="l01107"></a><span class="lineno"> 1107</span> CultureInfo.InvariantCulture,</div>
<div class="line"><a id="l01108" name="l01108"></a><span class="lineno"> 1108</span> <span class="stringliteral">&quot;Invalid embed timestamp: {0}&quot;</span>,</div>
<div class="line"><a id="l01109" name="l01109"></a><span class="lineno"> 1109</span> embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a12270babc71891c5a8781910cfa71ddd">Timestamp</a>));</div>
<div class="line"><a id="l01110" name="l01110"></a><span class="lineno"> 1110</span> </div>
<div class="line"><a id="l01111" name="l01111"></a><span class="lineno"> 1111</span> var discordEmbed = <span class="keyword">new</span> Embed</div>
<div class="line"><a id="l01112" name="l01112"></a><span class="lineno"> 1112</span> {</div>
<div class="line"><a id="l01113" name="l01113"></a><span class="lineno"> 1113</span> Author = embed.Author != <span class="keyword">null</span></div>
<div class="line"><a id="l01114" name="l01114"></a><span class="lineno"> 1114</span> ? <span class="keyword">new</span> EmbedAuthor(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#acf2a8d23747fbdf8349687db989857df">Author</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_provider.html#a7d29bec0678fbbf1e1e87478bb36d897">Name</a>!)</div>
<div class="line"><a id="l01115" name="l01115"></a><span class="lineno"> 1115</span> {</div>
<div class="line"><a id="l01116" name="l01116"></a><span class="lineno"> 1116</span> IconUrl = embed.Author.IconUrl ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01117" name="l01117"></a><span class="lineno"> 1117</span> ProxyIconUrl = embed.Author.ProxyIconUrl ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01118" name="l01118"></a><span class="lineno"> 1118</span> Url = embed.Author.Url ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01119" name="l01119"></a><span class="lineno"> 1119</span> }</div>
<div class="line"><a id="l01120" name="l01120"></a><span class="lineno"> 1120</span> : <span class="keywordflow">default</span>(Optional&lt;IEmbedAuthor&gt;),</div>
<div class="line"><a id="l01121" name="l01121"></a><span class="lineno"> 1121</span> Colour = colour,</div>
<div class="line"><a id="l01122" name="l01122"></a><span class="lineno"> 1122</span> Description = embed.Description ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01123" name="l01123"></a><span class="lineno"> 1123</span> Fields = fields ?? <span class="keywordflow">default</span>(<a class="code hl_enumvalue" href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#ae758c5cd6d61f61a7dc4b6f3c7000b52aebb061953c0454b2c8ee7b0ac615ebcd">Optional</a>&lt;IReadOnlyList&lt;IEmbedField&gt;&gt;),</div>
<div class="line"><a id="l01124" name="l01124"></a><span class="lineno"> 1124</span> Footer = embed.Footer != <span class="keyword">null</span></div>
<div class="line"><a id="l01125" name="l01125"></a><span class="lineno"> 1125</span> ? (Optional&lt;IEmbedFooter&gt;)<span class="keyword">new</span> EmbedFooter(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a43303379f4417e94d9cf6b284dae031d">Footer</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_footer.html#a9d96e0c77d06d84dd00fda1451807370">Text</a>!)</div>
<div class="line"><a id="l01126" name="l01126"></a><span class="lineno"> 1126</span> {</div>
<div class="line"><a id="l01127" name="l01127"></a><span class="lineno"> 1127</span> IconUrl = embed.Footer.IconUrl ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01128" name="l01128"></a><span class="lineno"> 1128</span> ProxyIconUrl = embed.Footer.ProxyIconUrl ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01129" name="l01129"></a><span class="lineno"> 1129</span> }</div>
<div class="line"><a id="l01130" name="l01130"></a><span class="lineno"> 1130</span> : <span class="keywordflow">default</span>,</div>
<div class="line"><a id="l01131" name="l01131"></a><span class="lineno"> 1131</span> Image = embed.Image != <span class="keyword">null</span></div>
<div class="line"><a id="l01132" name="l01132"></a><span class="lineno"> 1132</span> ? <span class="keyword">new</span> EmbedImage(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a3863a450e43588c18e28ea2f23c5131b">Image</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_media.html#a3b31d2e65dd3361c1a318db4ab7c6757">Url</a>!)</div>
<div class="line"><a id="l01133" name="l01133"></a><span class="lineno"> 1133</span> {</div>
<div class="line"><a id="l01134" name="l01134"></a><span class="lineno"> 1134</span> Width = embed.Image.Width ?? <span class="keywordflow">default</span>(Optional&lt;int&gt;),</div>
<div class="line"><a id="l01135" name="l01135"></a><span class="lineno"> 1135</span> Height = embed.Image.Height ?? <span class="keywordflow">default</span>(Optional&lt;int&gt;),</div>
<div class="line"><a id="l01136" name="l01136"></a><span class="lineno"> 1136</span> ProxyUrl = embed.Image.ProxyUrl ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01137" name="l01137"></a><span class="lineno"> 1137</span> }</div>
<div class="line"><a id="l01138" name="l01138"></a><span class="lineno"> 1138</span> : <span class="keywordflow">default</span>(Optional&lt;IEmbedImage&gt;),</div>
<div class="line"><a id="l01139" name="l01139"></a><span class="lineno"> 1139</span> Provider = embed.Provider != <span class="keyword">null</span></div>
<div class="line"><a id="l01140" name="l01140"></a><span class="lineno"> 1140</span> ? <span class="keyword">new</span> EmbedProvider</div>
<div class="line"><a id="l01141" name="l01141"></a><span class="lineno"> 1141</span> {</div>
<div class="line"><a id="l01142" name="l01142"></a><span class="lineno"> 1142</span> Name = embed.Provider.Name ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01143" name="l01143"></a><span class="lineno"> 1143</span> Url = embed.Provider.Url ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01144" name="l01144"></a><span class="lineno"> 1144</span> }</div>
<div class="line"><a id="l01145" name="l01145"></a><span class="lineno"> 1145</span> : <span class="keywordflow">default</span>(Optional&lt;IEmbedProvider&gt;),</div>
<div class="line"><a id="l01146" name="l01146"></a><span class="lineno"> 1146</span> Thumbnail = embed.Thumbnail != <span class="keyword">null</span></div>
<div class="line"><a id="l01147" name="l01147"></a><span class="lineno"> 1147</span> ? <span class="keyword">new</span> EmbedThumbnail(embed.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a576730e6f32d18333550f8a393331f91">Thumbnail</a>.<a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_media.html#a3b31d2e65dd3361c1a318db4ab7c6757">Url</a>!)</div>
<div class="line"><a id="l01148" name="l01148"></a><span class="lineno"> 1148</span> {</div>
<div class="line"><a id="l01149" name="l01149"></a><span class="lineno"> 1149</span> Width = embed.Thumbnail.Width ?? <span class="keywordflow">default</span>(Optional&lt;int&gt;),</div>
<div class="line"><a id="l01150" name="l01150"></a><span class="lineno"> 1150</span> Height = embed.Thumbnail.Height ?? <span class="keywordflow">default</span>(Optional&lt;int&gt;),</div>
<div class="line"><a id="l01151" name="l01151"></a><span class="lineno"> 1151</span> ProxyUrl = embed.Thumbnail.ProxyUrl ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01152" name="l01152"></a><span class="lineno"> 1152</span> }</div>
<div class="line"><a id="l01153" name="l01153"></a><span class="lineno"> 1153</span> : <span class="keywordflow">default</span>(Optional&lt;IEmbedThumbnail&gt;),</div>
<div class="line"><a id="l01154" name="l01154"></a><span class="lineno"> 1154</span> Timestamp = timestampOptional,</div>
<div class="line"><a id="l01155" name="l01155"></a><span class="lineno"> 1155</span> Title = embed.Title ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01156" name="l01156"></a><span class="lineno"> 1156</span> Url = embed.Url ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01157" name="l01157"></a><span class="lineno"> 1157</span> Video = embed.Video != <span class="keyword">null</span></div>
<div class="line"><a id="l01158" name="l01158"></a><span class="lineno"> 1158</span> ? <span class="keyword">new</span> EmbedVideo</div>
<div class="line"><a id="l01159" name="l01159"></a><span class="lineno"> 1159</span> {</div>
<div class="line"><a id="l01160" name="l01160"></a><span class="lineno"> 1160</span> Url = embed.Video.Url ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01161" name="l01161"></a><span class="lineno"> 1161</span> Width = embed.Video.Width ?? <span class="keywordflow">default</span>(Optional&lt;int&gt;),</div>
<div class="line"><a id="l01162" name="l01162"></a><span class="lineno"> 1162</span> Height = embed.Video.Height ?? <span class="keywordflow">default</span>(Optional&lt;int&gt;),</div>
<div class="line"><a id="l01163" name="l01163"></a><span class="lineno"> 1163</span> ProxyUrl = embed.Video.ProxyUrl ?? <span class="keywordflow">default</span>(Optional&lt;string&gt;),</div>
<div class="line"><a id="l01164" name="l01164"></a><span class="lineno"> 1164</span> }</div>
<div class="line"><a id="l01165" name="l01165"></a><span class="lineno"> 1165</span> : <span class="keywordflow">default</span>(Optional&lt;IEmbedVideo&gt;),</div>
<div class="line"><a id="l01166" name="l01166"></a><span class="lineno"> 1166</span> };</div>
<div class="line"><a id="l01167" name="l01167"></a><span class="lineno"> 1167</span> </div>
<div class="line"><a id="l01168" name="l01168"></a><span class="lineno"> 1168</span> var result = <span class="keyword">new</span> List&lt;IEmbed&gt; { discordEmbed };</div>
<div class="line"><a id="l01169" name="l01169"></a><span class="lineno"> 1169</span> </div>
<div class="line"><a id="l01170" name="l01170"></a><span class="lineno"> 1170</span> <span class="keywordflow">if</span> (embedErrors.Count &gt; 0)</div>
<div class="line"><a id="l01171" name="l01171"></a><span class="lineno"> 1171</span> {</div>
<div class="line"><a id="l01172" name="l01172"></a><span class="lineno"> 1172</span> var joinedErrors = String.Join(Environment.NewLine, embedErrors);</div>
<div class="line"><a id="l01173" name="l01173"></a><span class="lineno"> 1173</span> <a class="code hl_property" href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Logger</a>.LogError(<span class="stringliteral">&quot;Embed description contains errors:{newLine}{issues}&quot;</span>, Environment.NewLine, joinedErrors);</div>
<div class="line"><a id="l01174" name="l01174"></a><span class="lineno"> 1174</span> result.Add(<span class="keyword">new</span> Embed</div>
<div class="line"><a id="l01175" name="l01175"></a><span class="lineno"> 1175</span> {</div>
<div class="line"><a id="l01176" name="l01176"></a><span class="lineno"> 1176</span> Title = <span class="stringliteral">&quot;TGS Embed Errors&quot;</span>,</div>
<div class="line"><a id="l01177" name="l01177"></a><span class="lineno"> 1177</span> Description = joinedErrors,</div>
<div class="line"><a id="l01178" name="l01178"></a><span class="lineno"> 1178</span> Colour = Color.Red,</div>
<div class="line"><a id="l01179" name="l01179"></a><span class="lineno"> 1179</span> Footer = <span class="keyword">new</span> EmbedFooter(<span class="stringliteral">&quot;Please report this to your codebase&#39;s maintainers.&quot;</span>),</div>
<div class="line"><a id="l01180" name="l01180"></a><span class="lineno"> 1180</span> Timestamp = DateTimeOffset.UtcNow,</div>
<div class="line"><a id="l01181" name="l01181"></a><span class="lineno"> 1181</span> });</div>
<div class="line"><a id="l01182" name="l01182"></a><span class="lineno"> 1182</span> }</div>
<div class="line"><a id="l01183" name="l01183"></a><span class="lineno"> 1183</span> </div>
<div class="line"><a id="l01184" name="l01184"></a><span class="lineno"> 1184</span> <span class="keywordflow">return</span> result;</div>
<div class="line"><a id="l01185" name="l01185"></a><span class="lineno"> 1185</span> }</div>
</div>
<div class="line"><a id="l01186" name="l01186"></a><span class="lineno"> 1186</span><span class="preprocessor"> #pragma warning restore CA1502</span></div>
<div class="line"><a id="l01187" name="l01187"></a><span class="lineno"> 1187</span> }</div>
<div class="line"><a id="l01188" name="l01188"></a><span class="lineno"> 1188</span><span class="preprocessor">#pragma warning restore CA1506</span></div>
<div class="line"><a id="l01189" name="l01189"></a><span class="lineno"> 1189</span>}</div>
<div class="ttc" id="a_discord_provider_8cs_html_a6faaab8be32021a7d88c1d1ac62162c8"><div class="ttname"><a href="_discord_provider_8cs.html#a6faaab8be32021a7d88c1d1ac62162c8">ConvertEmbed</a></div><div class="ttdeci">Optional&lt; IReadOnlyList&lt; IEmbed &gt; &gt; ConvertEmbed(ChatEmbed? embed)</div><div class="ttdoc">Convert a ChatEmbed to an IEmbed parameters.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l01020">DiscordProvider.cs:1020</a></div></div>
<div class="ttc" id="aclass_exception_html"><div class="ttname"><a href="class_exception.html">Exception</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_api_1_1_models_1_1_discord_connection_string_builder_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_discord_connection_string_builder.html">Tgstation.Server.Api.Models.DiscordConnectionStringBuilder</a></div><div class="ttdoc">ChatConnectionStringBuilder for ChatProvider.Discord.</div><div class="ttdef"><b>Definition</b> <a href="_discord_connection_string_builder_8cs_source.html#l00011">DiscordConnectionStringBuilder.cs:12</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html">Tgstation.Server.Api.Models.EngineVersion</a></div><div class="ttdoc">Information about an engine installation.</div><div class="ttdef"><b>Definition</b> <a href="_engine_version_8cs_source.html#l00013">EngineVersion.cs:14</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version_html_ae13db4c5dbd6b06c79d37ad9afd25af2"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html#ae13db4c5dbd6b06c79d37ad9afd25af2">Tgstation.Server.Api.Models.EngineVersion.Engine</a></div><div class="ttdeci">EngineType? Engine</div><div class="ttdoc">The EngineType.</div><div class="ttdef"><b>Definition</b> <a href="_engine_version_8cs_source.html#l00024">EngineVersion.cs:24</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version_html_af9d95aff0fd29f0d587bdc78b4969a77"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_engine_version.html#af9d95aff0fd29f0d587bdc78b4969a77">Tgstation.Server.Api.Models.EngineVersion.CustomIteration</a></div><div class="ttdeci">int? CustomIteration</div><div class="ttdoc">The revision of the custom build.</div><div class="ttdef"><b>Definition</b> <a href="_engine_version_8cs_source.html#l00045">EngineVersion.cs:45</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot_settings_html_acdc14bc7df5569305c8a5af42e61f1da"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot_settings.html#acdc14bc7df5569305c8a5af42e61f1da">Tgstation.Server.Api.Models.Internal.ChatBotSettings.ConnectionString</a></div><div class="ttdeci">string? ConnectionString</div><div class="ttdoc">The information used to connect to the Provider.</div><div class="ttdef"><b>Definition</b> <a href="_chat_bot_settings_8cs_source.html#l00046">ChatBotSettings.cs:46</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_channel_base_html_af9afe694fd82c175dd24e8a0303ee8cf"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_channel_base.html#af9afe694fd82c175dd24e8a0303ee8cf">Tgstation.Server.Api.Models.Internal.ChatChannelBase.IsAdminChannel</a></div><div class="ttdeci">bool? IsAdminChannel</div><div class="ttdoc">If the ChatChannel is an admin channel.</div><div class="ttdef"><b>Definition</b> <a href="_chat_channel_base_8cs_source.html#l00015">ChatChannelBase.cs:15</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html">Tgstation.Server.Common.Extensions.ValueTaskExtensions</a></div><div class="ttdoc">Extension methods for the ValueTask and ValueTask&lt;TResult&gt; classes.</div><div class="ttdef"><b>Definition</b> <a href="_value_task_extensions_8cs_source.html#l00011">ValueTaskExtensions.cs:12</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions_html_a58adbd94d764754bd3e6c566a5fe7fe3"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_common_1_1_extensions_1_1_value_task_extensions.html#a58adbd94d764754bd3e6c566a5fe7fe3">Tgstation.Server.Common.Extensions.ValueTaskExtensions.WhenAll</a></div><div class="ttdeci">static async ValueTask WhenAll(IEnumerable&lt; ValueTask &gt; tasks)</div><div class="ttdoc">Fully await a given list of tasks .</div><div class="ttdef"><b>Definition</b> <a href="_value_task_extensions_8cs_source.html#l00099">ValueTaskExtensions.cs:99</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html">Tgstation.Server.Host.Components.Chat.ChannelRepresentation</a></div><div class="ttdoc">Represents a Providers.IProvider channel.</div><div class="ttdef"><b>Definition</b> <a href="_channel_representation_8cs_source.html#l00012">ChannelRepresentation.cs:13</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation_html_a5e3306682c350b0cfac4507762b6d8b1"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html#a5e3306682c350b0cfac4507762b6d8b1">Tgstation.Server.Host.Components.Chat.ChannelRepresentation.IsAdminChannel</a></div><div class="ttdeci">bool IsAdminChannel</div><div class="ttdoc">If this is considered a channel for admin commands.</div><div class="ttdef"><b>Definition</b> <a href="_channel_representation_8cs_source.html#l00043">ChannelRepresentation.cs:43</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation_html_ad5ca4b4a856afa45b02ba2ed9c324fce"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_channel_representation.html#ad5ca4b4a856afa45b02ba2ed9c324fce">Tgstation.Server.Host.Components.Chat.ChannelRepresentation.Tag</a></div><div class="ttdeci">string? Tag</div><div class="ttdoc">For user use.</div><div class="ttdef"><b>Definition</b> <a href="_channel_representation_8cs_source.html#l00053">ChannelRepresentation.cs:53</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_manager_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_manager.html">Tgstation.Server.Host.Components.Chat.ChatManager</a></div><div class="ttdef"><b>Definition</b> <a href="_chat_manager_8cs_source.html#l00028">ChatManager.cs:29</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_manager_html_a0b5b0d03d129b21de29dc2c2bbf17edf"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_manager.html#a0b5b0d03d129b21de29dc2c2bbf17edf">Tgstation.Server.Host.Components.Chat.ChatManager.CommonMention</a></div><div class="ttdeci">const string CommonMention</div><div class="ttdoc">The common bot mention.</div><div class="ttdef"><b>Definition</b> <a href="_chat_manager_8cs_source.html#l00033">ChatManager.cs:33</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_user_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat_user.html">Tgstation.Server.Host.Components.Chat.ChatUser</a></div><div class="ttdoc">Represents a tgs_chat_user datum.</div><div class="ttdef"><b>Definition</b> <a href="_chat_user_8cs_source.html#l00011">ChatUser.cs:12</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_message_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_message.html">Tgstation.Server.Host.Components.Chat.Providers.DiscordMessage</a></div><div class="ttdoc">A Message containing the source IMessageReference.</div><div class="ttdef"><b>Definition</b> <a href="_discord_message_8cs_source.html#l00009">DiscordMessage.cs:10</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider</a></div><div class="ttdoc">IProvider for the Discord app.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00043">DiscordProvider.cs:44</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a01881ab9506db0431f75db21224bf7e6"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a01881ab9506db0431f75db21224bf7e6">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.connectDisconnectLock</a></div><div class="ttdeci">readonly object connectDisconnectLock</div><div class="ttdoc">Lock object used to sychronize connect/disconnect operations.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00093">DiscordProvider.cs:93</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a044ae95d278a4ed4a6a02449e24e8146"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a044ae95d278a4ed4a6a02449e24e8146">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.mappedChannels</a></div><div class="ttdeci">readonly List&lt; ulong &gt; mappedChannels</div><div class="ttdoc">List&lt;T&gt; of mapped channel Snowflakes.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00088">DiscordProvider.cs:88</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a1494b2b91cc869199100c9338f91d864"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1494b2b91cc869199100c9338f91d864">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.SendMessage</a></div><div class="ttdeci">override async ValueTask SendMessage(Message? replyTo, MessageContent message, ulong channelId, CancellationToken cancellationToken)</div><div class="ttdoc">Send a message to the IProvider.A ValueTask representing the running operation.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00198">DiscordProvider.cs:198</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a182447c000f64abfb2e30336a6b9718f"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a182447c000f64abfb2e30336a6b9718f">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.deploymentBranding</a></div><div class="ttdeci">readonly bool deploymentBranding</div><div class="ttdoc">If the tgstation-server logo is shown in deployment embeds.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00098">DiscordProvider.cs:98</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a1896b3a7ddd7b500c2624d3676b64eaf"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a1896b3a7ddd7b500c2624d3676b64eaf">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.SupportedGuildChannelTypes</a></div><div class="ttdeci">static readonly ChannelType[] SupportedGuildChannelTypes</div><div class="ttdoc">The ChannelTypes supported by the DiscordProvider for mapping.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00062">DiscordProvider.cs:62</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a317ac4b2144b7b5d2764063b158c7f54"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a317ac4b2144b7b5d2764063b158c7f54">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.disposing</a></div><div class="ttdeci">bool disposing</div><div class="ttdoc">If serviceProvider is being disposed.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00128">DiscordProvider.cs:128</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a38455db633742e90572b9a83aa681831"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a38455db633742e90572b9a83aa681831">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.currentUserId</a></div><div class="ttdeci">Snowflake currentUserId</div><div class="ttdoc">The bot's Snowflake.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00123">DiscordProvider.cs:123</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a3cf5b9ba9079d6c9f582f61b5894f7c1"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3cf5b9ba9079d6c9f582f61b5894f7c1">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.NormalizeMentions</a></div><div class="ttdeci">static string NormalizeMentions(string fromDiscord)</div><div class="ttdoc">Normalize a discord mention string.</div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a3f81033139026af1ea3160ef0063e737"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3f81033139026af1ea3160ef0063e737">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.gatewayReadyTcs</a></div><div class="ttdeci">TaskCompletionSource? gatewayReadyTcs</div><div class="ttdoc">The TaskCompletionSource for the initial gateway connection event.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00113">DiscordProvider.cs:113</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a3fd130f635e4577bedefa9926a4e2c73"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a3fd130f635e4577bedefa9926a4e2c73">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.Connect</a></div><div class="ttdeci">override async ValueTask Connect(CancellationToken cancellationToken)</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00584">DiscordProvider.cs:584</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a48adcd32348dbab4150bd2c8087623e0"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a48adcd32348dbab4150bd2c8087623e0">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.MapChannelsImpl</a></div><div class="ttdeci">override async ValueTask&lt; Dictionary&lt; Models.ChatChannel, IEnumerable&lt; ChannelRepresentation &gt; &gt; &gt; MapChannelsImpl(IEnumerable&lt; Models.ChatChannel &gt; channels, CancellationToken cancellationToken)</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00669">DiscordProvider.cs:669</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a6b14b94a01f2a1478f1ade14ef9a7471"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a6b14b94a01f2a1478f1ade14ef9a7471">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.SendUpdateMessage</a></div><div class="ttdeci">override async ValueTask&lt; Func&lt; string?, string, ValueTask&lt; Func&lt; bool, ValueTask &gt; &gt; &gt; &gt; SendUpdateMessage(Models.RevisionInformation revisionInformation, Models.RevisionInformation? previousRevisionInformation, EngineVersion engineVersion, DateTimeOffset? estimatedCompletionTime, string? gitHubOwner, string? gitHubRepo, ulong channelId, bool localCommitPushed, CancellationToken cancellationToken)</div><div class="ttdoc">Send the message for a deployment.A ValueTask&lt;TResult&gt; resulting in a Func&lt;T1, T2,...</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00305">DiscordProvider.cs:305</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a73f7fae07fc8d7efc90b6464dc2eca79"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a73f7fae07fc8d7efc90b6464dc2eca79">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.assemblyInformationProvider</a></div><div class="ttdeci">readonly IAssemblyInformationProvider assemblyInformationProvider</div><div class="ttdoc">The IAssemblyInformationProvider for the DiscordProvider.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00073">DiscordProvider.cs:73</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a8d7bbc5ddb64df2800554c354ff1974a"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a8d7bbc5ddb64df2800554c354ff1974a">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.RespondAsync</a></div><div class="ttdeci">async Task&lt; Result &gt; RespondAsync(IMessageCreate messageCreateEvent, CancellationToken cancellationToken)</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00483">DiscordProvider.cs:483</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a96681c4d5a393d80bd2ff022eed95ee5"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a96681c4d5a393d80bd2ff022eed95ee5">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.outputDisplayType</a></div><div class="ttdeci">readonly DiscordDMOutputDisplayType outputDisplayType</div><div class="ttdoc">The DiscordDMOutputDisplayType.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00103">DiscordProvider.cs:103</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a968f8dd1140ebe40a77c774fe7f9019b"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a968f8dd1140ebe40a77c774fe7f9019b">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.gatewayTask</a></div><div class="ttdeci">Task&lt; Result &gt;? gatewayTask</div><div class="ttdoc">The Task representing the lifetime of the client.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00118">DiscordProvider.cs:118</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_a9998d613750e44e779ae89931f7cfd98"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#a9998d613750e44e779ae89931f7cfd98">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.DisconnectImpl</a></div><div class="ttdeci">override async ValueTask DisconnectImpl(CancellationToken cancellationToken)</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00644">DiscordProvider.cs:644</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_aa0b4853705d24be3e16314bf050f9e7c"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aa0b4853705d24be3e16314bf050f9e7c">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.BuildUpdateEmbedFields</a></div><div class="ttdeci">List&lt; IEmbedField &gt; BuildUpdateEmbedFields(Models.RevisionInformation revisionInformation, Models.RevisionInformation? previousRevisionInformation, EngineVersion engineVersion, string? gitHubOwner, string? gitHubRepo, bool localCommitPushed)</div><div class="ttdoc">Create a List&lt;T&gt; of IEmbedFields for a discord update embed.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00911">DiscordProvider.cs:911</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_ab4076d0667f118cef056a4d3d5ab6b4a"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab4076d0667f118cef056a4d3d5ab6b4a">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.DiscordProvider</a></div><div class="ttdeci">DiscordProvider(IJobManager jobManager, IAsyncDelayer asyncDelayer, ILogger&lt; DiscordProvider &gt; logger, IAssemblyInformationProvider assemblyInformationProvider, IOptionsMonitor&lt; GeneralConfiguration &gt; generalConfigurationOptions, ChatBot chatBot)</div><div class="ttdoc">Initializes a new instance of the DiscordProvider class.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00146">DiscordProvider.cs:146</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_ab650903107863653f1b637562f4813b4"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab650903107863653f1b637562f4813b4">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.DisposeAsync</a></div><div class="ttdeci">override async ValueTask DisposeAsync()</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00175">DiscordProvider.cs:175</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_ab92d4920074cec3e48fa204af595a498"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ab92d4920074cec3e48fa204af595a498">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.GetAllAccessibleTextChannels</a></div><div class="ttdeci">async ValueTask&lt; IEnumerable&lt; IChannel &gt; &gt; GetAllAccessibleTextChannels(CancellationToken cancellationToken)</div><div class="ttdoc">Get all text IChannels accessible to and supported by the bot.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00847">DiscordProvider.cs:847</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_ac2744da20824177724b971eb20a6d5a0"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac2744da20824177724b971eb20a6d5a0">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.Connected</a></div><div class="ttdeci">override bool Connected</div><div class="ttdoc">If the IProvider is currently connected.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00046">DiscordProvider.cs:46</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_ac93400b45eefb577306a70a7a530147f"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ac93400b45eefb577306a70a7a530147f">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.generalConfigurationOptions</a></div><div class="ttdeci">readonly IOptionsMonitor&lt; GeneralConfiguration &gt; generalConfigurationOptions</div><div class="ttdoc">The GeneralConfiguration IOptionsMonitor&lt;TOptions&gt; for the DiscordProvider.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00078">DiscordProvider.cs:78</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_addfb0baffffb90712e76e9bfc1800a15"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#addfb0baffffb90712e76e9bfc1800a15">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.RespondAsync</a></div><div class="ttdeci">Task&lt; Result &gt; RespondAsync(IReady readyEvent, CancellationToken cancellationToken)</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00574">DiscordProvider.cs:574</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_ae7dd055bf64dcff2228ae66fdcff7e92"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#ae7dd055bf64dcff2228ae66fdcff7e92">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.serviceProvider</a></div><div class="ttdeci">readonly ServiceProvider serviceProvider</div><div class="ttdoc">The ServiceProvider containing Discord services.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00083">DiscordProvider.cs:83</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_aecdf08d03a7a5fad8b9ff607fbec8bb6"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#aecdf08d03a7a5fad8b9ff607fbec8bb6">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.gatewayCts</a></div><div class="ttdeci">CancellationTokenSource? gatewayCts</div><div class="ttdoc">The CancellationTokenSource for the gatewayTask.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00108">DiscordProvider.cs:108</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider_html_af40c0ea392de9986a4705d403674f61c"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_discord_provider.html#af40c0ea392de9986a4705d403674f61c">Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.BotMention</a></div><div class="ttdeci">override string BotMention</div><div class="ttdoc">The string that indicates the IProvider was mentioned.</div><div class="ttdef"><b>Definition</b> <a href="_discord_provider_8cs_source.html#l00049">DiscordProvider.cs:50</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_message_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_message.html">Tgstation.Server.Host.Components.Chat.Providers.Message</a></div><div class="ttdoc">Represents a message received by a IProvider.</div><div class="ttdef"><b>Definition</b> <a href="_message_8cs_source.html#l00008">Message.cs:9</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html">Tgstation.Server.Host.Components.Chat.Providers.Provider</a></div><div class="ttdef"><b>Definition</b> <a href="_provider_8cs_source.html#l00017">Provider.cs:18</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider_html_a6a6dd225ccb27e30c2cc06562b035ebe"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#a6a6dd225ccb27e30c2cc06562b035ebe">Tgstation.Server.Host.Components.Chat.Providers.Provider.EnqueueMessage</a></div><div class="ttdeci">void EnqueueMessage(Message? message)</div><div class="ttdoc">Queues a message for NextMessage(CancellationToken).</div><div class="ttdef"><b>Definition</b> <a href="_provider_8cs_source.html#l00239">Provider.cs:239</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider_html_a838ad29e96221a58a71b29358c086c0c"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#a838ad29e96221a58a71b29358c086c0c">Tgstation.Server.Host.Components.Chat.Providers.Provider.GetEngineCompilerPrefix</a></div><div class="ttdeci">static string GetEngineCompilerPrefix(Api.Models.EngineType engineType)</div><div class="ttdoc">Get the prefix for messages about deployments.</div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider_html_aa36ffb34c69e4a990830e49f97b7c142"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#aa36ffb34c69e4a990830e49f97b7c142">Tgstation.Server.Host.Components.Chat.Providers.Provider.jobManager</a></div><div class="ttdeci">readonly IJobManager jobManager</div><div class="ttdoc">The IJobManager for the Provider.</div><div class="ttdef"><b>Definition</b> <a href="_provider_8cs_source.html#l00040">Provider.cs:40</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider_html_ab24337ff80dfef1a9657f7106758a8c3"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_provider.html#ab24337ff80dfef1a9657f7106758a8c3">Tgstation.Server.Host.Components.Chat.Providers.Provider.Logger</a></div><div class="ttdeci">ILogger&lt; Provider &gt; Logger</div><div class="ttdoc">The ILogger for the Provider.</div><div class="ttdef"><b>Definition</b> <a href="_provider_8cs_source.html#l00035">Provider.cs:35</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_footer_html_a9d96e0c77d06d84dd00fda1451807370"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_footer.html#a9d96e0c77d06d84dd00fda1451807370">Tgstation.Server.Host.Components.Interop.ChatEmbedFooter.Text</a></div><div class="ttdeci">string? Text</div><div class="ttdoc">Gets the text of the footer.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_footer_8cs_source.html#l00011">ChatEmbedFooter.cs:11</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html">Tgstation.Server.Host.Components.Interop.ChatEmbed</a></div><div class="ttdoc">Represents an embed for the chat.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00008">ChatEmbed.cs:9</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html_a12270babc71891c5a8781910cfa71ddd"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a12270babc71891c5a8781910cfa71ddd">Tgstation.Server.Host.Components.Interop.ChatEmbed.Timestamp</a></div><div class="ttdeci">string? Timestamp</div><div class="ttdoc">The ISO 8601 timestamp of the embed.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00030">ChatEmbed.cs:30</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html_a3863a450e43588c18e28ea2f23c5131b"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a3863a450e43588c18e28ea2f23c5131b">Tgstation.Server.Host.Components.Interop.ChatEmbed.Image</a></div><div class="ttdeci">ChatEmbedMedia? Image</div><div class="ttdoc">The ChatEmbedMedia for an image.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00045">ChatEmbed.cs:45</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html_a43303379f4417e94d9cf6b284dae031d"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a43303379f4417e94d9cf6b284dae031d">Tgstation.Server.Host.Components.Interop.ChatEmbed.Footer</a></div><div class="ttdeci">ChatEmbedFooter? Footer</div><div class="ttdoc">The ChatEmbedFooter.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00040">ChatEmbed.cs:40</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html_a576730e6f32d18333550f8a393331f91"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#a576730e6f32d18333550f8a393331f91">Tgstation.Server.Host.Components.Interop.ChatEmbed.Thumbnail</a></div><div class="ttdeci">ChatEmbedMedia? Thumbnail</div><div class="ttdoc">The ChatEmbedMedia for a thumbnail.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00050">ChatEmbed.cs:50</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html_aaa3ea3f3ef8e52643d39711e0cf21090"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#aaa3ea3f3ef8e52643d39711e0cf21090">Tgstation.Server.Host.Components.Interop.ChatEmbed.Fields</a></div><div class="ttdeci">ICollection&lt; ChatEmbedField &gt;? Fields</div><div class="ttdoc">The ChatEmbedFields.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00070">ChatEmbed.cs:70</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html_ab1a422f0ae51751307a024c69c80de92"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#ab1a422f0ae51751307a024c69c80de92">Tgstation.Server.Host.Components.Interop.ChatEmbed.Colour</a></div><div class="ttdeci">string? Colour</div><div class="ttdoc">The colour of the embed in the format hex &quot;#AARRGGBB&quot;.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00035">ChatEmbed.cs:35</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_html_acf2a8d23747fbdf8349687db989857df"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed.html#acf2a8d23747fbdf8349687db989857df">Tgstation.Server.Host.Components.Interop.ChatEmbed.Author</a></div><div class="ttdeci">ChatEmbedAuthor? Author</div><div class="ttdoc">The ChatEmbedAuthor.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_8cs_source.html#l00065">ChatEmbed.cs:65</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_media_html_a3b31d2e65dd3361c1a318db4ab7c6757"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_media.html#a3b31d2e65dd3361c1a318db4ab7c6757">Tgstation.Server.Host.Components.Interop.ChatEmbedMedia.Url</a></div><div class="ttdeci">string? Url</div><div class="ttdoc">Gets the source URL of the media. Only supports http(s) and attachments.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_media_8cs_source.html#l00012">ChatEmbedMedia.cs:12</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_provider_html_a7d29bec0678fbbf1e1e87478bb36d897"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_chat_embed_provider.html#a7d29bec0678fbbf1e1e87478bb36d897">Tgstation.Server.Host.Components.Interop.ChatEmbedProvider.Name</a></div><div class="ttdeci">string? Name</div><div class="ttdoc">Gets the name of the provider.</div><div class="ttdef"><b>Definition</b> <a href="_chat_embed_provider_8cs_source.html#l00011">ChatEmbedProvider.cs:11</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content.html">Tgstation.Server.Host.Components.Interop.MessageContent</a></div><div class="ttdoc">Represents a message to send to a chat provider.</div><div class="ttdef"><b>Definition</b> <a href="_message_content_8cs_source.html#l00006">MessageContent.cs:7</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content_html_a60f2aaeaf7f59e642e62b322bb1bce63"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content.html#a60f2aaeaf7f59e642e62b322bb1bce63">Tgstation.Server.Host.Components.Interop.MessageContent.Embed</a></div><div class="ttdeci">ChatEmbed? Embed</div><div class="ttdoc">The ChatEmbed.</div><div class="ttdef"><b>Definition</b> <a href="_message_content_8cs_source.html#l00016">MessageContent.cs:16</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content_html_acc847c3c842120dede3072ddb6e0c0cd"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_message_content.html#acc847c3c842120dede3072ddb6e0c0cd">Tgstation.Server.Host.Components.Interop.MessageContent.Text</a></div><div class="ttdeci">string? Text</div><div class="ttdoc">The message string.</div><div class="ttdef"><b>Definition</b> <a href="_message_content_8cs_source.html#l00011">MessageContent.cs:11</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html">Tgstation.Server.Host.Jobs.JobException</a></div><div class="ttdoc">Operation exceptions thrown from the context of a Models.Job.</div><div class="ttdef"><b>Definition</b> <a href="_job_exception_8cs_source.html#l00010">JobException.cs:11</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_models_1_1_chat_bot_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_models_1_1_chat_bot.html">Tgstation.Server.Host.Models.ChatBot</a></div><div class="ttdef"><b>Definition</b> <a href="_models_2_chat_bot_8cs_source.html#l00011">ChatBot.cs:12</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_models_1_1_chat_channel_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_models_1_1_chat_channel.html">Tgstation.Server.Host.Models.ChatChannel</a></div><div class="ttdef"><b>Definition</b> <a href="_tgstation_8_server_8_host_2_models_2_chat_channel_8cs_source.html#l00010">ChatChannel.cs:11</a></div></div>
<div class="ttc" id="aclass_tgstation_1_1_server_1_1_host_1_1_models_1_1_rev_info_test_merge_html"><div class="ttname"><a href="class_tgstation_1_1_server_1_1_host_1_1_models_1_1_rev_info_test_merge.html">Tgstation.Server.Host.Models.RevInfoTestMerge</a></div><div class="ttdoc">Many to many relationship for Models.RevisionInformation and Models.TestMerge.</div><div class="ttdef"><b>Definition</b> <a href="_rev_info_test_merge_8cs_source.html#l00009">RevInfoTestMerge.cs:10</a></div></div>
<div class="ttc" id="ainterface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_discord_responders_html"><div class="ttname"><a href="interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_discord_responders.html">Tgstation.Server.Host.Components.Chat.Providers.IDiscordResponders</a></div><div class="ttdoc">Combined interface for the IResponder types used by TGS.</div><div class="ttdef"><b>Definition</b> <a href="_i_discord_responders_8cs_source.html#l00009">IDiscordResponders.cs:10</a></div></div>
<div class="ttc" id="ainterface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager_html"><div class="ttname"><a href="interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html">Tgstation.Server.Host.Jobs.IJobManager</a></div><div class="ttdoc">Manages the runtime of Jobs.</div><div class="ttdef"><b>Definition</b> <a href="_i_job_manager_8cs_source.html#l00012">IJobManager.cs:13</a></div></div>
<div class="ttc" id="ainterface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider_html"><div class="ttname"><a href="interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider.html">Tgstation.Server.Host.System.IAssemblyInformationProvider</a></div><div class="ttdoc">For retrieving the Assembly's location.</div><div class="ttdef"><b>Definition</b> <a href="_i_assembly_information_provider_8cs_source.html#l00010">IAssemblyInformationProvider.cs:11</a></div></div>
<div class="ttc" id="ainterface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider_html_ab2a2be82555afbf6ffb5b7ae3d90b7f0"><div class="ttname"><a href="interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider.html#ab2a2be82555afbf6ffb5b7ae3d90b7f0">Tgstation.Server.Host.System.IAssemblyInformationProvider.VersionPrefix</a></div><div class="ttdeci">string VersionPrefix</div><div class="ttdoc">Prefix to VersionString.</div><div class="ttdef"><b>Definition</b> <a href="_i_assembly_information_provider_8cs_source.html#l00025">IAssemblyInformationProvider.cs:25</a></div></div>
<div class="ttc" id="ainterface_tgstation_1_1_server_1_1_host_1_1_utils_1_1_i_async_delayer_html"><div class="ttname"><a href="interface_tgstation_1_1_server_1_1_host_1_1_utils_1_1_i_async_delayer.html">Tgstation.Server.Host.Utils.IAsyncDelayer</a></div><div class="ttdoc">For waiting asynchronously.</div><div class="ttdef"><b>Definition</b> <a href="_i_async_delayer_8cs_source.html#l00010">IAsyncDelayer.cs:11</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal.html">Tgstation.Server.Api.Models.Internal</a></div><div class="ttdef"><b>Definition</b> <a href="_chat_bot_api_base_8cs_source.html#l00005">ChatBotApiBase.cs:6</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_api_1_1_models_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html">Tgstation.Server.Api.Models</a></div><div class="ttdef"><b>Definition</b> <a href="_tgstation_8_server_8_api_2_models_2_chat_channel_8cs_source.html#l00005">ChatChannel.cs:6</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_api_1_1_models_html_a1a6adb59dd51244efabf4e548e7075c8"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#a1a6adb59dd51244efabf4e548e7075c8">Tgstation.Server.Api.Models.ErrorCode</a></div><div class="ttdeci">ErrorCode</div><div class="ttdoc">Types of Response.ErrorMessageResponses that the API may return.</div><div class="ttdef"><b>Definition</b> <a href="_error_code_8cs_source.html#l00011">ErrorCode.cs:12</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_api_1_1_models_html_ad8fb60934662752c4bbed899440208ea"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#ad8fb60934662752c4bbed899440208ea">Tgstation.Server.Api.Models.EngineType</a></div><div class="ttdeci">EngineType</div><div class="ttdoc">The type of engine the codebase is using.</div><div class="ttdef"><b>Definition</b> <a href="_engine_type_8cs_source.html#l00006">EngineType.cs:7</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_api_1_1_models_html_ae758c5cd6d61f61a7dc4b6f3c7000b52aebb061953c0454b2c8ee7b0ac615ebcd"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#ae758c5cd6d61f61a7dc4b6f3c7000b52aebb061953c0454b2c8ee7b0ac615ebcd">Tgstation.Server.Api.Models.DMApiValidationMode.Optional</a></div><div class="ttdeci">@ Optional</div><div class="ttdoc">DMAPI validation is performed but not required for the deployment to succeed.</div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_api_1_1_models_html_af16952d12561118ecebc3d8ccf510221"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_api_1_1_models.html#af16952d12561118ecebc3d8ccf510221">Tgstation.Server.Api.Models.DiscordDMOutputDisplayType</a></div><div class="ttdeci">DiscordDMOutputDisplayType</div><div class="ttdoc">When the DM output section of Discord deployment embeds should be shown.</div><div class="ttdef"><b>Definition</b> <a href="_discord_d_m_output_display_type_8cs_source.html#l00006">DiscordDMOutputDisplayType.cs:7</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_common_1_1_extensions_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_common_1_1_extensions.html">Tgstation.Server.Common.Extensions</a></div><div class="ttdef"><b>Definition</b> <a href="_value_task_extensions_8cs_source.html#l00006">ValueTaskExtensions.cs:7</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers.html">Tgstation.Server.Host.Components.Chat.Providers</a></div><div class="ttdef"><b>Definition</b> <a href="_discord_forwarding_responder_8cs_source.html#l00009">DiscordForwardingResponder.cs:10</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop.html">Tgstation.Server.Host.Components.Interop</a></div><div class="ttdef"><b>Definition</b> <a href="_bridge_command_type_8cs_source.html#l00001">BridgeCommandType.cs:2</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_configuration_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_configuration.html">Tgstation.Server.Host.Configuration</a></div><div class="ttdef"><b>Definition</b> <a href="_control_panel_configuration_8cs_source.html#l00003">ControlPanelConfiguration.cs:4</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_extensions_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_extensions.html">Tgstation.Server.Host.Extensions</a></div><div class="ttdef"><b>Definition</b> <a href="_application_builder_extensions_8cs_source.html#l00021">ApplicationBuilderExtensions.cs:22</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_jobs_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_jobs.html">Tgstation.Server.Host.Jobs</a></div><div class="ttdef"><b>Definition</b> <a href="_i_job_manager_8cs_source.html#l00007">IJobManager.cs:8</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_models_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_models.html">Tgstation.Server.Host.Models</a></div><div class="ttdef"><b>Definition</b> <a href="_models_2_chat_bot_8cs_source.html#l00008">ChatBot.cs:9</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_system_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_system.html">Tgstation.Server.Host.System</a></div><div class="ttdef"><b>Definition</b> <a href="_assembly_information_provider_8cs_source.html#l00008">AssemblyInformationProvider.cs:9</a></div></div>
<div class="ttc" id="anamespace_tgstation_1_1_server_1_1_host_1_1_utils_html"><div class="ttname"><a href="namespace_tgstation_1_1_server_1_1_host_1_1_utils.html">Tgstation.Server.Host.Utils</a></div><div class="ttdef"><b>Definition</b> <a href="_graph_q_l_git_lab_client_8cs_source.html#l00006">GraphQLGitLabClient.cs:7</a></div></div>
</div><!-- fragment --></div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.8
</small></address>
</body>
</html>