steamutils 1.3.25 → 1.3.27
Sign up to get free protection for your applications and to get access to all the features.
- package/SteamClient.js +121 -36
- package/bufferHelpers.js +115 -0
- package/index.js +62 -26
- package/package.json +1 -1
package/SteamClient.js
CHANGED
@@ -14,6 +14,7 @@ import EFriendRelationship from "steam-user/enums/EFriendRelationship.js";
|
|
14
14
|
import SteamCommunity from "steamcommunity";
|
15
15
|
import ELobbyType from "steam-user/enums/ELobbyType.js";
|
16
16
|
import moment from "moment-timezone";
|
17
|
+
import {encode, encodeUids} from "./bufferHelpers.js";
|
17
18
|
|
18
19
|
const __filename = fileURLToPath(import.meta.url);
|
19
20
|
const __dirname = path.dirname(__filename);
|
@@ -344,22 +345,7 @@ function SteamClient({
|
|
344
345
|
}
|
345
346
|
|
346
347
|
async function gamePlay() {
|
347
|
-
|
348
|
-
for (let i = 0; i < 5; i++) {
|
349
|
-
ownedApps = await getUserOwnedApps()
|
350
|
-
if (ownedApps?.length) {
|
351
|
-
break
|
352
|
-
}
|
353
|
-
}
|
354
|
-
if (!ownedApps?.length) {
|
355
|
-
gamesPlayed(730)
|
356
|
-
} else {
|
357
|
-
ownedApps = ownedApps.map(({appid}) => appid)
|
358
|
-
ownedApps = _.shuffle(ownedApps)
|
359
|
-
ownedApps.length = Math.min(ownedApps.length, MAX_GAME_PLAY - 1)
|
360
|
-
_.remove(ownedApps, app => app == 730)
|
361
|
-
gamesPlayed([...ownedApps, 730])
|
362
|
-
}
|
348
|
+
gamesPlayed(730)
|
363
349
|
}
|
364
350
|
|
365
351
|
async function autoGamePlay() {
|
@@ -425,34 +411,127 @@ function SteamClient({
|
|
425
411
|
|
426
412
|
async function createLobby() {
|
427
413
|
console.log("createLobby");
|
428
|
-
steamClient.
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
public_ip: steamClient.logOnResult?.public_ip || {
|
436
|
-
v4: steamClient.publicIP,
|
414
|
+
steamClient._send(
|
415
|
+
{
|
416
|
+
msg: Protos.csgo.EMsg.k_EMsgClientMMSCreateLobby,
|
417
|
+
proto: {
|
418
|
+
steamid: steamClient.steamID.getSteamID64(),
|
419
|
+
routing_appid: 730
|
420
|
+
}
|
437
421
|
},
|
438
|
-
|
439
|
-
|
440
|
-
|
422
|
+
protoEncode(Protos.csgo.CMsgClientMMSCreateLobby, {
|
423
|
+
app_id: 730,
|
424
|
+
max_members: 1,
|
425
|
+
lobby_type: 1,
|
426
|
+
lobby_flags: 1
|
427
|
+
})
|
428
|
+
);
|
429
|
+
|
430
|
+
return new Promise(resolve => {
|
431
|
+
const timeout = setTimeout(function () {
|
432
|
+
delete steamClient._handlerManager._handlers[Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse];
|
433
|
+
resolve()
|
434
|
+
}, 60000)
|
435
|
+
steamClient._handlerManager.add(Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse, (payload) => {
|
436
|
+
clearTimeout(timeout)
|
437
|
+
delete steamClient._handlerManager._handlers[Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse];
|
438
|
+
const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload.toBuffer())
|
439
|
+
const steam_id_lobby = result.steam_id_lobby.toString();
|
440
|
+
resolve(steam_id_lobby);
|
441
|
+
});
|
442
|
+
})
|
443
|
+
|
444
|
+
// steamClient.sendToGC(730, Protos.csgo.EMsg.k_EMsgClientMMSCreateLobby, {
|
445
|
+
// steamid: steamClient.steamID,
|
446
|
+
// routing_appid: 730,
|
447
|
+
// }, protoEncode(Protos.csgo.CMsgClientMMSCreateLobby, {
|
448
|
+
// app_id: 730,
|
449
|
+
// max_members: 1,
|
450
|
+
// lobby_type: 1,
|
451
|
+
// lobby_flags: 1
|
452
|
+
// }))
|
453
|
+
}
|
454
|
+
|
455
|
+
async function updateLobby(lobbyID) {
|
456
|
+
console.log("updateLobby", lobbyID);
|
457
|
+
steamClient._send(
|
458
|
+
{
|
459
|
+
msg: Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyData,
|
460
|
+
proto: {
|
461
|
+
steamid: steamClient.steamID.getSteamID64(),
|
462
|
+
routing_appid: 730
|
463
|
+
}
|
464
|
+
},
|
465
|
+
protoEncode(Protos.csgo.CMsgClientMMSSetLobbyData, {
|
466
|
+
app_id: 730,
|
467
|
+
steam_id_lobby: lobbyID,
|
468
|
+
steam_id_member: '0',
|
469
|
+
max_members: 10,
|
470
|
+
lobby_type: 1,
|
471
|
+
lobby_flags: 1,
|
472
|
+
metadata: encode({
|
473
|
+
'game:ark': '0',
|
474
|
+
// Country/Message
|
475
|
+
'game:loc': '',
|
476
|
+
'game:mapgroupname': 'mg_de_mirage',
|
477
|
+
'game:mode': 'competitive',
|
478
|
+
'game:prime': '1',
|
479
|
+
'game:type': 'classic',
|
480
|
+
'members:numPlayers': '1',
|
481
|
+
'options:action': 'custommatch',
|
482
|
+
'options:anytypemode': '0',
|
483
|
+
'system:access': 'private',
|
484
|
+
'system:network': 'LIVE',
|
485
|
+
uids: [steamClient.steamID]
|
486
|
+
}, [0x00, 0x00], [0x08], {uids: encodeUids}).toBuffer()
|
487
|
+
})
|
488
|
+
);
|
489
|
+
|
490
|
+
return new Promise(resolve => {
|
491
|
+
const timeout = setTimeout(function () {
|
492
|
+
delete steamClient._handlerManager._handlers[Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyDataResponse];
|
493
|
+
resolve()
|
494
|
+
}, 60000)
|
495
|
+
//ClientMMSLobbyData
|
496
|
+
steamClient._handlerManager.add(Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyDataResponse, (payload) => {
|
497
|
+
clearTimeout(timeout)
|
498
|
+
delete steamClient._handlerManager._handlers[Protos.csgo.EMsg.k_EMsgClientMMSSetLobbyDataResponse];
|
499
|
+
const result = protoDecode(Protos.csgo.CMsgClientMMSSetLobbyDataResponse, payload.toBuffer())
|
500
|
+
const steam_id_lobby = result.steam_id_lobby.toString();
|
501
|
+
resolve(steam_id_lobby);
|
502
|
+
});
|
503
|
+
})
|
441
504
|
}
|
442
505
|
|
443
506
|
async function invite2Lobby(lobbyID, steamId) {
|
507
|
+
steamClient._send(
|
508
|
+
{
|
509
|
+
msg: Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby,
|
510
|
+
proto: {
|
511
|
+
steamid: steamClient.steamID.getSteamID64(),
|
512
|
+
routing_appid: 730
|
513
|
+
}
|
514
|
+
},
|
515
|
+
protoEncode(Protos.csgo.CMsgClientMMSInviteToLobby, {
|
516
|
+
app_id: 730,
|
517
|
+
steam_id_lobby: lobbyID,
|
518
|
+
steam_id_user_invited: steamId,
|
519
|
+
})
|
520
|
+
);
|
521
|
+
|
522
|
+
|
444
523
|
const accountid = new SteamID(steamId).accountid;
|
445
524
|
// lobbyID = new SteamID(lobbyID).accountid;
|
446
525
|
|
447
526
|
// Protos.csgo.EMsg.k_EMsgGCHInviteUserToLobby
|
448
527
|
// Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby
|
449
|
-
steamClient.sendToGC(730, Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby, {}, protoEncode(Protos.csgo.CMsgClientMMSInviteToLobby, {
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
}), function (...args) {
|
454
|
-
|
455
|
-
})
|
528
|
+
// steamClient.sendToGC(730, Protos.csgo.EMsg.k_EMsgClientMMSInviteToLobby, {}, protoEncode(Protos.csgo.CMsgClientMMSInviteToLobby, {
|
529
|
+
// app_id: 730,
|
530
|
+
// steam_id_lobby: lobbyID,
|
531
|
+
// steam_id_user_invited: accountid,
|
532
|
+
// }), function (...args) {
|
533
|
+
// console.log("invite2Lobby response", args)
|
534
|
+
// })
|
456
535
|
}
|
457
536
|
|
458
537
|
|
@@ -861,6 +940,7 @@ function SteamClient({
|
|
861
940
|
}
|
862
941
|
case Protos.csgo.EMsg.k_EMsgClientMMSCreateLobbyResponse: {
|
863
942
|
const result = protoDecode(Protos.csgo.CMsgClientMMSCreateLobbyResponse, payload)
|
943
|
+
console.log("k_EMsgClientMMSCreateLobbyResponse", result);
|
864
944
|
break
|
865
945
|
}
|
866
946
|
case Protos.csgo.ECsgoGCMsg.k_EMsgGCCStrike15_v2_ClientGCRankUpdate: {
|
@@ -1141,7 +1221,11 @@ function SteamClient({
|
|
1141
1221
|
callEvent(events.playingState, {playing_blocked, playing_app})
|
1142
1222
|
},
|
1143
1223
|
async friendRelationship(sid, relationship, previousRelationship) {
|
1144
|
-
callEvent(events.friendRelationship, {
|
1224
|
+
callEvent(events.friendRelationship, {
|
1225
|
+
steamId: sid.getSteamID64(),
|
1226
|
+
relationship,
|
1227
|
+
previousRelationship
|
1228
|
+
})
|
1145
1229
|
switch (relationship) {
|
1146
1230
|
case EFriendRelationship.None: {
|
1147
1231
|
//we got unfriended.
|
@@ -1781,6 +1865,7 @@ function SteamClient({
|
|
1781
1865
|
partySearch,
|
1782
1866
|
invite2Lobby,
|
1783
1867
|
createLobby,
|
1868
|
+
updateLobby,
|
1784
1869
|
joinLobby,
|
1785
1870
|
partyRegister,
|
1786
1871
|
requestCoPlays,
|
package/bufferHelpers.js
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
import ByteBuffer from 'bytebuffer';
|
2
|
+
import SteamID from 'steamid';
|
3
|
+
|
4
|
+
const Type = {
|
5
|
+
None : 0,
|
6
|
+
String : 1,
|
7
|
+
Int32 : 2,
|
8
|
+
Float32 : 3,
|
9
|
+
Pointer : 4,
|
10
|
+
WideString : 5,
|
11
|
+
Color : 6,
|
12
|
+
UInt64 : 7,
|
13
|
+
End : 8
|
14
|
+
}
|
15
|
+
|
16
|
+
// Encodes an object into a ByteBuffer
|
17
|
+
export const encode = (
|
18
|
+
_object,
|
19
|
+
prefix = [0x00, 0x00],
|
20
|
+
suffix = [],
|
21
|
+
customEncodeFields = {}
|
22
|
+
) => {
|
23
|
+
// Create a copy of the input object to avoid modifying it
|
24
|
+
const object = { ..._object };
|
25
|
+
const buffer = new ByteBuffer();
|
26
|
+
|
27
|
+
// Write the prefix bytes to the buffer
|
28
|
+
for (let pre of prefix) {
|
29
|
+
buffer.writeByte(pre);
|
30
|
+
}
|
31
|
+
|
32
|
+
// Iterate through the object's properties and encode them
|
33
|
+
for (let item in object) {
|
34
|
+
if (object.hasOwnProperty(item) === false) {
|
35
|
+
continue;
|
36
|
+
}
|
37
|
+
|
38
|
+
// If a custom encoder function exists for the property, use it
|
39
|
+
if (typeof customEncodeFields[item] === 'function') {
|
40
|
+
object[item] = customEncodeFields[item](object[item]);
|
41
|
+
}
|
42
|
+
_encode(object[item], buffer, item);
|
43
|
+
}
|
44
|
+
|
45
|
+
// Write the suffix bytes to the buffer
|
46
|
+
for (let suf of suffix) {
|
47
|
+
buffer.writeByte(suf);
|
48
|
+
}
|
49
|
+
|
50
|
+
// Write an End marker to the buffer
|
51
|
+
buffer.writeByte(Type.End);
|
52
|
+
buffer.flip(); // Prepare the buffer for reading
|
53
|
+
return buffer;
|
54
|
+
};
|
55
|
+
|
56
|
+
// Encodes individual properties into the ByteBuffer
|
57
|
+
const _encode = (object, buffer, name) => {
|
58
|
+
if (object instanceof Buffer) {
|
59
|
+
// If the object is a Buffer
|
60
|
+
buffer.writeByte(Type.String);
|
61
|
+
buffer.writeCString(name);
|
62
|
+
|
63
|
+
// Convert the Buffer to a hexadecimal string, split into 2-character parts, and write each part as a byte
|
64
|
+
let parts = object
|
65
|
+
.toString('hex')
|
66
|
+
.toUpperCase()
|
67
|
+
.match(/.{1,2}/g);
|
68
|
+
|
69
|
+
for (let part of parts) {
|
70
|
+
buffer.writeByte(parseInt('0x' + part));
|
71
|
+
}
|
72
|
+
} else {
|
73
|
+
// If the object is not a Buffer, check its type
|
74
|
+
switch (typeof object) {
|
75
|
+
case 'object': {
|
76
|
+
buffer.writeByte(Type.None);
|
77
|
+
buffer.writeCString(name);
|
78
|
+
|
79
|
+
for (let index in object) {
|
80
|
+
_encode(object[index], buffer, index); // Recursively encode each property
|
81
|
+
}
|
82
|
+
|
83
|
+
buffer.writeByte(Type.End);
|
84
|
+
break;
|
85
|
+
}
|
86
|
+
case 'string': {
|
87
|
+
buffer.writeByte(Type.String);
|
88
|
+
buffer.writeCString(name);
|
89
|
+
buffer.writeCString(object ? object : '');
|
90
|
+
break;
|
91
|
+
}
|
92
|
+
case 'number': {
|
93
|
+
buffer.writeByte(Type.String);
|
94
|
+
buffer.writeCString(name);
|
95
|
+
buffer.writeCString(object.toString());
|
96
|
+
break;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
};
|
101
|
+
|
102
|
+
// Encodes SteamIDs into a Buffer
|
103
|
+
export const encodeUids = (steamids) => {
|
104
|
+
const outputBuffer = [];
|
105
|
+
|
106
|
+
for (let id of steamids.map((s) => s.accountid)) {
|
107
|
+
while (id > 0x7f) {
|
108
|
+
outputBuffer.push((id | 0x80) & 0xff);
|
109
|
+
id >>= 7;
|
110
|
+
}
|
111
|
+
outputBuffer.push(id);
|
112
|
+
}
|
113
|
+
outputBuffer.push(0x00); // Null terminator
|
114
|
+
return Buffer.from(outputBuffer);
|
115
|
+
};
|
package/index.js
CHANGED
@@ -5816,17 +5816,18 @@ class SteamUser {
|
|
5816
5816
|
|
5817
5817
|
$('.profile_subpage_selector > a').each(function () {
|
5818
5818
|
const text = $(this).text()
|
5819
|
-
const link = $(this).attr('href')
|
5819
|
+
const link = _.trimEnd($(this).attr('href'), '/')
|
5820
5820
|
let count = 0
|
5821
5821
|
let offer = {}
|
5822
5822
|
if (text.includes('(') && text.includes(')')) {
|
5823
5823
|
count = parseInt(text.split('(')[1].split(')')[0].trim())
|
5824
5824
|
}
|
5825
|
-
if (
|
5825
|
+
if (link.endsWith('tradeoffers')) {
|
5826
5826
|
offer = IncomingOffers
|
5827
|
-
} else if (
|
5827
|
+
} else if (link.endsWith('tradeoffers/sent')) {
|
5828
5828
|
offer = SentOffers
|
5829
5829
|
} else {
|
5830
|
+
console.error("getTradeOffer", link);
|
5830
5831
|
//invalid text
|
5831
5832
|
}
|
5832
5833
|
offer.link = link
|
@@ -5841,30 +5842,65 @@ class SteamUser {
|
|
5841
5842
|
$('.profile_leftcol > .tradeoffer').each(function () {
|
5842
5843
|
const $1 = $(this);
|
5843
5844
|
const id = $1.attr('id')
|
5844
|
-
if (id.startsWith('tradeofferid_')) {
|
5845
|
-
|
5846
|
-
let partner = $1.html().split('ReportTradeScam(')[1].split(');')[0].trim()
|
5847
|
-
for (const s of [`"`, `'`, `"`]) {
|
5848
|
-
partner = _.trim(partner, s);
|
5849
|
-
}
|
5850
|
-
const partnerSteamId = partner.split(`',`)[0].trim()
|
5851
|
-
let partnerName = partner.split(`', "`)[1].trim();
|
5852
|
-
const playerAvatar = $1.find('.playerAvatar')
|
5853
|
-
const avatar = playerAvatar.find('img')?.attr('src')
|
5854
|
-
const link = playerAvatar.find('a')?.attr('href')
|
5855
|
-
const header = StringUtils.cleanSpace($1.find('.tradeoffer_header').text())
|
5856
|
-
const active = $1.find('.tradeoffer_items_ctn').hasClass("active")
|
5857
|
-
|
5858
|
-
tradeOffers.push({
|
5859
|
-
tradeofferid, partner: {
|
5860
|
-
steamId: partnerSteamId,
|
5861
|
-
name: partnerName,
|
5862
|
-
avatar,
|
5863
|
-
link,
|
5864
|
-
header,
|
5865
|
-
},
|
5866
|
-
})
|
5845
|
+
if (!id.startsWith('tradeofferid_')) {
|
5846
|
+
return;
|
5867
5847
|
}
|
5848
|
+
const tradeofferid = parseInt(id.split('tradeofferid_')[1])
|
5849
|
+
if(!tradeofferid){
|
5850
|
+
return
|
5851
|
+
}
|
5852
|
+
let partner = $1.html().split('ReportTradeScam(')[1].split(');')[0].trim()
|
5853
|
+
for (const s of [`"`, `'`, `"`]) {
|
5854
|
+
partner = _.trim(partner, s);
|
5855
|
+
}
|
5856
|
+
const partnerSteamId = partner.split(`',`)[0].trim()
|
5857
|
+
const partnerName = partner.split(`', "`)[1].trim();
|
5858
|
+
const playerAvatar = $1.find('.playerAvatar')
|
5859
|
+
const avatar = playerAvatar.find('img')?.attr('src')
|
5860
|
+
const link = playerAvatar.find('a')?.attr('href')
|
5861
|
+
const header = StringUtils.cleanSpace($1.find('.tradeoffer_header').text())
|
5862
|
+
const active = $1.find('.tradeoffer_items_ctn').hasClass("active")
|
5863
|
+
const tradeoffer_items_primary = $1.find('.tradeoffer_items_ctn .tradeoffer_items.primary')
|
5864
|
+
const tradeoffer_items_secondary = $1.find('.tradeoffer_items_ctn .tradeoffer_items.secondary')
|
5865
|
+
const primarySteamId = (SteamID.fromIndividualAccountID(parseInt(tradeoffer_items_primary.find("a.tradeoffer_avatar").attr("data-miniprofile")))).getSteamID64()
|
5866
|
+
const primaryItems = [...tradeoffer_items_primary.find(".tradeoffer_item_list > .trade_item")].map(function (el) {
|
5867
|
+
el = $(el)
|
5868
|
+
const economyItem = el.attr("data-economy-item")//classinfo/730/310777338/302028390
|
5869
|
+
const img = el.find("img").attr("src")
|
5870
|
+
return {
|
5871
|
+
economyItem,
|
5872
|
+
img
|
5873
|
+
}
|
5874
|
+
})
|
5875
|
+
const secondarySteamId = (SteamID.fromIndividualAccountID(parseInt(tradeoffer_items_secondary.find("a.tradeoffer_avatar").attr("data-miniprofile")))).getSteamID64()
|
5876
|
+
const secondaryItems = [...tradeoffer_items_secondary.find(".tradeoffer_item_list > .trade_item")].map(function (el) {
|
5877
|
+
el = $(el)
|
5878
|
+
const economyItem = el.attr("data-economy-item")//classinfo/730/310777338/302028390
|
5879
|
+
const img = el.find("img").attr("src")
|
5880
|
+
return {
|
5881
|
+
economyItem,
|
5882
|
+
img
|
5883
|
+
}
|
5884
|
+
})
|
5885
|
+
tradeOffers.push({
|
5886
|
+
tradeofferid,
|
5887
|
+
partner: {
|
5888
|
+
steamId: partnerSteamId,
|
5889
|
+
name: partnerName,
|
5890
|
+
avatarHash: SteamUser.GetAvatarHashFromURL(avatar),
|
5891
|
+
link,
|
5892
|
+
header,
|
5893
|
+
},
|
5894
|
+
active,
|
5895
|
+
primary: {
|
5896
|
+
steamId: primarySteamId,
|
5897
|
+
items: primaryItems
|
5898
|
+
},
|
5899
|
+
secondary: {
|
5900
|
+
steamId: secondarySteamId,
|
5901
|
+
items: secondaryItems
|
5902
|
+
}
|
5903
|
+
})
|
5868
5904
|
})
|
5869
5905
|
|
5870
5906
|
return {
|