-
Notifications
You must be signed in to change notification settings - Fork 154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Chat for SteamClient #13
Comments
I've looked into this a little bit and I've discovered: You can listen to the message
|
Sending a message:
Putting this all together you could write a simple "copycat":
|
Hi @thomassross, thanks for the info I appreciate it. My fault for not adding any details on the issue, but the issue was more about implementing code in the module that abstracts the unnecessary details while providing a simple and initiative API. I already have something in the works. |
* added send_message() on SteamUser * added `chat_message` event for incoming friend messages
Can you please add thomassross example of chat to documentation or examle pages? It helps to do basic things. |
You are right @alexche8, docs are a bit lacking on that. It will happen at some point. Currently you can send and receive messages from individual users. Here is a simple message echo example,
|
@rossengeorgiev , thanks! |
User chats work perfectly, are group chats getting implemented any time soon? |
User chat working tested on linux.I wish i had time to help but working too hard these days. Thanks for everyone ~~ |
I'm slowly figuring out group chat. For example, I managed to get joining group chats to work. You have to use non-protobuf messages (Msg class) serialized to bytes. For example, given an invite with chatroomid, to join that chatroom we need something like this:
Where MsgClientJoinChat is a class encapsulating the required fields, and providing a method for serialization to bytes. A crude version of this class could look like this:
The hard part is converting the steam id into bytes and reversing their order (unless I missed some built-in python function that does that). After sending the message in the way described in the first block of code, the bot joins the chatroom. I was unable to find non-protobuf messages with bodies specific to their types (like this MsgClientJoinChat class I pasted here). Have I missed them or is this functionality not implemented in the library? |
I figured out something more advanced: receiving group chat messages. In
This can be unpacked with Once we have this unpacked, we set a An ugly way to do that would be just getting the length of the message in bytes and subtracting 8+8+4=20 bytes, since that's how much the first three attributes take. Then we can use s in the format string. |
Nice, those seem to be correct. They are indeed not protos for them
If it is endianness just use
It's not ugly at all. "<QQI{}s".format(len(body) - struct.calcsize("QQI")) |
Yes, that works. I will post a pull request later today (with example usage in the docs) and next week I'll try handling events where people enter/exit chat, and sending messages to group chats. |
Everything is here btw: https://github.com/SteamRE/SteamKit/blob/master/Resources/SteamLanguage/steammsg.steamd Should probably write a script to parse those one day |
This is useful, but I do not believe this is 100% correct though. For example, I am now working on enter/exit events for group chat. The client receives So it turns out that this message has also a |
I want to implement the ClientChatEnter event which happens when you enter the group.
Now the first 8 are easy, struct.unpack_from with "<QQIQQ?II" format string. |
I will check this out once I get home. I am able to parse this correctly in a primitive way like this:
ChatMemberInfo uses |
@nukeop I've refactored the |
Great, when I make a pull request I'll use the new structure. Are those MessageObjects parsed somewhere, or are they only declared? I figured I could add this as a class somewhere with a method that could load them from this string-null-data format, either loading the attributes into a dictionary or turning them into object's own attributes. |
Classes inheriting from |
@nukeop oh, if you see |
Nope,
Here's example binary data in urlsafe base64-encoded form (use base64.urlsafe_b64decode to get the data; I'm not sure if I'd be able to post raw bytes in a comment on Github):
The above string contains everything after the group name. |
Ok. This is not the whole message. You can just use '\x00\x00MessageObject\x00\x07steamid\x00\x7f\xd2\x00\x04\x01\x00\x10\x01\x02permissions\x00\x1a\x03\x00\x00\x02Details\x00\x02\x00\x00\x00\x08\x08\x00MessageObject\x00\x07steamid\x00\x951\xca\x05\x01\x00\x10\x01\x02permissions\x00\n\x00\x00\x00\x02Details\x00\x04\x00\x00\x00\x08\x08\xe8\x03\x00\x00' There are two binary VDFs in there with some extra bytes. There is probably a field telling you how many bin VDFs there are. In [30]: vdf.binary_loads('\x00MessageObject\x00\x07steamid\x00\x951\xca\x05\x01\x00\x10\x01\x02permissions\x00\n\x00\x00\x00\x02Details\x00\x04\x00\x00\x00\x08\x08')
Out[30]:
{'MessageObject': {'Details': 4,
'permissions': 10,
'steamid': UINT_64(76561198057402773)}} |
This is the entire example message:
Should it end at 08 08? The number of these VDF blocks is equal to |
This does the trick:
Is this clean enough? I don't like the magic 08 08 but I don't know how to avoid it. |
I really don't like that parsing code, so I made def load(self, data):
buf, self.memberList = StructReader(data), list()
(self.steamIdChat, self.steamIdFriend, self.chatRoomType, self.steamIdOwner,
self.steamIdClan, self.chatFlags, self.enterResponse, self.numMembers
) = buf.unpack("<QQIQQ?II")
self.chatRoomName = buf.read_cstring().decode('utf-8')
for _ in range(self.numMembers):
self.memberList.append(vdf.binary_loads(buf.read(64))['MessageObject'])
self.UNKNOWN1, = buf.unpack("<I") |
After ClientChatEnter, what are the remaining group chat features that need to be implemented? What examples/recipes are needed for the documentation? |
Have that code
But it doesn't work. Have that error: |
@Lambda14 open a new issue and include the full stack trace |
Not sure if the old group chat exist anymore, but there are now protos for the new one. Added in 8c80ab8 |
Have there been any updates on this? I am interested in sending and receiving messages but only to one user, and was wondering if this was going to be made any easier in V.1 Is there also a discord server that I could join to get help? |
I'm not sure what you mean by commands, videos and pictures can't currently be sent but I can't imagine they are particularly high on the priorities list. |
Let me consult my 🎱 |
At first glance in the code, it looks like (as you pointed out above @rossengeorgiev) we have private methods to handle the sending and receiving of the Do you just need help with creating that subscription so that we can listen to these |
#13 (comment) all of that can already be done now. |
Is there no way to filter out own messages when listening to the event EVENT_CHAT_MESSAGE? |
That's a bug. That will only happen if you are logged into another session, which you didn't mention. So I'm guessing you are running your code on the same user you are logged in with Steam. When you send a message from either client, it will echo it into the other to keep the chats in sync. client.on("FriendMessagesClient.IncomingMessage#1")
def handle_priv_messages(self, msg):
if msg.body.chat_entry_type == EChatEntryType.ChatMsg and not msg.body.local_echo:
user = client.get_user(msg.body.steamid_friend)
text = msg.body.message
print("{} said: {}".format(user.name, text)) |
Fix for a bug reported in ValvePython#13
Hello I send a message to my friend using this guide https://steam.readthedocs.io/en/latest/api/steam.client.user.html#steam.client.user.SteamUser.send_message but nothing really happened. I checked the message tab from steam client and no message appeared. I am not sure what I am doing wrong. Here is my code
|
You didn't actually send the message. You queued a message to be send, but your code never gives a chance for that to happen. You have to yield to the event loop, so that the message gets processed and sent. For example, you could simply sleep for a short time |
Hello, I would like to ask, can I send messages to the Steam chat group now? This issue is from 2022 |
Tasks:
The text was updated successfully, but these errors were encountered: