Discord Sync - A very simple plugin

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

Previous topic - Next topic

habi

Introduction
This is a plugin used to get discord text messages. It can also send texts-
SendMessage("VCMP Server is online");

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 as a member to your Discord Server

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/main.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:
!say can you see me?


The messages send in discord are received by vcmp server:



Downloads
Click any of the below buttons to download:
  (updated)   
The last item Windows XP build uses builtin-openssl(statically linked) instead of native schannel of windows.

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
   
The plugin does not depend on squirrel. A Cpp server(script coded in cplus plus and compiled to dll, which is put in 'plugins' directory) is using discord above

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

Roystang

any idea why this happens?

linux x64 plugin

habi

No, it means discord has send a CLOSE event.

The server_log.txt must contain more information.

Please open server_log.txt and post the relevant messages.

In that file,
[DiscordSync] Resume URL:
[DiscordSync] Session id:
means it first connected and then disconnected.

Did you give MESSAGE CONTENT INTENT explained in step 4 of first post in this topic.?

Roystang

Quote from: habi on Nov 12, 2023, 06:56 AM-

i forgot to mention windows plugin works fine with the same script.

for some reasons server_log.txt is not logging the console content, however i took a screenshot that might help,



(these are emotes present in the discord server btw)

and yes i did the step 4 as mentioned and it works fine with windows server

habi

#9
Quote from: Roystang on Nov 12, 2023, 09:23 AM..
I understand the windows plugin works fine.  I see you are also getting a 'Session ID'. 

To debug the issue, i have finished a program to get more information about the bug.

Download this linux console program (it is discordsync scratch) and run it. console
chmod 777 console
./console your_bot_token

what do you see. Can you see "My ID is 98776082681339..", "READY", "GUILD_CREATE" events? Do your console get terminated automatically? It should stay for success.

To compare with, windows version: console.exe (might need vcruntime140.dll, msvcp140.dll, vcruntime140_1.dll)

Pun1sh3r

Quote from: Roystang on Nov 11, 2023, 06:10 PMany idea why this happens?

linux x64 plugin

Got the same Error, Windows works fine but Linux not, I get also no Information in Server Log about the Plugin

habi

#11
Quote from: Pun1sh3r on Nov 16, 2023, 11:30 AMGot the same Error, Windows works fine but Linux not, I get also no Information in Server Log about the Plugin

Could you try this console program which connect to discord and post the results
download

Pun1sh3r

Quote from: habi on Nov 18, 2023, 03:29 AM
Quote from: Pun1sh3r on Nov 16, 2023, 11:30 AMGot the same Error, Windows works fine but Linux not, I get also no Information in Server Log about the Plugin

Could you try this console program which connect to discord and post the results
download


"t": "READY"
}
My ID is 47821648158326XXXX doesnt terminate and runs

habi

Thanks for testing it out. Now, it will be easier for me to find out the bug. I will post the solution once it is found.

habi

#14
@Pun1sh3r, i made a debug version of plugin( discordsync04rel64so ). It will print all messages send and received. Could you try this and post me the results.
If there is secret token in output, you may remove cut/hide that part.

debug version - here

(i was bit lazy last week, also my computer got some problems)