625 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			625 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package steam
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"encoding/binary"
 | |
| 	"encoding/hex"
 | |
| 	. "github.com/Philipp15b/go-steam/protocol"
 | |
| 	. "github.com/Philipp15b/go-steam/protocol/protobuf"
 | |
| 	. "github.com/Philipp15b/go-steam/protocol/steamlang"
 | |
| 	. "github.com/Philipp15b/go-steam/rwu"
 | |
| 	"github.com/Philipp15b/go-steam/socialcache"
 | |
| 	. "github.com/Philipp15b/go-steam/steamid"
 | |
| 	"github.com/golang/protobuf/proto"
 | |
| 	"io"
 | |
| 	"sync"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| // Provides access to social aspects of Steam.
 | |
| type Social struct {
 | |
| 	mutex sync.RWMutex
 | |
| 
 | |
| 	name         string
 | |
| 	avatar       string
 | |
| 	personaState EPersonaState
 | |
| 
 | |
| 	Friends *socialcache.FriendsList
 | |
| 	Groups  *socialcache.GroupsList
 | |
| 	Chats   *socialcache.ChatsList
 | |
| 
 | |
| 	client *Client
 | |
| }
 | |
| 
 | |
| func newSocial(client *Client) *Social {
 | |
| 	return &Social{
 | |
| 		Friends: socialcache.NewFriendsList(),
 | |
| 		Groups:  socialcache.NewGroupsList(),
 | |
| 		Chats:   socialcache.NewChatsList(),
 | |
| 		client:  client,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Gets the local user's avatar
 | |
| func (s *Social) GetAvatar() string {
 | |
| 	s.mutex.RLock()
 | |
| 	defer s.mutex.RUnlock()
 | |
| 	return s.avatar
 | |
| }
 | |
| 
 | |
| // Gets the local user's persona name
 | |
| func (s *Social) GetPersonaName() string {
 | |
| 	s.mutex.RLock()
 | |
| 	defer s.mutex.RUnlock()
 | |
| 	return s.name
 | |
| }
 | |
| 
 | |
| // Sets the local user's persona name and broadcasts it over the network
 | |
| func (s *Social) SetPersonaName(name string) {
 | |
| 	s.mutex.Lock()
 | |
| 	defer s.mutex.Unlock()
 | |
| 	s.name = name
 | |
| 	s.client.Write(NewClientMsgProtobuf(EMsg_ClientChangeStatus, &CMsgClientChangeStatus{
 | |
| 		PersonaState: proto.Uint32(uint32(s.personaState)),
 | |
| 		PlayerName:   proto.String(name),
 | |
| 	}))
 | |
| }
 | |
| 
 | |
| // Gets the local user's persona state
 | |
| func (s *Social) GetPersonaState() EPersonaState {
 | |
| 	s.mutex.RLock()
 | |
| 	defer s.mutex.RUnlock()
 | |
| 	return s.personaState
 | |
| }
 | |
| 
 | |
| // Sets the local user's persona state and broadcasts it over the network
 | |
| func (s *Social) SetPersonaState(state EPersonaState) {
 | |
| 	s.mutex.Lock()
 | |
| 	defer s.mutex.Unlock()
 | |
| 	s.personaState = state
 | |
| 	s.client.Write(NewClientMsgProtobuf(EMsg_ClientChangeStatus, &CMsgClientChangeStatus{
 | |
| 		PersonaState: proto.Uint32(uint32(state)),
 | |
| 	}))
 | |
| }
 | |
| 
 | |
| // Sends a chat message to ether a room or friend
 | |
| func (s *Social) SendMessage(to SteamId, entryType EChatEntryType, message string) {
 | |
| 	//Friend
 | |
| 	if to.GetAccountType() == int32(EAccountType_Individual) || to.GetAccountType() == int32(EAccountType_ConsoleUser) {
 | |
| 		s.client.Write(NewClientMsgProtobuf(EMsg_ClientFriendMsg, &CMsgClientFriendMsg{
 | |
| 			Steamid:       proto.Uint64(to.ToUint64()),
 | |
| 			ChatEntryType: proto.Int32(int32(entryType)),
 | |
| 			Message:       []byte(message),
 | |
| 		}))
 | |
| 		//Chat room
 | |
| 	} else if to.GetAccountType() == int32(EAccountType_Clan) || to.GetAccountType() == int32(EAccountType_Chat) {
 | |
| 		chatId := to.ClanToChat()
 | |
| 		s.client.Write(NewClientMsg(&MsgClientChatMsg{
 | |
| 			ChatMsgType:     entryType,
 | |
| 			SteamIdChatRoom: chatId,
 | |
| 			SteamIdChatter:  s.client.SteamId(),
 | |
| 		}, []byte(message)))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Adds a friend to your friends list or accepts a friend. You'll receive a FriendStateEvent
 | |
| // for every new/changed friend
 | |
| func (s *Social) AddFriend(id SteamId) {
 | |
| 	s.client.Write(NewClientMsgProtobuf(EMsg_ClientAddFriend, &CMsgClientAddFriend{
 | |
| 		SteamidToAdd: proto.Uint64(id.ToUint64()),
 | |
| 	}))
 | |
| }
 | |
| 
 | |
| // Removes a friend from your friends list
 | |
| func (s *Social) RemoveFriend(id SteamId) {
 | |
| 	s.client.Write(NewClientMsgProtobuf(EMsg_ClientRemoveFriend, &CMsgClientRemoveFriend{
 | |
| 		Friendid: proto.Uint64(id.ToUint64()),
 | |
| 	}))
 | |
| }
 | |
| 
 | |
| // Ignores or unignores a friend on Steam
 | |
| func (s *Social) IgnoreFriend(id SteamId, setIgnore bool) {
 | |
| 	ignore := uint8(1) //True
 | |
| 	if !setIgnore {
 | |
| 		ignore = uint8(0) //False
 | |
| 	}
 | |
| 	s.client.Write(NewClientMsg(&MsgClientSetIgnoreFriend{
 | |
| 		MySteamId:     s.client.SteamId(),
 | |
| 		SteamIdFriend: id,
 | |
| 		Ignore:        ignore,
 | |
| 	}, make([]byte, 0)))
 | |
| }
 | |
| 
 | |
| // Requests persona state for a list of specified SteamIds
 | |
| func (s *Social) RequestFriendListInfo(ids []SteamId, requestedInfo EClientPersonaStateFlag) {
 | |
| 	var friends []uint64
 | |
| 	for _, id := range ids {
 | |
| 		friends = append(friends, id.ToUint64())
 | |
| 	}
 | |
| 	s.client.Write(NewClientMsgProtobuf(EMsg_ClientRequestFriendData, &CMsgClientRequestFriendData{
 | |
| 		PersonaStateRequested: proto.Uint32(uint32(requestedInfo)),
 | |
| 		Friends:               friends,
 | |
| 	}))
 | |
| }
 | |
| 
 | |
| // Requests persona state for a specified SteamId
 | |
| func (s *Social) RequestFriendInfo(id SteamId, requestedInfo EClientPersonaStateFlag) {
 | |
| 	s.RequestFriendListInfo([]SteamId{id}, requestedInfo)
 | |
| }
 | |
| 
 | |
| // Requests profile information for a specified SteamId
 | |
| func (s *Social) RequestProfileInfo(id SteamId) {
 | |
| 	s.client.Write(NewClientMsgProtobuf(EMsg_ClientFriendProfileInfo, &CMsgClientFriendProfileInfo{
 | |
| 		SteamidFriend: proto.Uint64(id.ToUint64()),
 | |
| 	}))
 | |
| }
 | |
| 
 | |
| // Requests all offline messages and marks them as read
 | |
| func (s *Social) RequestOfflineMessages() {
 | |
| 	s.client.Write(NewClientMsgProtobuf(EMsg_ClientFSGetFriendMessageHistoryForOfflineMessages, &CMsgClientFSGetFriendMessageHistoryForOfflineMessages{}))
 | |
| }
 | |
| 
 | |
| // Attempts to join a chat room
 | |
| func (s *Social) JoinChat(id SteamId) {
 | |
| 	chatId := id.ClanToChat()
 | |
| 	s.client.Write(NewClientMsg(&MsgClientJoinChat{
 | |
| 		SteamIdChat: chatId,
 | |
| 	}, make([]byte, 0)))
 | |
| }
 | |
| 
 | |
| // Attempts to leave a chat room
 | |
| func (s *Social) LeaveChat(id SteamId) {
 | |
| 	chatId := id.ClanToChat()
 | |
| 	payload := new(bytes.Buffer)
 | |
| 	binary.Write(payload, binary.LittleEndian, s.client.SteamId().ToUint64())       // ChatterActedOn
 | |
| 	binary.Write(payload, binary.LittleEndian, uint32(EChatMemberStateChange_Left)) // StateChange
 | |
| 	binary.Write(payload, binary.LittleEndian, s.client.SteamId().ToUint64())       // ChatterActedBy
 | |
| 	s.client.Write(NewClientMsg(&MsgClientChatMemberInfo{
 | |
| 		SteamIdChat: chatId,
 | |
| 		Type:        EChatInfoType_StateChange,
 | |
| 	}, payload.Bytes()))
 | |
| }
 | |
| 
 | |
| // Kicks the specified chat member from the given chat room
 | |
| func (s *Social) KickChatMember(room SteamId, user SteamId) {
 | |
| 	chatId := room.ClanToChat()
 | |
| 	s.client.Write(NewClientMsg(&MsgClientChatAction{
 | |
| 		SteamIdChat:        chatId,
 | |
| 		SteamIdUserToActOn: user,
 | |
| 		ChatAction:         EChatAction_Kick,
 | |
| 	}, make([]byte, 0)))
 | |
| }
 | |
| 
 | |
| // Bans the specified chat member from the given chat room
 | |
| func (s *Social) BanChatMember(room SteamId, user SteamId) {
 | |
| 	chatId := room.ClanToChat()
 | |
| 	s.client.Write(NewClientMsg(&MsgClientChatAction{
 | |
| 		SteamIdChat:        chatId,
 | |
| 		SteamIdUserToActOn: user,
 | |
| 		ChatAction:         EChatAction_Ban,
 | |
| 	}, make([]byte, 0)))
 | |
| }
 | |
| 
 | |
| // Unbans the specified chat member from the given chat room
 | |
| func (s *Social) UnbanChatMember(room SteamId, user SteamId) {
 | |
| 	chatId := room.ClanToChat()
 | |
| 	s.client.Write(NewClientMsg(&MsgClientChatAction{
 | |
| 		SteamIdChat:        chatId,
 | |
| 		SteamIdUserToActOn: user,
 | |
| 		ChatAction:         EChatAction_UnBan,
 | |
| 	}, make([]byte, 0)))
 | |
| }
 | |
| 
 | |
| func (s *Social) HandlePacket(packet *Packet) {
 | |
| 	switch packet.EMsg {
 | |
| 	case EMsg_ClientPersonaState:
 | |
| 		s.handlePersonaState(packet)
 | |
| 	case EMsg_ClientClanState:
 | |
| 		s.handleClanState(packet)
 | |
| 	case EMsg_ClientFriendsList:
 | |
| 		s.handleFriendsList(packet)
 | |
| 	case EMsg_ClientFriendMsgIncoming:
 | |
| 		s.handleFriendMsg(packet)
 | |
| 	case EMsg_ClientAccountInfo:
 | |
| 		s.handleAccountInfo(packet)
 | |
| 	case EMsg_ClientAddFriendResponse:
 | |
| 		s.handleFriendResponse(packet)
 | |
| 	case EMsg_ClientChatEnter:
 | |
| 		s.handleChatEnter(packet)
 | |
| 	case EMsg_ClientChatMsg:
 | |
| 		s.handleChatMsg(packet)
 | |
| 	case EMsg_ClientChatMemberInfo:
 | |
| 		s.handleChatMemberInfo(packet)
 | |
| 	case EMsg_ClientChatActionResult:
 | |
| 		s.handleChatActionResult(packet)
 | |
| 	case EMsg_ClientChatInvite:
 | |
| 		s.handleChatInvite(packet)
 | |
| 	case EMsg_ClientSetIgnoreFriendResponse:
 | |
| 		s.handleIgnoreFriendResponse(packet)
 | |
| 	case EMsg_ClientFriendProfileInfoResponse:
 | |
| 		s.handleProfileInfoResponse(packet)
 | |
| 	case EMsg_ClientFSGetFriendMessageHistoryResponse:
 | |
| 		s.handleFriendMessageHistoryResponse(packet)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (s *Social) handleAccountInfo(packet *Packet) {
 | |
| 	//Just fire the personainfo, Auth handles the callback
 | |
| 	flags := EClientPersonaStateFlag_PlayerName | EClientPersonaStateFlag_Presence | EClientPersonaStateFlag_SourceID
 | |
| 	s.RequestFriendInfo(s.client.SteamId(), EClientPersonaStateFlag(flags))
 | |
| }
 | |
| 
 | |
| func (s *Social) handleFriendsList(packet *Packet) {
 | |
| 	list := new(CMsgClientFriendsList)
 | |
| 	packet.ReadProtoMsg(list)
 | |
| 	var friends []SteamId
 | |
| 	for _, friend := range list.GetFriends() {
 | |
| 		steamId := SteamId(friend.GetUlfriendid())
 | |
| 		isClan := steamId.GetAccountType() == int32(EAccountType_Clan)
 | |
| 
 | |
| 		if isClan {
 | |
| 			rel := EClanRelationship(friend.GetEfriendrelationship())
 | |
| 			if rel == EClanRelationship_None {
 | |
| 				s.Groups.Remove(steamId)
 | |
| 			} else {
 | |
| 				s.Groups.Add(socialcache.Group{
 | |
| 					SteamId:      steamId,
 | |
| 					Relationship: rel,
 | |
| 				})
 | |
| 
 | |
| 			}
 | |
| 			if list.GetBincremental() {
 | |
| 				s.client.Emit(&GroupStateEvent{steamId, rel})
 | |
| 			}
 | |
| 		} else {
 | |
| 			rel := EFriendRelationship(friend.GetEfriendrelationship())
 | |
| 			if rel == EFriendRelationship_None {
 | |
| 				s.Friends.Remove(steamId)
 | |
| 			} else {
 | |
| 				s.Friends.Add(socialcache.Friend{
 | |
| 					SteamId:      steamId,
 | |
| 					Relationship: rel,
 | |
| 				})
 | |
| 
 | |
| 			}
 | |
| 			if list.GetBincremental() {
 | |
| 				s.client.Emit(&FriendStateEvent{steamId, rel})
 | |
| 			}
 | |
| 		}
 | |
| 		if !list.GetBincremental() {
 | |
| 			friends = append(friends, steamId)
 | |
| 		}
 | |
| 	}
 | |
| 	if !list.GetBincremental() {
 | |
| 		s.RequestFriendListInfo(friends, EClientPersonaStateFlag_DefaultInfoRequest)
 | |
| 		s.client.Emit(&FriendsListEvent{})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (s *Social) handlePersonaState(packet *Packet) {
 | |
| 	list := new(CMsgClientPersonaState)
 | |
| 	packet.ReadProtoMsg(list)
 | |
| 	flags := EClientPersonaStateFlag(list.GetStatusFlags())
 | |
| 	for _, friend := range list.GetFriends() {
 | |
| 		id := SteamId(friend.GetFriendid())
 | |
| 		if id == s.client.SteamId() { //this is our client id
 | |
| 			s.mutex.Lock()
 | |
| 			if friend.GetPlayerName() != "" {
 | |
| 				s.name = friend.GetPlayerName()
 | |
| 			}
 | |
| 			avatar := hex.EncodeToString(friend.GetAvatarHash())
 | |
| 			if ValidAvatar(avatar) {
 | |
| 				s.avatar = avatar
 | |
| 			}
 | |
| 			s.mutex.Unlock()
 | |
| 		} else if id.GetAccountType() == int32(EAccountType_Individual) {
 | |
| 			if (flags & EClientPersonaStateFlag_PlayerName) == EClientPersonaStateFlag_PlayerName {
 | |
| 				if friend.GetPlayerName() != "" {
 | |
| 					s.Friends.SetName(id, friend.GetPlayerName())
 | |
| 				}
 | |
| 			}
 | |
| 			if (flags & EClientPersonaStateFlag_Presence) == EClientPersonaStateFlag_Presence {
 | |
| 				avatar := hex.EncodeToString(friend.GetAvatarHash())
 | |
| 				if ValidAvatar(avatar) {
 | |
| 					s.Friends.SetAvatar(id, avatar)
 | |
| 				}
 | |
| 				s.Friends.SetPersonaState(id, EPersonaState(friend.GetPersonaState()))
 | |
| 				s.Friends.SetPersonaStateFlags(id, EPersonaStateFlag(friend.GetPersonaStateFlags()))
 | |
| 			}
 | |
| 			if (flags & EClientPersonaStateFlag_GameDataBlob) == EClientPersonaStateFlag_GameDataBlob {
 | |
| 				s.Friends.SetGameAppId(id, friend.GetGamePlayedAppId())
 | |
| 				s.Friends.SetGameId(id, friend.GetGameid())
 | |
| 				s.Friends.SetGameName(id, friend.GetGameName())
 | |
| 			}
 | |
| 		} else if id.GetAccountType() == int32(EAccountType_Clan) {
 | |
| 			if (flags & EClientPersonaStateFlag_PlayerName) == EClientPersonaStateFlag_PlayerName {
 | |
| 				if friend.GetPlayerName() != "" {
 | |
| 					s.Groups.SetName(id, friend.GetPlayerName())
 | |
| 				}
 | |
| 			}
 | |
| 			if (flags & EClientPersonaStateFlag_Presence) == EClientPersonaStateFlag_Presence {
 | |
| 				avatar := hex.EncodeToString(friend.GetAvatarHash())
 | |
| 				if ValidAvatar(avatar) {
 | |
| 					s.Groups.SetAvatar(id, avatar)
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		s.client.Emit(&PersonaStateEvent{
 | |
| 			StatusFlags:            flags,
 | |
| 			FriendId:               id,
 | |
| 			State:                  EPersonaState(friend.GetPersonaState()),
 | |
| 			StateFlags:             EPersonaStateFlag(friend.GetPersonaStateFlags()),
 | |
| 			GameAppId:              friend.GetGamePlayedAppId(),
 | |
| 			GameId:                 friend.GetGameid(),
 | |
| 			GameName:               friend.GetGameName(),
 | |
| 			GameServerIp:           friend.GetGameServerIp(),
 | |
| 			GameServerPort:         friend.GetGameServerPort(),
 | |
| 			QueryPort:              friend.GetQueryPort(),
 | |
| 			SourceSteamId:          SteamId(friend.GetSteamidSource()),
 | |
| 			GameDataBlob:           friend.GetGameDataBlob(),
 | |
| 			Name:                   friend.GetPlayerName(),
 | |
| 			Avatar:                 hex.EncodeToString(friend.GetAvatarHash()),
 | |
| 			LastLogOff:             friend.GetLastLogoff(),
 | |
| 			LastLogOn:              friend.GetLastLogon(),
 | |
| 			ClanRank:               friend.GetClanRank(),
 | |
| 			ClanTag:                friend.GetClanTag(),
 | |
| 			OnlineSessionInstances: friend.GetOnlineSessionInstances(),
 | |
| 			PublishedSessionId:     friend.GetPublishedInstanceId(),
 | |
| 			PersonaSetByUser:       friend.GetPersonaSetByUser(),
 | |
| 			FacebookName:           friend.GetFacebookName(),
 | |
| 			FacebookId:             friend.GetFacebookId(),
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (s *Social) handleClanState(packet *Packet) {
 | |
| 	body := new(CMsgClientClanState)
 | |
| 	packet.ReadProtoMsg(body)
 | |
| 	var name string
 | |
| 	var avatar string
 | |
| 	if body.GetNameInfo() != nil {
 | |
| 		name = body.GetNameInfo().GetClanName()
 | |
| 		avatar = hex.EncodeToString(body.GetNameInfo().GetShaAvatar())
 | |
| 	}
 | |
| 	var totalCount, onlineCount, chattingCount, ingameCount uint32
 | |
| 	if body.GetUserCounts() != nil {
 | |
| 		usercounts := body.GetUserCounts()
 | |
| 		totalCount = usercounts.GetMembers()
 | |
| 		onlineCount = usercounts.GetOnline()
 | |
| 		chattingCount = usercounts.GetChatting()
 | |
| 		ingameCount = usercounts.GetInGame()
 | |
| 	}
 | |
| 	var events, announcements []ClanEventDetails
 | |
| 	for _, event := range body.GetEvents() {
 | |
| 		events = append(events, ClanEventDetails{
 | |
| 			Id:         event.GetGid(),
 | |
| 			EventTime:  event.GetEventTime(),
 | |
| 			Headline:   event.GetHeadline(),
 | |
| 			GameId:     event.GetGameId(),
 | |
| 			JustPosted: event.GetJustPosted(),
 | |
| 		})
 | |
| 	}
 | |
| 	for _, announce := range body.GetAnnouncements() {
 | |
| 		announcements = append(announcements, ClanEventDetails{
 | |
| 			Id:         announce.GetGid(),
 | |
| 			EventTime:  announce.GetEventTime(),
 | |
| 			Headline:   announce.GetHeadline(),
 | |
| 			GameId:     announce.GetGameId(),
 | |
| 			JustPosted: announce.GetJustPosted(),
 | |
| 		})
 | |
| 	}
 | |
| 	flags := EClientPersonaStateFlag(body.GetMUnStatusFlags())
 | |
| 	//Add stuff to group
 | |
| 	clanid := SteamId(body.GetSteamidClan())
 | |
| 	if (flags & EClientPersonaStateFlag_PlayerName) == EClientPersonaStateFlag_PlayerName {
 | |
| 		if name != "" {
 | |
| 			s.Groups.SetName(clanid, name)
 | |
| 		}
 | |
| 	}
 | |
| 	if (flags & EClientPersonaStateFlag_Presence) == EClientPersonaStateFlag_Presence {
 | |
| 		if ValidAvatar(avatar) {
 | |
| 			s.Groups.SetAvatar(clanid, avatar)
 | |
| 		}
 | |
| 	}
 | |
| 	if body.GetUserCounts() != nil {
 | |
| 		s.Groups.SetMemberTotalCount(clanid, totalCount)
 | |
| 		s.Groups.SetMemberOnlineCount(clanid, onlineCount)
 | |
| 		s.Groups.SetMemberChattingCount(clanid, chattingCount)
 | |
| 		s.Groups.SetMemberInGameCount(clanid, ingameCount)
 | |
| 	}
 | |
| 	s.client.Emit(&ClanStateEvent{
 | |
| 		ClandId:             clanid,
 | |
| 		StateFlags:          EClientPersonaStateFlag(body.GetMUnStatusFlags()),
 | |
| 		AccountFlags:        EAccountFlags(body.GetClanAccountFlags()),
 | |
| 		ClanName:            name,
 | |
| 		Avatar:              avatar,
 | |
| 		MemberTotalCount:    totalCount,
 | |
| 		MemberOnlineCount:   onlineCount,
 | |
| 		MemberChattingCount: chattingCount,
 | |
| 		MemberInGameCount:   ingameCount,
 | |
| 		Events:              events,
 | |
| 		Announcements:       announcements,
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleFriendResponse(packet *Packet) {
 | |
| 	body := new(CMsgClientAddFriendResponse)
 | |
| 	packet.ReadProtoMsg(body)
 | |
| 	s.client.Emit(&FriendAddedEvent{
 | |
| 		Result:      EResult(body.GetEresult()),
 | |
| 		SteamId:     SteamId(body.GetSteamIdAdded()),
 | |
| 		PersonaName: body.GetPersonaNameAdded(),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleFriendMsg(packet *Packet) {
 | |
| 	body := new(CMsgClientFriendMsgIncoming)
 | |
| 	packet.ReadProtoMsg(body)
 | |
| 	message := string(bytes.Split(body.GetMessage(), []byte{0x0})[0])
 | |
| 	s.client.Emit(&ChatMsgEvent{
 | |
| 		ChatterId: SteamId(body.GetSteamidFrom()),
 | |
| 		Message:   message,
 | |
| 		EntryType: EChatEntryType(body.GetChatEntryType()),
 | |
| 		Timestamp: time.Unix(int64(body.GetRtime32ServerTimestamp()), 0),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleChatMsg(packet *Packet) {
 | |
| 	body := new(MsgClientChatMsg)
 | |
| 	payload := packet.ReadClientMsg(body).Payload
 | |
| 	message := string(bytes.Split(payload, []byte{0x0})[0])
 | |
| 	s.client.Emit(&ChatMsgEvent{
 | |
| 		ChatRoomId: SteamId(body.SteamIdChatRoom),
 | |
| 		ChatterId:  SteamId(body.SteamIdChatter),
 | |
| 		Message:    message,
 | |
| 		EntryType:  EChatEntryType(body.ChatMsgType),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleChatEnter(packet *Packet) {
 | |
| 	body := new(MsgClientChatEnter)
 | |
| 	payload := packet.ReadClientMsg(body).Payload
 | |
| 	reader := bytes.NewBuffer(payload)
 | |
| 	name, _ := ReadString(reader)
 | |
| 	ReadByte(reader) //0
 | |
| 	count := body.NumMembers
 | |
| 	chatId := SteamId(body.SteamIdChat)
 | |
| 	clanId := SteamId(body.SteamIdClan)
 | |
| 	s.Chats.Add(socialcache.Chat{SteamId: chatId, GroupId: clanId})
 | |
| 	for i := 0; i < int(count); i++ {
 | |
| 		id, chatPerm, clanPerm := readChatMember(reader)
 | |
| 		ReadBytes(reader, 6) //No idea what this is
 | |
| 		s.Chats.AddChatMember(chatId, socialcache.ChatMember{
 | |
| 			SteamId:         SteamId(id),
 | |
| 			ChatPermissions: chatPerm,
 | |
| 			ClanPermissions: clanPerm,
 | |
| 		})
 | |
| 	}
 | |
| 	s.client.Emit(&ChatEnterEvent{
 | |
| 		ChatRoomId:    SteamId(body.SteamIdChat),
 | |
| 		FriendId:      SteamId(body.SteamIdFriend),
 | |
| 		ChatRoomType:  EChatRoomType(body.ChatRoomType),
 | |
| 		OwnerId:       SteamId(body.SteamIdOwner),
 | |
| 		ClanId:        SteamId(body.SteamIdClan),
 | |
| 		ChatFlags:     byte(body.ChatFlags),
 | |
| 		EnterResponse: EChatRoomEnterResponse(body.EnterResponse),
 | |
| 		Name:          name,
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleChatMemberInfo(packet *Packet) {
 | |
| 	body := new(MsgClientChatMemberInfo)
 | |
| 	payload := packet.ReadClientMsg(body).Payload
 | |
| 	reader := bytes.NewBuffer(payload)
 | |
| 	chatId := SteamId(body.SteamIdChat)
 | |
| 	if body.Type == EChatInfoType_StateChange {
 | |
| 		actedOn, _ := ReadUint64(reader)
 | |
| 		state, _ := ReadInt32(reader)
 | |
| 		actedBy, _ := ReadUint64(reader)
 | |
| 		ReadByte(reader) //0
 | |
| 		stateChange := EChatMemberStateChange(state)
 | |
| 		if stateChange == EChatMemberStateChange_Entered {
 | |
| 			_, chatPerm, clanPerm := readChatMember(reader)
 | |
| 			s.Chats.AddChatMember(chatId, socialcache.ChatMember{
 | |
| 				SteamId:         SteamId(actedOn),
 | |
| 				ChatPermissions: chatPerm,
 | |
| 				ClanPermissions: clanPerm,
 | |
| 			})
 | |
| 		} else if stateChange == EChatMemberStateChange_Banned || stateChange == EChatMemberStateChange_Kicked ||
 | |
| 			stateChange == EChatMemberStateChange_Disconnected || stateChange == EChatMemberStateChange_Left {
 | |
| 			s.Chats.RemoveChatMember(chatId, SteamId(actedOn))
 | |
| 		}
 | |
| 		stateInfo := StateChangeDetails{
 | |
| 			ChatterActedOn: SteamId(actedOn),
 | |
| 			StateChange:    EChatMemberStateChange(stateChange),
 | |
| 			ChatterActedBy: SteamId(actedBy),
 | |
| 		}
 | |
| 		s.client.Emit(&ChatMemberInfoEvent{
 | |
| 			ChatRoomId:      SteamId(body.SteamIdChat),
 | |
| 			Type:            EChatInfoType(body.Type),
 | |
| 			StateChangeInfo: stateInfo,
 | |
| 		})
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func readChatMember(r io.Reader) (SteamId, EChatPermission, EClanPermission) {
 | |
| 	ReadString(r) // MessageObject
 | |
| 	ReadByte(r)   // 7
 | |
| 	ReadString(r) //steamid
 | |
| 	id, _ := ReadUint64(r)
 | |
| 	ReadByte(r)   // 2
 | |
| 	ReadString(r) //Permissions
 | |
| 	chat, _ := ReadInt32(r)
 | |
| 	ReadByte(r)   // 2
 | |
| 	ReadString(r) //Details
 | |
| 	clan, _ := ReadInt32(r)
 | |
| 	return SteamId(id), EChatPermission(chat), EClanPermission(clan)
 | |
| }
 | |
| 
 | |
| func (s *Social) handleChatActionResult(packet *Packet) {
 | |
| 	body := new(MsgClientChatActionResult)
 | |
| 	packet.ReadClientMsg(body)
 | |
| 	s.client.Emit(&ChatActionResultEvent{
 | |
| 		ChatRoomId: SteamId(body.SteamIdChat),
 | |
| 		ChatterId:  SteamId(body.SteamIdUserActedOn),
 | |
| 		Action:     EChatAction(body.ChatAction),
 | |
| 		Result:     EChatActionResult(body.ActionResult),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleChatInvite(packet *Packet) {
 | |
| 	body := new(CMsgClientChatInvite)
 | |
| 	packet.ReadProtoMsg(body)
 | |
| 	s.client.Emit(&ChatInviteEvent{
 | |
| 		InvitedId:    SteamId(body.GetSteamIdInvited()),
 | |
| 		ChatRoomId:   SteamId(body.GetSteamIdChat()),
 | |
| 		PatronId:     SteamId(body.GetSteamIdPatron()),
 | |
| 		ChatRoomType: EChatRoomType(body.GetChatroomType()),
 | |
| 		FriendChatId: SteamId(body.GetSteamIdFriendChat()),
 | |
| 		ChatRoomName: body.GetChatName(),
 | |
| 		GameId:       body.GetGameId(),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleIgnoreFriendResponse(packet *Packet) {
 | |
| 	body := new(MsgClientSetIgnoreFriendResponse)
 | |
| 	packet.ReadClientMsg(body)
 | |
| 	s.client.Emit(&IgnoreFriendEvent{
 | |
| 		Result: EResult(body.Result),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleProfileInfoResponse(packet *Packet) {
 | |
| 	body := new(CMsgClientFriendProfileInfoResponse)
 | |
| 	packet.ReadProtoMsg(body)
 | |
| 	s.client.Emit(&ProfileInfoEvent{
 | |
| 		Result:      EResult(body.GetEresult()),
 | |
| 		SteamId:     SteamId(body.GetSteamidFriend()),
 | |
| 		TimeCreated: body.GetTimeCreated(),
 | |
| 		RealName:    body.GetRealName(),
 | |
| 		CityName:    body.GetCityName(),
 | |
| 		StateName:   body.GetStateName(),
 | |
| 		CountryName: body.GetCountryName(),
 | |
| 		Headline:    body.GetHeadline(),
 | |
| 		Summary:     body.GetSummary(),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (s *Social) handleFriendMessageHistoryResponse(packet *Packet) {
 | |
| 	body := new(CMsgClientFSGetFriendMessageHistoryResponse)
 | |
| 	packet.ReadProtoMsg(body)
 | |
| 	steamid := SteamId(body.GetSteamid())
 | |
| 	for _, message := range body.GetMessages() {
 | |
| 		if !message.GetUnread() {
 | |
| 			continue // Skip already read messages
 | |
| 		}
 | |
| 		s.client.Emit(&ChatMsgEvent{
 | |
| 			ChatterId: steamid,
 | |
| 			Message:   message.GetMessage(),
 | |
| 			EntryType: EChatEntryType_ChatMsg,
 | |
| 			Timestamp: time.Unix(int64(message.GetTimestamp()), 0),
 | |
| 			Offline:   true, // GetUnread is true
 | |
| 		})
 | |
| 	}
 | |
| }
 | 
