Chatlog - Discord Bot

umutsen19

Member
Joined
Jul 31, 2015
Messages
7
Reaction score
0
Hello pals,

Is it possible to do this? If yes, how? I'll be explaining step by step below.

-Join a SA-MP server using raksamp.
-Connect the chatlog.txt file with a Discord bot.
-Let the Discord bot scan for the updation of chatlog.txt as often as possible.
-Make the Discord bot search for any word, "ADMIN" for an example.
-Make the Discord bot take the full line that contains the word it looks for, "ADMIN" is the word in this example.
-Make the Discord bot copy that line, and post it into the channel with the tag "@here/@everyone".

The point of this is having a notification on Discord when the word "ADMIN" appears in the chat. It would be much more helpful if you'd release the source code.

Please if you know that if this is possible or impossible, give a reply here about which one is it so I'll not waste my time on either trying or waiting for someone to do it.
 

ini

Well-known member
Joined
Sep 28, 2015
Messages
321
Reaction score
115
well its possible why chatlog.txt when u can read chat directly using raknet lol, and the discord part u can use node.js 4 example
 

umutsen19

Member
Joined
Jul 31, 2015
Messages
7
Reaction score
0
ini said:
well its possible why chatlog.txt when u can read chat directly using raknet lol, and the discord part u can use node.js 4 example

Well, the main purpose of this is leaving my system turned ON 7/24 and let the people in my Discord (tag them if they are busy with something else) channel read the messages in chatlog. The messages I'll let the bot read are quite important, so they will know when they are needed in-game without my call but a Discord bot's @here message.
 

monday

Expert
Joined
Jun 23, 2014
Messages
1,127
Solutions
1
Reaction score
158
hi, I never used RakSAMP but from what I see it would be necessary to modify its source code...

in "netrpc.cpp" file there's a "ClientMessage(RPCParameters *rpcParams)" which has :

Code:
void ClientMessage(RPCParameters *rpcParams)
{
	//if(!iGameInited) return;

	PCHAR Data = reinterpret_cast<PCHAR>(rpcParams->input);
	int iBitLength = rpcParams->numberOfBitsOfData;

	RakNet::BitStream bsData((unsigned char *)Data,(iBitLength/8)+1,false);
	DWORD dwStrLen, dwColor;
	char szMsg[257];
	memset(szMsg, 0, 257);

	bsData.Read(dwColor);
	bsData.Read(dwStrLen);
	if(dwStrLen > 256) return;

	bsData.Read(szMsg, dwStrLen);
	szMsg[dwStrLen] = 0;

// use szMsg here

	if(settings.iFind)
	{
		for(int i = 0; i < MAX_FIND_ITEMS; i++)
		{
			if(!settings.findItems[i].iExists)
				continue;

			if(strstr(szMsg, settings.findItems[i].szFind))
				if(settings.findItems[i].szSay[0] != 0x00)
					sendChat(settings.findItems[i].szSay);
		}
	}

	char szNonColorEmbeddedMsg[257];
	int iNonColorEmbeddedMsgLen = 0;

	for (size_t pos = 0; pos < strlen(szMsg) && szMsg[pos] != '\0'; pos++)
	{
		if (!((*(unsigned char*)(&szMsg[pos]) - 32) >= 0 && (*(unsigned char*)(&szMsg[pos]) - 32) < 224))
			continue;

		if(pos+7 < strlen(szMsg))
		{
			if (szMsg[pos] == '{' && szMsg[pos+7] == '}')
			{
				pos += 7;
				continue;
			}
		}

		szNonColorEmbeddedMsg[iNonColorEmbeddedMsgLen] = szMsg[pos];
		iNonColorEmbeddedMsgLen++;
	}

	szNonColorEmbeddedMsg[iNonColorEmbeddedMsgLen] = 0;

	Log("[CMSG] %s", szNonColorEmbeddedMsg);
}

Probably the best way would be to use this:
https://github.com/yourWaifu/sleepy-discord
And itegrate it into the RakSamp, but it might be difficult...

Another way would be to just modify the ClientMessage function to send HTTP request to its own machine (127.0.0.1) and use python to:
-locally host http server
-use https://github.com/Rapptz/discord.py to post a message
(both would have to be separate threads and use "queue" to pass the received message)
 

monday

Expert
Joined
Jun 23, 2014
Messages
1,127
Solutions
1
Reaction score
158
[img=780x600]https://i.imgur.com/W4vn5WX.png[/img]

it acutally works xD

that's the modified netrpc.cpp file
https://pastebin.com/NkWuq7t7

I used visual studio 2017 to open the RakSAMPClient project, it required me to adapt it somehow (just press "ok" or something to automatically do that once you open the project), then I had to right-click on the "Solution RakSAMPClient_2008" (int the Solution Explorer on the left side) and click "Retarget solution", it compiled well then without the need to change any settings or link libraries etc.


that's python code for discord server + receiving data from http request
Code:
from bottle import route, run # server to receive data

import discord
import asyncio

from queue import Queue
import threading
import re


q = Queue()


@route('<mypath:path>')
def server_callback(mypath):
    q.put(mypath)
    return "OK"

def server_thread():
    run(host='localhost', port=7891)


client = discord.Client()
async def my_background_task():
    await client.wait_until_ready()
    channel = discord.Object(id='480410810397622274')
    while not client.is_closed:
        msg = q.get(block=True)
        await client.send_message(channel, msg)
        #await asyncio.sleep(60) # task runs every second
        
@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')


if __name__ == "__main__":
    server_thread = threading.Thread(target=server_thread)
    server_thread.daemon = True
    server_thread.start()

    

    client.loop.create_task(my_background_task())
    client.run('NDgasdODU4MTAxMjU4.dsfsdfds.K782Qj-xmtm5vcIRMG6sadVjZjo')
I used python 3 version, it also requires "bottle" and "discord" libraries. If you have python installed (and added to path my ticking box during installation) then you can just go to your command prompt and use the following commands:
py -3 -m pip install -U discord.py
py -3 -m pip install bottle

Here's some updated python and netrpc.cpp code if anyone was going to play with it (it's just more comfortable for testing, also python code is not blocking other discord functionality anymore)

netrpc.cpp  - https://pastebin.com/ACr0sPCe

Code:
from bottle import route, run # server to receive data

import discord, asyncio
from discord.ext import commands

from queue import Queue # for safe communication between threads
import threading


import logging
logging.basicConfig(level=logging.DEBUG)

'''
logger = logging.getLogger('discord')
logger.setLevel(logging.INFO)
handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
logger.addHandler(handler)
'''

# 2 lines below have to be changed if you'd like to use this code yourself:
channel_id = '48041251525124'
discord_bot_token = 'NDgwNDA5NzQ1OD'

server_port = 7891

q = Queue()

@route('<mypath:path>')
def server_callback(mypath):
    #print("server_callback -",datetime.datetime.time(datetime.datetime.now()))
    q.put(mypath)
    return "OK"

def server_thread():
    run(host='localhost', port=server_port, debug=True)


def FilterMessage(msg): # function that intakes received request/message and returns what will be posted on discord
    msg = msg[1:] # get rid of "/"
    if msg.startswith("[CMSG]"):
        #return msg
        if "Your turf is being taken over!!!" in msg[6:]: # if that phrase is within message (safe in cases where space is added after/before), there could be check if the message is equal to that phrase though (using if msg[6:] == "Your turf is being taken over!!!")
            return "IN GAME INFO: Our turf is taken over :("
    elif msg.startswith("[CHAT]"):
        pass # do nothing with chat messages received from players
    return        

client = discord.Client()

import datetime

async def my_background_task():
    await client.wait_until_ready()
    channel = discord.Object(id=channel_id)
    while not client.is_closed:
        try:    
            msg = FilterMessage(q.get(False))
        except:
            pass
        else:
            if msg:
                await client.send_message(channel, msg)
        finally:
            await asyncio.sleep(0.1)
        
@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

'''
# example of additional functionality (used for testing, to make sure that it's not being blocked)
@client.event
async def on_message(message):
    import random
    # we do not want the bot to reply to itself
    if message.author == client.user:
        return

    if message.content.startswith('$guess'):
        await client.send_message(message.channel, 'Guess a number between 1 to 10')

        def guess_check(m):
            return m.content.isdigit()

        guess = await client.wait_for_message(timeout=5.0, author=message.author, check=guess_check)
        answer = random.randint(1, 10)
        if guess is None:
            fmt = 'Sorry, you took too long. It was {}.'
            await client.send_message(message.channel, fmt.format(answer))
            return
        if int(guess.content) == answer:
            await client.send_message(message.channel, 'You are right!')
        else:
            await client.send_message(message.channel, 'Sorry. It is actually {}.'.format(answer))
'''

if __name__ == "__main__":
    server_thread = threading.Thread(target=server_thread)
    server_thread.daemon = True
    server_thread.start()

    client.loop.create_task(my_background_task())
    client.run(discord_bot_token)

"FilterMessage" function is where the main check for message content is being done and it is determined there what will be posted on discord
 

Ezel

Active member
Joined
Dec 6, 2017
Messages
134
Reaction score
18
Location
Syria
as always, our superhero come to help :iknowwhatyoudidthere:
 

umutsen19

Member
Joined
Jul 31, 2015
Messages
7
Reaction score
0
I will be trying this out tomorrow, and give you a feedback. Thank you for taking your time and giving a reply here.
 

0x32789

Expert
Joined
May 26, 2014
Messages
849
Reaction score
52
Location
LongForgotten <-> 0x32789
found one more library, works for auto hot key and is portable af. just tested it works.
Code:
#NoEnv
SetBatchLines, -1

#Include %A_LineFile%\..\Discord.ahk

new DiscordBot("bot token here")
return


class DiscordBot extends Discord
{
	; Called by the JS on WS open
	OnOpen(Event)
	{
		this.SendMessage("channelid, can be string or int both work", "you are gay af")
	}
	
	; Called by the JS on WS message
	OnMessage(Event)
	{
		
	}
}
Use with samp udfex or whatever and listen for messages easy and shit.
https://github.com/G33kDude/Discord.ahk
Only thing here is that it will not be a bot but the active player itself ehhh.
 

umutsen19

Member
Joined
Jul 31, 2015
Messages
7
Reaction score
0
Thanks to Monday, the bot has successfully taken text lines from the server and sent it to my discord channel. All I have to do is, making the bot look for specific words and get the text lines that contain them.


The thread may be locked, give this man a beer!
 
Top