Discord Sync - A very simple plugin

Started by habi, Sep 13, 2023, 04:44 PM

Previous topic - Next topic

habi

Introduction
I have made this plugin in request of a forum member. Then lot of searching and learning led me to develop this plugin called DiscordSync. It is made following the websocket protocol of discord gateway.

Configuration


In server.cfg, you add token and channel.

Creating a bot and getting token

1. Head to https://discord.com/developers/applications.


2. Click on New Application


3. Select Bot on left panel.


4. Scroll down to MESSAGE CONTENT INTENT


5. Click on Save Changes


6. After Saving changes, scroll down and select permissions:
  • Read Messages/View Channels
  • Send Messages


7. Now at last, scroll up and Click on RESET TOKEN

Click on Yes, do it

Atlast, copy the token

This is the token you should provide in server.cfg mentioned on top

channel
Below you can see what is your channel id. We do not need Server ID.

This is the channel you should provide in server.cfg mentioned on top

Adding bot to your channel

1. Go to General Information and copy the Application ID:

2. Open a new tab and go to https://discordapp.com/api/oauth2/authorize?client_id=<YOUR_APPLICATION_ID>&permissions=0&scope=bot

3. Select your Server from dropdown list and click on Authorize on bottom.
4. Now, you can see the bot in your channel as offline.

Functions of DiscordSync
  • SendMessage( [string] message )

Events/Callbacks
  • onDiscordMessage( [string]nick, [string]message )
  • onDiscordCommand( [string]nick, [string]message )

Example
#file: scripts/mmain.nut
//Part 1 - In Game Events
function onScriptLoad()
{
    print("VCMP 0.4 Server (rel006) Loaded");
}
function onPlayerJoin(player)
{
    //This will send message to discord - 'SendMessage'
    SendMessage("```\\n"+player.Name+" has joined the server\\n```");
}
function onPlayerPart(player, reason)
{
    SendMessage("```\\n"+player.Name+" has left the server ("+GetReason(reason)+")\\n```");
}
function onPlayerChat(player, text)
{
    SendMessage(player.Name+": "+text);
        return 1;
}
function onPlayerDeath(player,reason)
{
    local reasontxt=GetDeathReason(player, reason);
    SendMessage(format("```\\n%s\\n```",reasontxt));
}
function onPlayerKill( killer, player, reason, bodypart )
{
    SendMessage( killer.Name + " killed " + player.Name + " `" + GetWeaponName( reason ) + "` " + GetBodyPart(bodypart) + "" );   
}
function onPlayerTeamKill( killer, player, reason, bodypart )
{
    SendMessage( killer.Name + " team killed " + player.Name + " `" + GetWeaponName( reason ) + "` " + GetBodyPart(bodypart) + "" );   
}
function onPlayerSpawn( player )
{
    SendMessage(player.Name+" has spawned.");
}
function onPlayerCrashDump( player, CrashReport )
{
    SendMessage(player.Name+" crash dumped.");
}

//Part 2 - Discord Events
function onDiscordCommand(username, cmd, text ) //Called when using / or !. text="" if empty
{
    switch(cmd)
    {
        case "echo":SendMessage(text);break;
        case "hostname": SendMessage(GetServerName());break;
        case "gamemode": SendMessage(GetGameModeName());break;
        case "say": if(text!=""){
                    local msg=format("[#ffffff]%s (web): [#ffff00]%s", username, text);
                    ClientMessageToAll(msg,255,255,255);
                    print(format("\x1b[1K\r\x1b[1;33m%s (web): \x1b[37m%s\x1b[0m",username,text));
                    }else SendMessage("Usage: !say text");
                    break;
        case "players":  local plr, names="",count=0;
            for(local i=0;i<GetMaxPlayers();i++)
            {
                plr=FindPlayer(i);
                if(plr)
                {
                    names+=format("%s[%d] %s",count?"\\n":"",i,plr.Name);
                    count++;
                }
            }
            if(!count)
                SendMessage("No players in server");
            else
            {
                //See new line added
                SendMessage(format("Total players: %d.\\n%s",count, names));
            }
            break;
        case "gravity": SendMessage("```fix\\nGravity: "+GetGravity()+"\\n```");break;
        case "time": SendMessage("The current game time is "+format("%02d:%02d",GetHour(),GetMinute()));break;
        case "weather":
            local weather = GetWeather();

            switch (weather) {
                case 0:
                    weather = "Mostly clear skies";
                    break;
                case 1:
                    weather = "Overcast";
                    break;
                case 2:
                    weather = "Rainy-lightning";
                    break;
                case 3:
                    weather = "Foggy";
                    break;
                case 4:
                    weather = "Clear skies";
                    break;
                case 5:
                    weather = "Rainy";
                    break;
                case 6:
                    weather = "Dark sky partly cloudy";
                    break;
                case 7:
                    weather = "Light sky partly cloudy";
                    break;
                case 8:
                    weather = "Overcast partly cloudy";
                    break;
                case 9:
                    weather = "Grey sky black clouds";
                    break;
                default:
                    weather = "Unknown";
                    break;
            }

            SendMessage("Current weather: " + weather);
        break;
        case "cmds":
        case "help":
        case "cmd":
        SendMessage("Available cmds:\\n"+
"`echo say hostname gamemode players gravity time weather cmds`\\n"+
"Use / or ! as prefix.");break;
    }
}

//Chat messages in channel
function onDiscordMessage(username, text)
{
    print("\x1b[1K\r\x1b[1;33m"+username+":\x1b[1;37m "+text+"\x1b[0m");
}
//useful functions

//Credits: SLC https://forum.vc-mp.org/index.php?topic=400.msg2563
function GetBodyPart(bpid)
{
 switch(bpid)
 {
        case BODYPART_BODY:    return "Body";
        case BODYPART_TORSO:    return "Torso";
        case BODYPART_LEFTARM:  return "Left Arm";
        case BODYPART_RIGHTARM: return "Right Arm";
        case BODYPART_LEFTLEG:  return "Left Leg";
        case BODYPART_RIGHTLEG: return "Right Leg";
        case BODYPART_HEAD:    return "Head";
        default:                return "Unknown";
  }
}
function GetReason(reason)
{
    switch(reason)
    {
        case 1: return "quit";
        case 2: return "kicked";
        case 3: return "crashed";
        case 4: return "anticheat";
        case 0:
        default: return "timeout";
    }
}
function GetDeathReason(player,reason)
{
    switch(reason)
    {
        case WEP_FALL: return player.Name+" fell to death.";
        case WEP_DROWNED: return player.Name+" drowned.";
        case WEP_VEHICLE: return player.Name+" died in car.";
        case WEP_SUICIDE: return player.Name+" suicided.";
        case 41: return player.Name+" exploded.";
        default: return player.Name+" died.";
    }
}

Screenshots


The result of !say command from discord:




Downloads
Click any of three buttons to download:
     
Note: Windows XP not supported because of old ws2_32.

License
This plugin is open-sourced. See LICENSE file in downloads.

Source code
The source-code can be downloaded:

(Size 6 MB approx, because of static libraries inside).




Squirrel ServerC++ Server
   

More Info on C++ Server
In order to show that this discord plugin can also be used in non-squirrel servers, i made an example of c++ server using it. In the screenshot you can see it as Loaded plugin: hello32 apart from discordsync04rel32.
It's source and compile instructions can be downloaded below:

It shows !say command in game( the green one in above picture). It also send ingame /say command to discord (pink one).



Plugin Commands (Reference)
The plugin both give and respond to certain plugin commands:

Sl NoNameIdentifier          Identifier(In decimal)MessageIn/OutDetails
1CMD_DISCONNECT0x3B456AB3994405043InDisconnects the bot from discord gateway.
2CMD_RECONNECT0x3B456AB4994405044"" OR "RESUME"InDisconnects and reconnect. If message="RESUME", then it will Resume instead of restarting new session.
3CMD_LOGMSGEX0x3B456AB5994405045""InLogs message into the server_log.txt without printing to screen. It uses VT sequences to disable console printing.
4CMD_SHOWUPTIME0x3B456AB6994405046""InPrints how much time the bot's current session is up.
5CMD_RESUME0x3B456AB7994405047""InIf the bot is connected, it will disconnect and resume the session again.
6CMD_STATUS0x3B456AB8994405048""InPrints to console "Connected" or "Not Connected" which is the status of bot
7CMD_CHANNEL0x3B456AB9994405049ChannelIDInChange channel
8CMD_TOKEN0x3B456ABA994405050tokenInChange bot token
9CMD_ONMESSAGE0x3B456ABB994405051nick:cmd txtOutWhen users send messages starting with '/' or '!'. Not sent by default unless CMD_SUBSCRIBE is received.
10CMD_SUBSCRIBE0x3B456ABC994405052""InTo activate CMD_ONMESSAGE and CMD_ONMESSAGE2.
11CMD_UNSUBSCRIBE0x3B456ABD994405053""InTo deactivate effects of CMD_SUBSCRIBE
12CMD_SENDMSG0x3B456ABE994405054msgInSends a message to the channel as chat
13CMD_ONCONNECT0x3B456ABF994405055""OutSends when connected and "READY" signal received from discord gateway
14CMD_ON_DISCONNECT0x3B456AC0994405056""OutWhen connection is closed permanently
15CMD_VERBOSE0x3B456AC1994405057"" or "off"InTo show some reconnection messages if any on screen. By default, they are hidden.
16CMD_ONMESSAGE20x3B456AC2994405058nick:txtOutWhen the user chats normally without '/' or '!'


Interacting RCON tool (which has function to send plgncmd) with VCMP Server. You can download the tool and its plugin here

H.a.S.a.N

Wow bro Great plugin at VC:MP
Amazing and better
Not like others plugin for discord out date

Bro keep going your works done!!
Good luck!

habi

Thank you for your kind words. I'm glad to see you're enjoying the plugin. Happy Gaming.

Xann^

Hey there habi! great job out there!
Suggestion: You should try putting the source code and stuff on github aswell.
Yo there.

habi

#4
It is already there: GitHub

Anybody having discord connection problem check you have given Message Content Intent permission. This is shown on step 4 of  first post of this topic(Creating a bot and getting token).

habi

1.0 (a)
Fixed one bug of bot not connecting even if with proper token, channel and permissions.
Thanks to Xann
download links in first post updated