SHARE
TWEET

Untitled

a guest Jul 19th, 2019 306 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.     {
  227.         return;
  228.     }
  229.    
  230.     char sMessage[2048];
  231.     message.GetContent(sMessage, sizeof(sMessage));
  232.    
  233.     char sAuthor[128];
  234.     message.GetAuthor().GetUsername(sAuthor, sizeof(sAuthor));
  235.    
  236.     if(sMessage[0]=='!')
  237.     {
  238.         char buffers[32][32];
  239.         ExplodeString(sMessage, " ", buffers, 32, 32);
  240.         PrintToChatAll("Command received: %s", buffers[0]);
  241.         if(StrEqual(buffers[0], "!players", false))
  242.         {
  243.             strcopy(sMessage, sizeof(sMessage), "**Player name  SteamId     UserId      Time connected      Tag**");
  244.             for(int i=1; i<=MaxClients; i++)
  245.             {
  246.                 if(IsClientInGame(i))
  247.                 {
  248.                     char buffer1[64];
  249.                     char authid[64];
  250.                     GetClientName(i, buffer1, sizeof(buffer1));
  251.                     StrCat(sMessage, sizeof(sMessage), "\n");
  252.                     StrCat(sMessage, sizeof(sMessage), buffer1);
  253.                     StrCat(sMessage, sizeof(sMessage), "    ");
  254.                     GetClientAuthId(i, AuthId_Steam3, authid, sizeof(authid));
  255.                     StrCat(sMessage, sizeof(sMessage), authid);
  256.                     StrCat(sMessage, sizeof(sMessage), "    ");
  257.                     IntToString(GetClientUserId(i), buffer1, sizeof(buffer1));
  258.                     StrCat(sMessage, sizeof(sMessage), buffer1);
  259.                     StrCat(sMessage, sizeof(sMessage), "    ");
  260.                     IntToString(RoundFloat(GetClientTime(i)), buffer1, sizeof(buffer1));
  261.                     StrCat(sMessage, sizeof(sMessage), buffer1);
  262.                     StrCat(sMessage, sizeof(sMessage), "    ");
  263.                     h_UserTags.GetString(authid, buffer1, sizeof(buffer1));
  264.                     if(buffer1[0]=='\0')
  265.                     {
  266.                         strcopy(buffer1, sizeof(buffer1), "No Tag");
  267.                     }
  268.                     StrCat(sMessage, sizeof(sMessage), buffer1);
  269.                     SendToDiscord(sMessage, sizeof(sMessage));
  270.                 }
  271.             }
  272.         }
  273.         else if(StrEqual(buffers[0], "!help", false))
  274.         {
  275.             strcopy(sMessage, sizeof(sMessage), "");
  276.             StrCat(sMessage, sizeof(sMessage), "*!help* - Show this help\n");
  277.             StrCat(sMessage, sizeof(sMessage), "*!players* - Show list of players and little more info\n");
  278.             SendToDiscord(sMessage, sizeof(sMessage));
  279.         }
  280.         else
  281.         {
  282.             strcopy(sMessage, sizeof(sMessage), "Unknown command entered. For avaiable commmands, type *!help*");
  283.             SendToDiscord(sMessage, sizeof(sMessage));
  284.         }
  285.         return;
  286.     }
  287.     else
  288.     {
  289.         Format(sMessage, sizeof(sMessage), "%s %s: %s", gS_DiscordTag, sAuthor, sMessage);
  290.         CPrintToChatAll("%s", sMessage);
  291.     }
  292.     //Broadcast(INVALID_HANDLE, sMessage, sizeof(sMessage));
  293. }
  294.  
  295. public Action Hook_ChatMessage(int client, const char[] command, int argc)
  296. {
  297.     if(client<=0)
  298.     {
  299.         //To-do: Server console print?
  300.         return Plugin_Continue;
  301.     }
  302.     if(BaseComm_IsClientGagged(client))
  303.     {
  304.         return Plugin_Continue;
  305.     }
  306.     char full_message[MAX_BUFFER_LENGTH];
  307.     GetCmdArgString(full_message, sizeof(full_message));
  308.     ReplaceString(full_message, sizeof(full_message), "\"", "", false);
  309.     if(full_message[0] == '/') // remove chat commands
  310.     {
  311.         char str[64];
  312.         GetCmdArg(1, str, sizeof(str));
  313.         ReplaceString(str, sizeof(str), "/", "", false);
  314.         ReplaceString(str, sizeof(str), "\"", "", false);
  315.         if(CommandExists(str))
  316.         {
  317.             return Plugin_Continue;
  318.         }
  319.         Format(str, sizeof(str), "sm_%s", str);
  320.         if(CommandExists(str))
  321.         {
  322.             return Plugin_Continue;
  323.         }
  324.     }
  325.    
  326.     char sMessage[MAX_BUFFER_LENGTH];
  327.     char player_tag[MAX_BUFFER_LENGTH];
  328.     char auth_id[MAX_BUFFER_LENGTH];
  329.     if(!GetClientAuthId(client, AuthId_Steam2, auth_id, sizeof(auth_id)))
  330.     {
  331.         strcopy(player_tag, sizeof(player_tag), "CLIENT NOT AUTHENTICATED. STEAM DOWN?");
  332.     }
  333.     else
  334.     {
  335.         h_UserTags.GetString(auth_id, player_tag, sizeof(player_tag));
  336.     }
  337.     Format(sMessage, sizeof(sMessage), "%s%s %N: %s", player_tag, gS_ServerTag, client, full_message);
  338.    
  339.     ReplaceString(sMessage, sizeof(sMessage), "@", "", false);
  340.     SendToDiscord(sMessage ,sizeof(sMessage));
  341.     return Plugin_Continue;
  342. }
  343.  
  344. public void OnClientAuthorized(int client, const char[] auth)
  345. {
  346.     char steamid[64];
  347.     GetClientAuthId(client, AuthId_Steam3, steamid, sizeof(steamid));
  348.     if(StrContains(steamid, "bot", false)>-1)
  349.     {
  350.         return;
  351.     }
  352.    
  353.     char sMessage[MAX_BUFFER_LENGTH];
  354.     Format(sMessage, sizeof(sMessage), "**Client %N connected (Steam ID: %s)**", client, steamid);
  355.     ReplaceString(sMessage, sizeof(sMessage), "@", "", false);
  356.     SendToDiscord(sMessage ,sizeof(sMessage));
  357. }
  358.  
  359. public void OnClientDisconnect(int client)
  360. {
  361.     char steamid[64];
  362.     GetClientAuthId(client, AuthId_Steam3, steamid, sizeof(steamid));
  363.     if(StrContains(steamid, "bot", false)>-1)
  364.     {
  365.         return;
  366.     }
  367.    
  368.     char sMessage[MAX_BUFFER_LENGTH];
  369.     Format(sMessage, sizeof(sMessage), "**Client %N disconnected (Steam ID: %s)**", client, steamid);
  370.     ReplaceString(sMessage, sizeof(sMessage), "@", "", false);
  371.     SendToDiscord(sMessage ,sizeof(sMessage));
  372. }
  373.  
  374. public void OnMessageSent(DiscordBot bot, char[] channel, DiscordMessage message, any data)
  375. {
  376.     char sMessage[2048];
  377.     message.GetContent(sMessage, sizeof(sMessage));
  378.     LogMessage("[SM] Message sent to discord: \"%s\".", sMessage);
  379. }
  380.  
  381. void GetServerIP(char[] ip, int length)
  382. {
  383.     int hostip = FindConVar("hostip").IntValue;
  384.  
  385.     Format(ip, length, "%d.%d.%d.%d",
  386.     (hostip >> 24 & 0xFF),
  387.     (hostip >> 16 & 0xFF),
  388.     (hostip >> 8 & 0xFF),
  389.     (hostip & 0xFF)
  390.     );
  391. }
  392.  
  393. void CloseSocket()
  394. {
  395.     if(gH_Socket != INVALID_HANDLE)
  396.     {
  397.         CloseHandle(gH_Socket);
  398.         gH_Socket = INVALID_HANDLE;
  399.         LogMessage("Closed local Server Chat Relay socket");
  400.     }
  401.     if(gAL_Clients != INVALID_HANDLE)
  402.     {
  403.         CloseHandle(gAL_Clients);
  404.     }
  405. }
  406.  
  407. void RemoveClient(Handle client)
  408. {
  409.  
  410.     if (gAL_Clients == INVALID_HANDLE)
  411.     {
  412.         LogError("Attempted to remove client while g_clients was invalid. This should never happen!");
  413.         return;
  414.     }
  415.    
  416.     int size = gAL_Clients.Length;
  417.     for (int i = 0; i < size; i++)
  418.     {
  419.         if(gAL_Clients.Get(i) == client)
  420.         {
  421.             gAL_Clients.Erase(i);
  422.             return;
  423.         }
  424.     }
  425.    
  426.     LogError("Could not find client in RemoveClient. This should never happen!");
  427. }
  428.  
  429. public int OnSocketIncoming(Handle socket, Handle newSocket, char[] remoteIP, int remotePort, any arg)
  430. {
  431.     if (gAL_Clients == INVALID_HANDLE) {
  432.         LogError("In OnSocketIncoming, gAL_Clients was invalid. This should never happen!");
  433.     }
  434.     else {
  435.         PushArrayCell(gAL_Clients, newSocket);
  436.     }
  437.  
  438.     SocketSetReceiveCallback(newSocket, OnChildSocketReceive);
  439.     SocketSetDisconnectCallback(newSocket, OnChildSocketDisconnected);
  440.     SocketSetErrorCallback(newSocket, OnChildSocketError);
  441. }
  442.  
  443. public int OnSocketDisconnected(Handle socket, any arg)
  444. {
  445.     CloseSocket();
  446. }
  447.  
  448. public int OnSocketError(Handle socket, const int errorType, const int errorNum, any arg)
  449. {
  450.     LogError("Socket error %d (errno %d)", errorType, errorNum);
  451.     CloseSocket();
  452. }
  453.  
  454. public int OnChildSocketReceive(Handle socket, char[] receiveData, const int dataSize, any arg)
  455. {
  456.     //Broadcast(socket, receiveData, dataSize);
  457.    
  458.     SendToDiscord(receiveData, dataSize);
  459. }
  460.  
  461. public int OnChildSocketDisconnected(Handle socket, any arg) {
  462.     RemoveClient(socket);
  463.     CloseHandle(socket);
  464. }
  465.  
  466. public int OnChildSocketError(Handle socket, const int errorType, const int errorNum, any arg)
  467. {
  468.     LogError("Child socket error %d (errno %d)", errorType, errorNum);
  469.     RemoveClient(socket);
  470.     CloseHandle(socket);
  471. }
  472.  
  473. void SendToDiscord(const char[] message, int maxlength)
  474. {
  475.     char[] sMessage = new char[maxlength];
  476.     FormatEx(sMessage, maxlength, "%s", message);
  477.    
  478.     CRemoveTags(sMessage, maxlength);
  479.    
  480.     char sChannelID[64];
  481.     gCV_DiscordChatChannel.GetString(sChannelID, sizeof(sChannelID));
  482.     gDB_Bot.SendMessageToChannelID(sChannelID, sMessage, OnMessageSent);
  483. }
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