SHARE
TWEET

Untitled

a guest Jul 19th, 2019 55 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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[MAX_BUFFER_LENGTH];
  37.  
  38. char gS_ServerTag[MAX_BUFFER_LENGTH];
  39. char gS_DiscordTag[MAX_BUFFER_LENGTH];
  40.  
  41. bool gB_ChatProcessor;
  42. bool gB_ListeningToDiscord = false;
  43.  
  44. StringMap h_UserTags;
  45.  
  46.  
  47. public Plugin myinfo =
  48. {
  49.     name = "Discord Chat Relay - Server",
  50.     author = "PaxPlay, Credits to Ryan \"FLOOR_MASTER\" Mannion, shavit and Deathknife",
  51.     description = "Chat relay between a sourcemod server and Discord.",
  52.     version = "1.0.0",
  53.     url = ""
  54. };
  55.  
  56. public void OnPluginStart()
  57. {
  58.     gCV_DiscordChatChannel = CreateConVar("sm_discord_text_channel_id", "", "The Discord text channel id.");
  59.    
  60.     gCV_DiscordEnable = CreateConVar("sm_discord_relay_enable", "1", "Enable the chat relay with Discord.", 0, true, 0.0, true, 1.0);
  61.    
  62.     gCV_SocketEnable = CreateConVar("sm_discord_socket_enable", "0", "Enable the cross server chat relay.", 0, true, 0.0, true, 1.0);
  63.     gCV_SocketPort = CreateConVar("sm_discord_socket_port", "13370", "Port for the cross server chat relay socket.");
  64.    
  65.     gCV_ServerMessageTag = CreateConVar("sm_discord_chat_prefix_server", "{grey}[{green}SERVER{grey}]", "Chat Tag for messages from the server.");
  66.     gCV_DiscordMessageTag = CreateConVar("sm_discord_chat_prefix_discord", "{grey}[{blue}DISCORD{grey}]", "Chat Tag for messages from discord.");
  67.    
  68.     gCV_ServerMessageTag.AddChangeHook(OnConVarChanged);
  69.     gCV_DiscordMessageTag.AddChangeHook(OnConVarChanged);
  70.    
  71.     AutoExecConfig(true, "discord-chat-relay-server", "sourcemod");
  72.    
  73.     gB_ChatProcessor = LibraryExists("chat-processor");
  74.    
  75.     AddCommandListener(Hook_ChatMessage, "say");
  76.     AddCommandListener(Hook_ChatMessage, "say_team");
  77.    
  78.     h_UserTags=new StringMap();
  79.    
  80.     KeyValues file=new KeyValues("");
  81.     char config[PLATFORM_MAX_PATH];
  82.     BuildPath(Path_SM, config, sizeof(config), "configs/custom-chatcolors.cfg");
  83.     if(!file.ImportFromFile(config))
  84.     {
  85.         PrintToChatAll("Failed to load the config!");
  86.     }
  87.     file.GotoFirstSubKey(false);
  88.     char section_name[64];
  89.     char value[64];
  90.     do
  91.     {
  92.         file.GetSectionName(section_name, sizeof(section_name));
  93.         if(StrContains(section_name, "STEAM_", false)<=-1)
  94.         {
  95.             continue;
  96.         }
  97.         file.GetString("tag", value, sizeof(value));
  98.         h_UserTags.SetString(section_name, value);
  99.     }
  100.     while(file.GotoNextKey(false));
  101.     delete file;
  102.    
  103. }
  104.  
  105. public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
  106. {
  107.     UpdateCvars();
  108. }
  109.  
  110. void UpdateCvars()
  111. {
  112.     char buffer[MAX_BUFFER_LENGTH];
  113.     gCV_ServerMessageTag.GetString(buffer, sizeof(buffer));
  114.     FormatEx(gS_ServerTag, sizeof(gS_ServerTag), "%s", buffer); // Update Gameserver Chat Tag
  115.    
  116.     gCV_DiscordMessageTag.GetString(buffer, sizeof(buffer));
  117.     FormatEx(gS_DiscordTag, sizeof(gS_DiscordTag), "%s", buffer);   // Update Discord Chat Tag
  118. }
  119.  
  120. bool LoadConfig()
  121. {
  122.     char[] sPath = new char[PLATFORM_MAX_PATH];
  123.     BuildPath(Path_SM, sPath, PLATFORM_MAX_PATH, "configs/dcr.cfg");
  124.    
  125.     if (!FileExists(sPath))
  126.     {
  127.         File hFile = OpenFile(sPath, "w");
  128.         WriteFileLine(hFile, "\"discord-chat-relay\"");
  129.         WriteFileLine(hFile, "{");
  130.         WriteFileLine(hFile, "\t\"bot-token\"\t\"<insert-bot-token>\"");
  131.         WriteFileLine(hFile, "}");
  132.         CloseHandle(hFile);
  133.        
  134.         LogError("[DCR] \"%s\" not found, creating!", sPath);
  135.         return false;
  136.     }
  137.    
  138.     KeyValues kv = new KeyValues("discord-chat-relay");
  139.    
  140.     if(!kv.ImportFromFile(sPath))
  141.     {
  142.         delete kv;
  143.         LogError("[DCR] Couldnt import KeyValues from \"%s\"!", sPath);
  144.        
  145.         return false;
  146.     }
  147.    
  148.     kv.GetString("bot-token", gS_BotToken, sizeof(gS_BotToken));
  149.    
  150.     LogMessage("Loaded the BotToken.");
  151.    
  152.     delete kv;
  153.     return true;
  154. }
  155.  
  156. public void OnAllPluginsLoaded()
  157. {
  158.     if(gDB_Bot != view_as<DiscordBot>(INVALID_HANDLE))
  159.     return;
  160.    
  161.     if (LoadConfig())
  162.     gDB_Bot = new DiscordBot(gS_BotToken);
  163.     else
  164.     LogError("Couldnt load the dcr config.");
  165. }
  166.  
  167. public void OnConfigsExecuted()
  168. {
  169.     UpdateCvars();
  170.    
  171.     if (gCV_DiscordEnable.BoolValue && gDB_Bot != view_as<DiscordBot>(INVALID_HANDLE))
  172.     {
  173.         if(!gB_ListeningToDiscord)
  174.         gDB_Bot.GetGuilds(GuildList, INVALID_FUNCTION);
  175.     }
  176.    
  177.     if(gCV_SocketEnable.BoolValue && gH_Socket == INVALID_HANDLE)
  178.     {
  179.         char ip[24];
  180.         int port = gCV_SocketPort.IntValue;
  181.         GetServerIP(ip, sizeof(ip));
  182.        
  183.         gH_Socket = SocketCreate(SOCKET_TCP, OnSocketError);
  184.         SocketBind(gH_Socket, ip, port);
  185.         SocketListen(gH_Socket, OnSocketIncoming);
  186.        
  187.         gAL_Clients = CreateArray();
  188.        
  189.         LogMessage("%s chat-processor. DCR %s be able to send messages.", gB_ChatProcessor ? "Found" : "Couldn\'t find", gB_ChatProcessor ? "will" : "won\'t");
  190.        
  191.         LogMessage("[DCR] Started Server Chat Relay server on port %d", port);
  192.     }
  193. }
  194.  
  195. public void GuildList(DiscordBot bot, char[] id, char[] name, char[] icon, bool owner, int permissions, any data)
  196. {
  197.     gDB_Bot.GetGuildChannels(id, ChannelList, INVALID_FUNCTION);
  198. }
  199.  
  200. public void ChannelList(DiscordBot bot, char[] guild, DiscordChannel Channel, any data)
  201. {
  202.     if(Channel.IsText) {
  203.         char id[32];
  204.         Channel.GetID(id, sizeof(id));
  205.        
  206.         char sChannelID[64];
  207.         gCV_DiscordChatChannel.GetString(sChannelID, sizeof(sChannelID));
  208.        
  209.         if(StrEqual(id, sChannelID) && !gB_ListeningToDiscord)
  210.         {
  211.             gDB_Bot.StopListening();
  212.            
  213.             char name[32];
  214.             Channel.GetName(name, sizeof(name));
  215.             gDB_Bot.StartListeningToChannel(Channel, OnMessage);
  216.            
  217.             LogMessage("[DCR] Started listening to channel %s (%s)", name, id);
  218.             gB_ListeningToDiscord = true;
  219.         }
  220.     }
  221. }
  222.  
  223. public void OnMessage(DiscordBot Bot, DiscordChannel Channel, DiscordMessage message)
  224. {
  225.     if (message.GetAuthor().IsBot())
  226.     return;
  227.    
  228.     char sMessage[2048];
  229.     message.GetContent(sMessage, sizeof(sMessage));
  230.    
  231.     char sAuthor[128];
  232.     message.GetAuthor().GetUsername(sAuthor, sizeof(sAuthor));
  233.    
  234.     Format(sMessage, sizeof(sMessage), "%s %s: %s", gS_DiscordTag, sAuthor, sMessage);
  235.    
  236.     CPrintToChatAll("%s", sMessage);
  237.     //Broadcast(INVALID_HANDLE, sMessage, sizeof(sMessage));
  238. }
  239.  
  240. public Action Hook_ChatMessage(int client, const char[] command, int argc)
  241. {
  242.     if(client<=0)
  243.     {
  244.         //To-do: Server console print?
  245.         return Plugin_Continue;
  246.     }
  247.     if(BaseComm_IsClientGagged(client))
  248.     {
  249.         return Plugin_Continue;
  250.     }
  251.     char full_message[MAX_BUFFER_LENGTH];
  252.     GetCmdArgString(full_message, sizeof(full_message));
  253.     ReplaceString(full_message, sizeof(full_message), "/", "", false);
  254.     ReplaceString(full_message, sizeof(full_message), "\"", "", false);
  255.     if(full_message[0] == '/') // remove chat commands
  256.     {
  257.         char str[64];
  258.         GetCmdArg(1, str, sizeof(str));
  259.         ReplaceString(str, sizeof(str), "/", "", false);
  260.         ReplaceString(str, sizeof(str), "\"", "", false);
  261.         if(CommandExists(str))
  262.         {
  263.             return Plugin_Continue;
  264.         }
  265.     }
  266.    
  267.     char sMessage[MAX_BUFFER_LENGTH];
  268.     char player_tag[MAX_BUFFER_LENGTH];
  269.     char auth_id[MAX_BUFFER_LENGTH];
  270.     if(!GetClientAuthId(client, AuthId_Steam2, auth_id, sizeof(auth_id)))
  271.     {
  272.         strcopy(player_tag, sizeof(player_tag), "CLIENT NOT AUTHENTICATED. STEAM DOWN?");
  273.     }
  274.     else
  275.     {
  276.         h_UserTags.GetString(auth_id, player_tag, sizeof(player_tag));
  277.     }
  278.     Format(sMessage, sizeof(sMessage), "%s%s %N: %s", player_tag, gS_ServerTag, client, full_message);
  279.     //ReplaceString(sMessage, sizeof(sMessage), "\"", "", false);
  280.  
  281.     //Broadcast() is questionnable...
  282.     //Broadcast(INVALID_HANDLE, sMessage, sizeof(sMessage));
  283.    
  284.     SendToDiscord(sMessage ,sizeof(sMessage));
  285.     return Plugin_Continue;
  286. }
  287.  
  288. public void OnMessageSent(DiscordBot bot, char[] channel, DiscordMessage message, any data)
  289. {
  290.     char sMessage[2048];
  291.     message.GetContent(sMessage, sizeof(sMessage));
  292.     LogMessage("[SM] Message sent to discord: \"%s\".", sMessage);
  293. }
  294.  
  295. void GetServerIP(char[] ip, int length)
  296. {
  297.     int hostip = FindConVar("hostip").IntValue;
  298.  
  299.     Format(ip, length, "%d.%d.%d.%d",
  300.     (hostip >> 24 & 0xFF),
  301.     (hostip >> 16 & 0xFF),
  302.     (hostip >> 8 & 0xFF),
  303.     (hostip & 0xFF)
  304.     );
  305. }
  306.  
  307. /*
  308. bool Broadcast(Handle socket, const char[] message, int maxlength)
  309. {
  310.     if(!gCV_SocketEnable.BoolValue)
  311.     return false;
  312.    
  313.     if(gAL_Clients == INVALID_HANDLE)
  314.     {
  315.         LogError("In Broadcast, gAL_Clients was invalid. This should never happen!");
  316.         return false;
  317.     }
  318.    
  319.    
  320.     int size = gAL_Clients.Length;
  321.     Handle dest_socket = INVALID_HANDLE;
  322.    
  323.     for (int i = 0; i < size; i++)
  324.     {
  325.         dest_socket = gAL_Clients.Get(i);
  326.         if (dest_socket != socket) // Prevent sending back to the same server.
  327.         {
  328.             SocketSend(dest_socket, message, maxlength);
  329.         }
  330.     }
  331.    
  332.     if (socket != INVALID_HANDLE) // Prevent printing to the server chat, if message is by the server.
  333.     {
  334.         PrintToChatAll(" %s", message);
  335.     }
  336.     return true;
  337. }
  338. */
  339.  
  340. void CloseSocket()
  341. {
  342.     if(gH_Socket != INVALID_HANDLE)
  343.     {
  344.         CloseHandle(gH_Socket);
  345.         gH_Socket = INVALID_HANDLE;
  346.         LogMessage("Closed local Server Chat Relay socket");
  347.     }
  348.     if(gAL_Clients != INVALID_HANDLE)
  349.     {
  350.         CloseHandle(gAL_Clients);
  351.     }
  352. }
  353.  
  354. void RemoveClient(Handle client)
  355. {
  356.  
  357.     if (gAL_Clients == INVALID_HANDLE)
  358.     {
  359.         LogError("Attempted to remove client while g_clients was invalid. This should never happen!");
  360.         return;
  361.     }
  362.    
  363.     int size = gAL_Clients.Length;
  364.     for (int i = 0; i < size; i++)
  365.     {
  366.         if(gAL_Clients.Get(i) == client)
  367.         {
  368.             gAL_Clients.Erase(i);
  369.             return;
  370.         }
  371.     }
  372.    
  373.     LogError("Could not find client in RemoveClient. This should never happen!");
  374. }
  375.  
  376. public int OnSocketIncoming(Handle socket, Handle newSocket, char[] remoteIP, int remotePort, any arg)
  377. {
  378.     if (gAL_Clients == INVALID_HANDLE) {
  379.         LogError("In OnSocketIncoming, gAL_Clients was invalid. This should never happen!");
  380.     }
  381.     else {
  382.         PushArrayCell(gAL_Clients, newSocket);
  383.     }
  384.  
  385.     SocketSetReceiveCallback(newSocket, OnChildSocketReceive);
  386.     SocketSetDisconnectCallback(newSocket, OnChildSocketDisconnected);
  387.     SocketSetErrorCallback(newSocket, OnChildSocketError);
  388. }
  389.  
  390. public int OnSocketDisconnected(Handle socket, any arg)
  391. {
  392.     CloseSocket();
  393. }
  394.  
  395. public int OnSocketError(Handle socket, const int errorType, const int errorNum, any arg)
  396. {
  397.     LogError("Socket error %d (errno %d)", errorType, errorNum);
  398.     CloseSocket();
  399. }
  400.  
  401. public int OnChildSocketReceive(Handle socket, char[] receiveData, const int dataSize, any arg)
  402. {
  403.     //Broadcast(socket, receiveData, dataSize);
  404.    
  405.     SendToDiscord(receiveData, dataSize);
  406. }
  407.  
  408. public int OnChildSocketDisconnected(Handle socket, any arg) {
  409.     RemoveClient(socket);
  410.     CloseHandle(socket);
  411. }
  412.  
  413. public int OnChildSocketError(Handle socket, const int errorType, const int errorNum, any arg)
  414. {
  415.     LogError("Child socket error %d (errno %d)", errorType, errorNum);
  416.     RemoveClient(socket);
  417.     CloseHandle(socket);
  418. }
  419.  
  420. void SendToDiscord(const char[] message, int maxlength)
  421. {
  422.     char[] sMessage = new char[maxlength];
  423.     FormatEx(sMessage, maxlength, "%s", message);
  424.    
  425.     CRemoveTags(sMessage, maxlength);
  426.    
  427.     char sChannelID[64];
  428.     gCV_DiscordChatChannel.GetString(sChannelID, sizeof(sChannelID));
  429.     gDB_Bot.SendMessageToChannelID(sChannelID, sMessage, OnMessageSent);
  430. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top