Created
April 22, 2016 13:15
-
-
Save DoctorGester/a242b85e3b53b37f1ea13595438656da to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Net; | |
using System.Security.Cryptography; | |
using System.Threading; | |
using SteamKit2; | |
using SteamKit2.GC; | |
using SteamKit2.GC.Dota.Internal; | |
using SteamKit2.Internal; | |
namespace playerchecker | |
{ | |
class Program | |
{ | |
private static string login, pass; | |
private static ulong modId = 0; | |
private static SteamClient client; | |
private static SteamUser user; | |
private static string authCode, twoFactorAuth; | |
private static SteamGameCoordinator gc; | |
private static readonly IPEndPoint server = new IPEndPoint(IPAddress.Parse("208.78.164.10"), 27017); | |
private static void Main(string[] args) | |
{ | |
Console.WriteLine("Login"); | |
login = Console.ReadLine(); | |
Console.WriteLine("Password"); | |
pass = Console.ReadLine(); | |
Console.WriteLine("Desired mod id"); | |
ulong.TryParse(Console.ReadLine(), out modId); | |
client = new SteamClient(); | |
var manager = new CallbackManager(client); | |
user = client.GetHandler<SteamUser>(); | |
gc = client.GetHandler<SteamGameCoordinator>(); | |
manager.Subscribe<SteamClient.ConnectedCallback>(OnConnected); | |
manager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected); | |
manager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn); | |
manager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth); | |
manager.Subscribe<SteamGameCoordinator.MessageCallback>(OnGCMessage); | |
Console.WriteLine("Connecting to Steam..."); | |
client.Connect(server); | |
while (true) | |
{ | |
manager.RunWaitCallbacks(TimeSpan.FromSeconds(1)); | |
} | |
} | |
private static void OnGCMessage(SteamGameCoordinator.MessageCallback callback) | |
{ | |
if (callback.EMsg == (uint) EGCBaseClientMsg.k_EMsgGCClientWelcome) | |
{ | |
RequestPlayerNumbers(1); | |
} | |
if (callback.EMsg == (uint) EDOTAGCMsg.k_EMsgGCToClientCustomGamePlayerCountResponse) | |
{ | |
var response = | |
Activator.CreateInstance(typeof(ClientGCMsgProtobuf<CMsgGCToClientCustomGamePlayerCountResponse>), | |
callback.Message) as ClientGCMsgProtobuf<CMsgGCToClientCustomGamePlayerCountResponse>; | |
var players = response.Body.player_count; | |
var spectators = response.Body.spectator_count; | |
Console.WriteLine("Players: {0}, Spectators: {1}", players, spectators); | |
RequestPlayerNumbers(60); | |
} | |
else | |
{ | |
Console.WriteLine("Got {0} GC message {1}", callback.AppID, GetEMsgName(callback.EMsg)); | |
} | |
} | |
private static void RequestPlayerNumbers(int wait) | |
{ | |
new Thread((() => | |
{ | |
Thread.Sleep(TimeSpan.FromSeconds(wait)); | |
var request = new ClientGCMsgProtobuf<CMsgClientToGCCustomGamePlayerCountRequest>( | |
(uint) EDOTAGCMsg.k_EMsgClientToGCCustomGamePlayerCountRequest | |
); | |
request.Body.custom_game_id = modId; | |
request.SourceJobID = client.GetNextJobID(); | |
gc.Send(request, 570); | |
})).Start(); | |
} | |
private static string GetEMsgName(uint eMsg) | |
{ | |
// first lets try the enum'd emsgs | |
Type[] eMsgEnums = | |
{ | |
typeof(SteamKit2.GC.Dota.Internal.EGCBaseMsg), | |
typeof(SteamKit2.GC.Dota.Internal.EGCBaseClientMsg), | |
typeof(SteamKit2.GC.Dota.Internal.ESOMsg), | |
typeof(SteamKit2.GC.Dota.Internal.EGCSystemMsg), | |
typeof(SteamKit2.GC.Dota.Internal.EGCItemMsg), | |
typeof(SteamKit2.GC.Dota.Internal.EGCToGCMsg), | |
typeof(SteamKit2.GC.Dota.Internal.EDOTAGCMsg), | |
typeof(SteamKit2.GC.TF2.Internal.EGCBaseMsg), | |
typeof(SteamKit2.GC.TF2.Internal.ETFGCMsg), | |
}; | |
foreach (var enumType in eMsgEnums) | |
{ | |
if (Enum.IsDefined(enumType, (int) eMsg)) | |
return Enum.GetName(enumType, (int) eMsg); | |
} | |
// no dice, we can only use the uint | |
return eMsg.ToString(); | |
} | |
private static void OnDisconnected(SteamClient.DisconnectedCallback obj) | |
{ | |
Console.WriteLine("Disconnected from Steam, reconnecting in 5..."); | |
Thread.Sleep(TimeSpan.FromSeconds(5)); | |
client.Connect(server); | |
} | |
private static void OnLoggedOn(SteamUser.LoggedOnCallback callback) | |
{ | |
Console.WriteLine("Login callback: " + callback.Result.ToString()); | |
var isSteamGuard = callback.Result == EResult.AccountLogonDenied; | |
var is2FA = callback.Result == EResult.AccountLoginDeniedNeedTwoFactor; | |
if (isSteamGuard || is2FA) | |
{ | |
if (is2FA) | |
{ | |
Console.Write("Please enter your 2 factor auth code from your authenticator app: "); | |
twoFactorAuth = Console.ReadLine(); | |
} | |
else | |
{ | |
Console.Write("Please enter the auth code sent to the email at {0}: ", callback.EmailDomain); | |
authCode = Console.ReadLine(); | |
} | |
return; | |
} | |
Console.WriteLine("Logged in"); | |
RequestGameData(); | |
} | |
private static void RequestGameData() | |
{ | |
var playGame = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed); | |
playGame.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed | |
{ | |
game_id = new GameID(570), | |
}); | |
Thread.Sleep(TimeSpan.FromSeconds(3)); | |
client.Send(playGame); | |
var hello = new ClientGCMsgProtobuf<CMsgClientHello>((uint) EGCBaseClientMsg.k_EMsgGCClientHello); | |
hello.Body.engine = ESourceEngine.k_ESE_Source2; | |
gc.Send(hello, 570); | |
} | |
private static void OnConnected(SteamClient.ConnectedCallback obj) | |
{ | |
Console.WriteLine("Connected to Steam! Logging in"); | |
byte[] sentryHash = null; | |
if (File.Exists("sentry.bin")) | |
{ | |
Console.WriteLine("Found a sentry file"); | |
// if we have a saved sentry file, read and sha-1 hash it | |
var sentryFile = File.ReadAllBytes("sentry.bin"); | |
sentryHash = CryptoHelper.SHAHash(sentryFile); | |
} | |
user.LogOn(new SteamUser.LogOnDetails | |
{ | |
Username = login, | |
Password = pass, | |
AuthCode = authCode, | |
SentryFileHash = sentryHash, | |
TwoFactorCode = twoFactorAuth | |
}); | |
} | |
static void OnMachineAuth(SteamUser.UpdateMachineAuthCallback callback) | |
{ | |
Console.WriteLine("Updating sentryfile..."); | |
// write out our sentry file | |
// ideally we'd want to write to the filename specified in the callback | |
// but then this sample would require more code to find the correct sentry file to read during logon | |
// for the sake of simplicity, we'll just use "sentry.bin" | |
int fileSize; | |
byte[] sentryHash; | |
using (var fs = File.Open("sentry.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite)) | |
{ | |
fs.Seek(callback.Offset, SeekOrigin.Begin); | |
fs.Write(callback.Data, 0, callback.BytesToWrite); | |
fileSize = (int) fs.Length; | |
fs.Seek(0, SeekOrigin.Begin); | |
using (var sha = new SHA1CryptoServiceProvider()) | |
{ | |
sentryHash = sha.ComputeHash(fs); | |
} | |
} | |
// inform the steam servers that we're accepting this sentry file | |
user.SendMachineAuthResponse(new SteamUser.MachineAuthDetails | |
{ | |
JobID = callback.JobID, | |
FileName = callback.FileName, | |
BytesWritten = callback.BytesToWrite, | |
FileSize = fileSize, | |
Offset = callback.Offset, | |
Result = EResult.OK, | |
LastError = 0, | |
OneTimePassword = callback.OneTimePassword, | |
SentryFileHash = sentryHash, | |
}); | |
Console.WriteLine("Done!"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment