sapphonie / StAC-tf2

steph's anticheat (StAC). a built-from-scratch sourcemod based solution to cheating in Team Fortress 2.
https://sappho.io
GNU General Public License v3.0
120 stars 23 forks source link

Use inc for Discord JSON and add translations #57

Closed sapphonie closed 2 years ago

sapphonie commented 3 years ago

https://github.com/Cruze03/discord-utilities

sapphonie commented 3 years ago

https://github.com/clugg/sm-json

MAGNAT2645 commented 3 years ago

Discord-Utilities uses smjansson extension so you shouldn't use sm-json in this case.

MAGNAT2645 commented 3 years ago

But you can use sm-json (or smjansson) to create object then encode it to string.

sapphonie commented 3 years ago

Ill be using sm-json as I don't want to include another ext

MAGNAT2645 commented 3 years ago

I think you can create object only once (via static) and if it is null then put basic information. After that you can change existing keys (name, value etc.) with every function call.

MAGNAT2645 commented 3 years ago

Here's a snippet (haven't tested):

#define _INT(%0) view_as<int>( %0 )

enum StacDetectionNotifyFields {
    StacDetectionNotify_Name = 0,
    StacDetectionNotify_SteamID,
    StacDetectionNotify_Type,
    StacDetectionNotify_Count,
    StacDetectionNotify_HostName,
    StacDetectionNotify_HostIP,
    StacDetectionNotify_Demo,
    StacDetectionNotify_TimeStamp
};

void StacDetectionDiscordNotify(int userid, char[] type, int detections) {
    // ...

    SetGlobalTransTarget( LANG_SERVER );

    static JSON_Object hRoot = null;
    static JSON_Array hFields = null;
    {
        static JSON_Object hEmbedsContent = null;

        if ( hRoot == null && hEmbedsContent == null && hFields == null ) {
            hRoot = new JSON_Object(); // {  }

            JSON_Array hEmbeds = new JSON_Array();
            hRoot.SetObject( "embeds", hEmbeds ); // { "embeds": [  ] }

            hEmbedsContent = new JSON_Object();
            hEmbedsContent.SetInt( "color", 0xFF69B4 );
            hEmbeds.PushObject( hEmbedsContent ); // { "embeds": [ { "color": 0xFF69B4 } ] }

            hFields = new JSON_Array();
            hEmbedsContent.SetObject( "fields", hFields ); // { "embeds": [ { "color": 0xFF69B4, "fields": [  ] } ] }

            for ( int i = _INT( StacDetectionNotify_Name ); i < _INT( StacDetectionNotifyFields ); i++ )
                hFields.PushObject( new JSON_Object() );
        }

        FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_detection_title" );
        hEmbedsContent.SetString( "title", szBuffer );
    }

    JSON_Object hField;
    for ( int i = _INT( StacDetectionNotify_Name ); i < _INT( StacDetectionNotifyFields ); i++ ) {
        hField = hFields.GetObject( i );

        switch ( i ) {
            case StacDetectionNotify_Name: {
                FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_player_field" );

                char szName[MAX_NAME_LENGTH];
                GetClientName( Cl, szName, sizeof szName );
                hField.SetString( "value", szName );
            }
            case StacDetectionNotify_SteamID: {
                strcopy( szBuffer, sizeof szBuffer, "SteamID" );
                hField.SetString( "value", steamid );
            }
            case StacDetectionNotify_Type: {
                FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_detection_type_field" );
                hField.SetString( "value", type );
            }
            case StacDetectionNotify_Count: {
                FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_detection_count_field" );

                char szValue[12];
                IntToString( detections, szValue, sizeof szValue );
                hField.SetString( "value", szValue );
            }
            case StacDetectionNotify_HostName: {
                FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_hostname_field" );
                hField.SetString( "value", hostname );
            }
            case StacDetectionNotify_HostIP: {
                FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_hostip_field" );
                hField.SetString( "value", hostipandport );
            }
            case StacDetectionNotify_Demo: {
                FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_demo_field" );
                hField.SetString( "value", demoname );
            }
            case StacDetectionNotify_TimeStamp: {
                FormatEx( szBuffer, sizeof szBuffer, "%t", "discord_unix_timestamp_field" );

                char szValue[12];
                IntToString( GetTime(), szValue, sizeof szValue );
                hField.SetString( "value", szValue );
            }
        }

        hField.SetString( "name", szBuffer );
    }

    char szMessage[2048];
    hRoot.Encode( szMessage, sizeof szMessage );

    SendMessageToDiscord( szMessage );
}

But i think it is easier to use MessageEmbed from Discord-Utilities (requires smjansson extension).

sapphonie commented 3 years ago

ugh this sucks, not because your coding is bad, just because it's going to be a huge pain in the ass

MAGNAT2645 commented 3 years ago

I know, the snippet isn't perfect but this is how you can do it using sm-json.

MAGNAT2645 commented 3 years ago

If you would use smjansson and discord-utilities, you could make them optional so whole Discord feature would be optional for StAC.

MAGNAT2645 commented 3 years ago

Here's another snippet (again, didn't test):

methodmap MessageEmbed < JSON_Object {
    public MessageEmbed(const char[] title = "", int color = 0xFFFFFF) {
        JSON_Object hRoot = new JSON_Object(); // { }

        JSON_Array hEmbeds = new JSON_Array();
        hRoot.SetObject( "embeds", hEmbeds ); // { "embeds": [ ] }

        JSON_Object hEmbedsContent = new JSON_Object();
        hEmbedsContent.SetString( "title", title );
        hEmbedsContent.SetInt( "color", color );
        hEmbeds.PushObject( hEmbedsContent ); // { "embeds": [ { "title": title, "color": color } ] }
        hRoot.SetObject( "_embeds", hEmbedsContent ); // Shortcut
        hRoot.SetKeyHidden( "_embeds", true ); // hide from JSON_Object.Encode()

        JSON_Array hFields = new JSON_Array();
        hEmbedsContent.SetObject( "fields", hFields ); // { "embeds": [ { "title": title, "color": color, "fields": [ ] } ] }
        hRoot.SetObject( "_fields", hFields ); // Shortcut to fields array
        hRoot.SetKeyHidden( "_fields", true ); // hide from JSON_Object.Encode()

        return view_as<MessageEmbed>( hRoot );
    }

    property JSON_Array Fields {
        public get() { return this.GetObject( "_fields" ); }
    }

    property JSON_Object EmbedsContent {
        public get() { return this.GetObject( "_embeds" ); }
    }

    property int Color {
        public get() { return this.EmbedsContent.GetInt( "color" ); }
        public set(int color) { this.EmbedsContent.SetInt( "color", color ); }
    }

    public int GetTitle(char[] buffer, int maxlength) {
        int iBytes;
        this.EmbedsContent.GetString( "title", buffer, maxlength, iBytes );
        return iBytes;
    }
    public bool SetTitle(const char[] title) {
        if ( strlen( title ) > 256 ) return false; // Discord Limit
        return this.EmbedsContent.SetString( "title", title );
    }

    public int AddField(const char[] name, const char[] value) {
        JSON_Array hFields = this.Fields;
        if ( hFields.Length == 25 ) return -1; // Discord Limit
        if ( strlen( name ) > 256 || strlen( value ) > 1024 ) return -1; // Discord Limits

        JSON_Object hField = new JSON_Object();
        hField.SetString( "name", name );
        hField.SetString( "value", value );

        return hFields.PushObject( hField );
    }
    public int AddFieldEx(const char[] name, const char[] value, any ...) {
        char szBuffer[1024]; // Discord Limit
        VFormat( szBuffer, sizeof szBuffer, value, 4 );
        return this.AddField( name, szBuffer );
    }

    public bool RemoveField(int index) {
        JSON_Array hFields = this.Fields;
        hFields.GetObject( index ).Close();
        return hFields.Remove( index );
    }
};

Might be useful (or not).

Usage:

void SendMessageToDiscord(MessageEmbed message) {
    char szMessage[2048];
    message.Encode( szMessage, sizeof szMessage );
    Discord_SendMessage( "stac", szMessage );
}

MessageEmbed hEmbed = new MessageEmbed( "StAC Detection!", 0xFF69B4 );
hEmbed.AddFieldEx( "Player", "%N", Cl );
hEmbed.AddField( "SteamID", steamid );
hEmbed.AddField( "Detection type", type );
hEmbed.AddFieldEx( "Detections", "%i", detections );
hEmbed.AddField( "Hostname", hostname );
hEmbed.AddField( "Host IP", hostipandport );
hEmbed.AddField( "Current Demo Recording", demoname );
hEmbed.AddFieldEx( "Unix timestamp of detection", "%i", GetTime() );

SendMessageToDiscord( hEmbed );
json_cleanup_and_delete( hEmbed );
MAGNAT2645 commented 3 years ago

Good thing, there's a new Discord API which uses sm-json.

sapphonie commented 2 years ago

all these incs suck. i am okay with the current method.