Advertisement
Guest User

Untitled

a guest
Jul 19th, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.81 KB | None | 0 0
  1. #pragma semicolon 1
  2.  
  3. #include <sourcemod>
  4. #include <sdktools>
  5. #include <discord>
  6. #include <socket>
  7. #include <morecolors>
  8. #include <basecomm>
  9.  
  10. #undef REQUIRE_PLUGIN
  11. #include <chat-processor>
  12.  
  13. #pragma newdecls required
  14.  
  15.  
  16. // Socket Handles
  17. Handle gH_Socket = INVALID_HANDLE;
  18.  
  19. // Clients
  20. ArrayList gAL_Clients;
  21.  
  22. // Discord Bot
  23. DiscordBot gDB_Bot = view_as<DiscordBot>(INVALID_HANDLE);
  24.  
  25. // ConVars
  26. ConVar gCV_DiscordChatChannel;
  27.  
  28. ConVar gCV_DiscordEnable;
  29.  
  30. ConVar gCV_SocketEnable;
  31. ConVar gCV_SocketPort;
  32.  
  33. ConVar gCV_ServerMessageTag;
  34. ConVar gCV_DiscordMessageTag;
  35.  
  36. char gS_BotToken[128];
  37.  
  38. char gS_ServerTag[128];
  39. char gS_DiscordTag[128];
  40.  
  41. bool gB_ChatProcessor;
  42. bool gB_ListeningToDiscord = false;
  43.  
  44.  
  45. public Plugin myinfo =
  46. {
  47.     name = "Discord Chat Relay - Server",
  48.     author = "PaxPlay, Credits to Ryan \"FLOOR_MASTER\" Mannion, shavit and Deathknife",
  49.     description = "Chat relay between a sourcemod server and Discord.",
  50.     version = "1.0.0",
  51.     url = ""
  52. };
  53.  
  54. public void OnPluginStart()
  55. {
  56.     gCV_DiscordChatChannel = CreateConVar("sm_discord_text_channel_id", "", "The Discord text channel id.");
  57.    
  58.     gCV_DiscordEnable = CreateConVar("sm_discord_relay_enable", "1", "Enable the chat relay with Discord.", 0, true, 0.0, true, 1.0);
  59.    
  60.     gCV_SocketEnable = CreateConVar("sm_discord_socket_enable", "0", "Enable the cross server chat relay.", 0, true, 0.0, true, 1.0);
  61.     gCV_SocketPort = CreateConVar("sm_discord_socket_port", "13370", "Port for the cross server chat relay socket.");
  62.    
  63.     gCV_ServerMessageTag = CreateConVar("sm_discord_chat_prefix_server", "{grey}[{green}SERVER{grey}]", "Chat Tag for messages from the server.");
  64.     gCV_DiscordMessageTag = CreateConVar("sm_discord_chat_prefix_discord", "{grey}[{blue}DISCORD{grey}]", "Chat Tag for messages from discord.");
  65.    
  66.     gCV_ServerMessageTag.AddChangeHook(OnConVarChanged);
  67.     gCV_DiscordMessageTag.AddChangeHook(OnConVarChanged);
  68.    
  69.     AutoExecConfig(true, "discord-chat-relay-server", "sourcemod");
  70.    
  71.     gB_ChatProcessor = LibraryExists("chat-processor");
  72.    
  73.     AddCommandListener(Hook_ChatMessage, "say");
  74.     AddCommandListener(Hook_ChatMessage, "say_team");
  75. }
  76.  
  77. public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
  78. {
  79.     UpdateCvars();
  80. }
  81.  
  82. void UpdateCvars()
  83. {
  84.     char buffer[MAX_BUFFER_LENGTH];
  85.     gCV_ServerMessageTag.GetString(buffer, sizeof(buffer));
  86.     FormatEx(gS_ServerTag, sizeof(gS_ServerTag), "%s", buffer); // Update Gameserver Chat Tag
  87.    
  88.     gCV_DiscordMessageTag.GetString(buffer, sizeof(buffer));
  89.     FormatEx(gS_DiscordTag, sizeof(gS_DiscordTag), "%s", buffer);   // Update Discord Chat Tag
  90. }
  91.  
  92. bool LoadConfig()
  93. {
  94.     char[] sPath = new char[PLATFORM_MAX_PATH];
  95.     BuildPath(Path_SM, sPath, PLATFORM_MAX_PATH, "configs/dcr.cfg");
  96.    
  97.     if (!FileExists(sPath))
  98.     {
  99.         File hFile = OpenFile(sPath, "w");
  100.         WriteFileLine(hFile, "\"discord-chat-relay\"");
  101.         WriteFileLine(hFile, "{");
  102.         WriteFileLine(hFile, "\t\"bot-token\"\t\"<insert-bot-token>\"");
  103.         WriteFileLine(hFile, "}");
  104.         CloseHandle(hFile);
  105.        
  106.         LogError("[DCR] \"%s\" not found, creating!", sPath);
  107.         return false;
  108.     }
  109.    
  110.     KeyValues kv = new KeyValues("discord-chat-relay");
  111.    
  112.     if(!kv.ImportFromFile(sPath))
  113.     {
  114.         delete kv;
  115.         LogError("[DCR] Couldnt import KeyValues from \"%s\"!", sPath);
  116.        
  117.         return false;
  118.     }
  119.    
  120.     kv.GetString("bot-token", gS_BotToken, sizeof(gS_BotToken));
  121.    
  122.     LogMessage("Loaded the BotToken.");
  123.    
  124.     delete kv;
  125.     return true;
  126. }
  127.  
  128. public void OnAllPluginsLoaded()
  129. {
  130.     if(gDB_Bot != view_as<DiscordBot>(INVALID_HANDLE))
  131.         return;
  132.    
  133.     if (LoadConfig())
  134.         gDB_Bot = new DiscordBot(gS_BotToken);
  135.     else
  136.         LogError("Couldnt load the dcr config.");
  137. }
  138.  
  139. public void OnConfigsExecuted()
  140. {
  141.     UpdateCvars();
  142.    
  143.     if (gCV_DiscordEnable.BoolValue && gDB_Bot != view_as<DiscordBot>(INVALID_HANDLE))
  144.     {
  145.         if(!gB_ListeningToDiscord)
  146.             gDB_Bot.GetGuilds(GuildList, INVALID_FUNCTION);
  147.     }
  148.    
  149.     if(gCV_SocketEnable.BoolValue && gH_Socket == INVALID_HANDLE)
  150.     {
  151.         char ip[24];
  152.         int port = gCV_SocketPort.IntValue;
  153.         GetServerIP(ip, sizeof(ip));
  154.        
  155.         gH_Socket = SocketCreate(SOCKET_TCP, OnSocketError);
  156.         SocketBind(gH_Socket, ip, port);
  157.         SocketListen(gH_Socket, OnSocketIncoming);
  158.        
  159.         gAL_Clients = CreateArray();
  160.        
  161.         LogMessage("%s chat-processor. DCR %s be able to send messages.", gB_ChatProcessor ? "Found" : "Couldn\'t find", gB_ChatProcessor ? "will" : "won\'t");
  162.    
  163.         LogMessage("[DCR] Started Server Chat Relay server on port %d", port);
  164.     }
  165. }
  166.  
  167. public void GuildList(DiscordBot bot, char[] id, char[] name, char[] icon, bool owner, int permissions, any data)
  168. {
  169.     gDB_Bot.GetGuildChannels(id, ChannelList, INVALID_FUNCTION);
  170. }
  171.  
  172. public void ChannelList(DiscordBot bot, char[] guild, DiscordChannel Channel, any data)
  173. {
  174.     if(Channel.IsText) {
  175.         char id[32];
  176.         Channel.GetID(id, sizeof(id));
  177.        
  178.         char sChannelID[64];
  179.         gCV_DiscordChatChannel.GetString(sChannelID, sizeof(sChannelID));
  180.        
  181.         if(StrEqual(id, sChannelID) && !gB_ListeningToDiscord)
  182.         {
  183.             gDB_Bot.StopListening();
  184.            
  185.             char name[32];
  186.             Channel.GetName(name, sizeof(name));
  187.             gDB_Bot.StartListeningToChannel(Channel, OnMessage);
  188.            
  189.             LogMessage("[DCR] Started listening to channel %s (%s)", name, id);
  190.             gB_ListeningToDiscord = true;
  191.         }
  192.     }
  193. }
  194.  
  195. public void OnMessage(DiscordBot Bot, DiscordChannel Channel, DiscordMessage message)
  196. {
  197.     if (message.GetAuthor().IsBot())
  198.         return;
  199.    
  200.     char sMessage[2048];
  201.     message.GetContent(sMessage, sizeof(sMessage));
  202.    
  203.     char sAuthor[128];
  204.     message.GetAuthor().GetUsername(sAuthor, sizeof(sAuthor));
  205.    
  206.     Format(sMessage, sizeof(sMessage), "%s %s: %s", gS_DiscordTag, sAuthor, sMessage);
  207.    
  208.     CPrintToChatAll("%s", sMessage);
  209.     Broadcast(INVALID_HANDLE, sMessage, sizeof(sMessage));
  210. }
  211.  
  212. public Action Hook_ChatMessage(int client, const char[] command, int argc)
  213. {
  214.     if(BaseComm_IsClientGagged(client))
  215.     {
  216.         return Plugin_Continue;
  217.     }
  218.     char full_message[MAX_BUFFER_LENGTH];
  219.     GetCmdArgString(full_message, sizeof(full_message));
  220.     if(full_message[0] == '!' || full_message[1] == '!') // remove chat commands
  221.     {
  222.         return Plugin_Continue;
  223.     }
  224.    
  225.     char sMessage[MAX_BUFFER_LENGTH];
  226.     Format(sMessage, sizeof(sMessage), "%s %N: %s", gS_ServerTag, client, full_message);
  227.     ReplaceString(sMessage, sizeof(sMessage), "\"", "", false);
  228.  
  229.     //Broadcast() is questionnable...
  230.     Broadcast(INVALID_HANDLE, sMessage, sizeof(sMessage));
  231.    
  232.     SendToDiscord(sMessage ,sizeof(sMessage));
  233.     return Plugin_Continue;
  234. }
  235.  
  236. public void OnMessageSent(DiscordBot bot, char[] channel, DiscordMessage message, any data)
  237. {
  238.     char sMessage[2048];
  239.     message.GetContent(sMessage, sizeof(sMessage));
  240.     LogMessage("[SM] Message sent to discord: \"%s\".", sMessage);
  241. }
  242.  
  243. void GetServerIP(char[] ip, int length)
  244. {
  245.     int hostip = FindConVar("hostip").IntValue;
  246.  
  247.     Format(ip, length, "%d.%d.%d.%d",
  248.         (hostip >> 24 & 0xFF),
  249.         (hostip >> 16 & 0xFF),
  250.         (hostip >> 8 & 0xFF),
  251.         (hostip & 0xFF)
  252.         );
  253. }
  254.  
  255. bool Broadcast(Handle socket, const char[] message, int maxlength)
  256. {
  257.     if(!gCV_SocketEnable.BoolValue)
  258.         return false;
  259.    
  260.     if(gAL_Clients == INVALID_HANDLE)
  261.     {
  262.         LogError("In Broadcast, gAL_Clients was invalid. This should never happen!");
  263.         return false;
  264.     }
  265.    
  266.    
  267.     int size = gAL_Clients.Length;
  268.     Handle dest_socket = INVALID_HANDLE;
  269.    
  270.     for (int i = 0; i < size; i++)
  271.     {
  272.         dest_socket = gAL_Clients.Get(i);
  273.         if (dest_socket != socket) // Prevent sending back to the same server.
  274.         {
  275.             SocketSend(dest_socket, message, maxlength);
  276.         }
  277.     }
  278.    
  279.     if (socket != INVALID_HANDLE) // Prevent printing to the server chat, if message is by the server.
  280.     {
  281.         PrintToChatAll(" %s", message);
  282.     }
  283.     return true;
  284. }
  285.  
  286. void CloseSocket()
  287. {
  288.     if(gH_Socket != INVALID_HANDLE)
  289.     {
  290.         CloseHandle(gH_Socket);
  291.         gH_Socket = INVALID_HANDLE;
  292.         LogMessage("Closed local Server Chat Relay socket");
  293.     }
  294.     if(gAL_Clients != INVALID_HANDLE)
  295.     {
  296.         CloseHandle(gAL_Clients);
  297.     }
  298. }
  299.  
  300. void RemoveClient(Handle client)
  301. {
  302.  
  303.     if (gAL_Clients == INVALID_HANDLE)
  304.     {
  305.         LogError("Attempted to remove client while g_clients was invalid. This should never happen!");
  306.         return;
  307.     }
  308.    
  309.     int size = gAL_Clients.Length;
  310.     for (int i = 0; i < size; i++)
  311.     {
  312.         if(gAL_Clients.Get(i) == client)
  313.         {
  314.             gAL_Clients.Erase(i);
  315.             return;
  316.         }
  317.     }
  318.    
  319.     LogError("Could not find client in RemoveClient. This should never happen!");
  320. }
  321.  
  322. public int OnSocketIncoming(Handle socket, Handle newSocket, char[] remoteIP, int remotePort, any arg)
  323. {
  324.     if (gAL_Clients == INVALID_HANDLE) {
  325.         LogError("In OnSocketIncoming, gAL_Clients was invalid. This should never happen!");
  326.     }
  327.     else {
  328.         PushArrayCell(gAL_Clients, newSocket);
  329.     }
  330.  
  331.     SocketSetReceiveCallback(newSocket, OnChildSocketReceive);
  332.     SocketSetDisconnectCallback(newSocket, OnChildSocketDisconnected);
  333.     SocketSetErrorCallback(newSocket, OnChildSocketError);
  334. }
  335.  
  336. public int OnSocketDisconnected(Handle socket, any arg)
  337. {
  338.     CloseSocket();
  339. }
  340.  
  341. public int OnSocketError(Handle socket, const int errorType, const int errorNum, any arg)
  342. {
  343.     LogError("Socket error %d (errno %d)", errorType, errorNum);
  344.     CloseSocket();
  345. }
  346.  
  347. public int OnChildSocketReceive(Handle socket, char[] receiveData, const int dataSize, any arg)
  348. {
  349.     Broadcast(socket, receiveData, dataSize);
  350.    
  351.     SendToDiscord(receiveData, dataSize);
  352. }
  353.  
  354. public int OnChildSocketDisconnected(Handle socket, any arg) {
  355.     RemoveClient(socket);
  356.     CloseHandle(socket);
  357. }
  358.  
  359. public int OnChildSocketError(Handle socket, const int errorType, const int errorNum, any arg)
  360. {
  361.     LogError("Child socket error %d (errno %d)", errorType, errorNum);
  362.     RemoveClient(socket);
  363.     CloseHandle(socket);
  364. }
  365.  
  366. void SendToDiscord(const char[] message, int maxlength)
  367. {
  368.     char[] sMessage = new char[maxlength];
  369.     FormatEx(sMessage, maxlength, "%s", message);
  370.    
  371.     CRemoveTags(sMessage, maxlength);
  372.    
  373.     char sChannelID[64];
  374.     gCV_DiscordChatChannel.GetString(sChannelID, sizeof(sChannelID));
  375.     gDB_Bot.SendMessageToChannelID(sChannelID, sMessage, OnMessageSent);
  376. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement