I am trying to create a simple steam bot with SteamKit2 and C#, but am running into issues connecting. This code will ask me for all credentials, but never do anything else after that (wont even reach the end of the program, think its stuck in the while loop)
Code (http://hastebin.com/idikidixaq.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SteamKit2;
using ProtoBuf;
namespace chatbot
{
class Program
{
static string user, pass;
static SteamClient steamClient;
static CallbackManager manager;
static SteamUser steamUser;
static bool running = true;
static void Main(string[] args)
{
Console.Title = "Chat Bot\n\n";
Console.Write("Enter Username: ");
user = Console.ReadLine();
Console.Write("Enter Password: ");
pass = Console.ReadLine();
SteamLogIn(user, pass);
Console.ReadKey();
}
static void SteamLogIn(string u, string p)
{
steamClient = new SteamClient();
manager = new CallbackManager(steamClient);
steamUser = steamClient.GetHandler<SteamUser>();
new Callback<SteamClient.ConnectedCallback>(onConnected, manager);
new Callback<SteamUser.LoggedOnCallback>(onLogOn, manager);
steamClient.Connect();
while (running)
{
manager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
}
}
static void onConnected(SteamClient.ConnectedCallback callback)
{
if(callback.Result != EResult.OK)
{
Console.WriteLine("Error! {0}", callback.Result);
running = false;
return;
}
Console.WriteLine("Connected to Steam.\nLogging In...\n");
steamUser.LogOn(new SteamUser.LogOnDetails
{
Username = user,
Password = pass,
});
}
static void onLogOn(SteamUser.LoggedOnCallback callback)
{
Console.WriteLine(callback);
}
}
}
Related
I'm running a server with a localhost http://*:52080.
On the same computer, I'm run client and trying to connect to a local IP hub http://192.168.1.102:52080/signalr. Everything works well.
But if I run the client on another computer (from the same local network) and try to connect to http://192.168.1.102:52080/signalr, it does not connect. The client catches an exception ("System.AggregateException" in mscorlib.dll).
Port 52080 on the computer with the hub is open.
What could be the reason for the failure?
Server:
using System;
using Microsoft.Owin.Hosting;
public class Program
{
static void Main(string[] args)
{
string url = "http://*:52080";
using (WebApp.Start<Startup>(url))
{
Console.WriteLine("Server running at {0}\n", url);
Console.ReadLine();
}
}
}
Startup.cs
using Owin;
using Microsoft.Owin.Cors;
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
SGHub.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using System.Collections.Generic;
public class SGHub : Hub
{
public static List<string> Users = new List<string>();
public override Task OnConnected()
{
Console.WriteLine("\nOnConnected {0}", Context.ConnectionId);
Users.Add(Context.ConnectionId);
Clients.Caller.broadcastMessage("Server:", "Successful connection");
Clients.Others.broadcastMessage("Server:", "New connection");
return (base.OnConnected());
}
}
Client:
using System;
using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNet.SignalR.Client.Hubs;
using Newtonsoft.Json.Linq;
class Program
{
static void Main(string[] args)
{
string serverURL = "http://192.168.1.102:52080/signalr";
Console.WriteLine("Connection to {0}\n", serverURL);
HubConnection hubConnection = new HubConnection(serverURL);
IHubProxy myHubProxy = hubConnection.CreateHubProxy("StartGameHub");
myHubProxy.On<string, string>("Send", (name, message) => Console.Write("Recieved addMessage: " + name + ": " + message + "\n"));
myHubProxy.On("heartbeat", () => Console.Write("Recieved heartbeat \n"));
Subscription subscription = myHubProxy.Subscribe("broadcastMessage");
subscription.Received += SubscriptionData;
while (true)
{
string key = Console.ReadLine();
if (key.ToUpper() == "A")
{
try
{
Console.WriteLine("Start connect..");
hubConnection.Start().Wait();
}
catch (System.AggregateException e)
{
Console.WriteLine("Connected fauld :(");
}
}
}
}
private static void SubscriptionData(IList<JToken> obj)
{
Console.WriteLine(obj[1].ToString());
}
}
I am making a trade offer bot in C# using SteamKit2, and most of the time it is successfully connecting to steam. But some of the time it just freezes when I have it output "Connecting to Steam..." right before client.connect(); is called. It happens often enough that it needs to be fixed, but I don't know what the problem is. Here is my code (a lot was taken from a SteamKit2 tutorial):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SteamKit2;
namespace ATO
{
class OfferSender
{
string username;
string password;
SteamClient client;
CallbackManager manager;
SteamUser user;
bool isRunning = false;
public OfferSender()
{
}
public void login()
{
Console.Write("Please enter your username: ");
username = Console.ReadLine();
Console.Write("Please enter your password: ");
password = Console.ReadLine();
client = new SteamClient();
manager = new CallbackManager(client);
user = client.GetHandler<SteamUser>();
new Callback<SteamClient.ConnectedCallback>(OnConnected, manager);
new Callback<SteamUser.LoggedOnCallback>(OnLoggedOn, manager);
isRunning = true;
Console.WriteLine("\nConnecting to Steam...\n");
client.Connect();
while(isRunning)
{
manager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
}
Console.ReadKey();
}
public void OnConnected(SteamClient.ConnectedCallback callback)
{
if (callback.Result != EResult.OK)
{
Console.WriteLine("Error connecting to Steam: {0}", callback.Result);
isRunning = false;
return;
}
Console.WriteLine("Connected to steam.\nLogging in {0}...\n", username);
user.LogOn(new SteamUser.LogOnDetails {
Username = username,
Password = password
});
}
public void OnLoggedOn(SteamUser.LoggedOnCallback callback)
{
if (callback.Result == EResult.AccountLogonDenied)
{
Console.WriteLine("This account is SteamGuard protected.");
return;
}
if(callback.Result != EResult.OK)
{
Console.WriteLine("Unable to log in to steam {0}\n", callback.Result);
isRunning = false;
return;
}
Console.WriteLine("successfully logged in!");
Environment.Exit(0);
}
}
}
How do I fix this?
Well, after banging my head against the keyboard I finaly spoted that Steam would be requesting an AuthCode like any other new computer or browser login.
And that's it...
The code below handles either AuthCode and TwoFactor authentications:
https://github.com/SteamRE/SteamKit/tree/master/Samples/5.SteamGuard
You need to handle some more callbacks.
Here is how do I log into steam with my bot.
SteamBot.cs
using System;
using SteamKit2;
using System.Collections.Generic;
namespace StackOverflow
{
class SteamBot
{
CallbackManager m_CallbackManager;
SteamUser m_SteamUser;
SteamClient m_SteamClient;
SteamFriends m_SteamFriends;
SteamID m_SteamID;
Dictionary<string, string> m_Config;
public bool isLoggedOn { get; private set; }
public bool isReady { get; private set; }
public SteamBot(string pUsername, string pPassword)
{
isLoggedOn = false;
isReady = false;
m_Config = new Dictionary<string, string>();
m_Config.Add("username", pUsername);
m_Config.Add("password", pPassword);
Init();
RegisterCallbacks();
Connect();
}
private void Init()
{
m_SteamClient = new SteamClient();
m_CallbackManager = new CallbackManager(m_SteamClient);
m_SteamFriends = m_SteamClient.GetHandler<SteamFriends>();
m_SteamUser = m_SteamClient.GetHandler<SteamUser>();
}
private void RegisterCallbacks()
{
m_CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
m_CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);
m_CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
m_CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
m_CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
}
public void WaitForCallbacks()
{
m_CallbackManager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
}
public string GetConfigValue(string pKey)
{
return m_Config[pKey];
}
public void Connect()
{
m_SteamClient.Connect();
isReady = true;
}
void OnConnected(SteamClient.ConnectedCallback pData)
{
Console.WriteLine("Connected to Steam! Logging in '{0}'...", GetConfigValue("username"));
SteamUser.LogOnDetails details = new SteamUser.LogOnDetails
{
Username = GetConfigValue("username"),
Password = GetConfigValue("password"),
};
m_SteamUser.LogOn(details);
m_SteamID = m_SteamClient.SteamID;
}
void OnDisconnected(SteamClient.DisconnectedCallback pData)
{
m_SteamClient.Disconnect();
}
void OnLoggedOff(SteamUser.LoggedOffCallback pData)
{
isLoggedOn = false;
}
void OnLoggedOn(SteamUser.LoggedOnCallback pData)
{
if (pData.Result != EResult.OK)
{
Console.WriteLine("Unable to login to Steam: {0} / {1}", pData.Result, pData.ExtendedResult);
return;
}
Console.WriteLine("Successfully logged on!");
isLoggedOn = true;
}
void OnAccountInfo(SteamUser.AccountInfoCallback pData)
{
//Announce to all friends that we are online
m_SteamFriends.SetPersonaState(EPersonaState.Online);
}
}
}
Program.cs
namespace StackOverflow
{
class Program
{
static void Main(string[] args)
{
SteamBot bot = new SteamBot("botname", "password");
while(true)
{
if(bot.isReady)
{
bot.WaitForCallbacks();
}
}
}
}
}
You need to add Steam Directory.Initialize().Wait(); before you attempt to connect so SteamKit can update its internal list of servers, as explained here.
I wrote this C# code to have namedPipeServer and NamedPipeClient, with Asynchronous read and write settings, connect to each other. Both code runs perfectly on visual studio 2010 that I am using with read and write working well without any application freeze during runtime.
But I want the client side running in unity3d. The problem I encounter is in client side code implemented in Unity3D. When I use Write_to_Server_Async(string message), read in the server side is not invoked and is only invoked when I quit Unity3d (I have end its process typically). I can tell something wrong with Unity3D, because the exact code works perfectly in visual studio, so I know my code is implemented the right way. I have heard about how unity3d does not really use real threads unless user manually creates one but even that has not solved the problem. My speculation is Unity3D developers might have created their version of .NET library 3.5 (sounds bizzare (does explain why they still haven't adopted 4.5)) or somehow they must have structured their library in a way that by default functions like NamedPipeClientStream.BeginWrite cannot create its own real thread. But then again I am not sure if its the problem with threads.
At the moment, I would like anyone to come up with good explanation.
Make sure to replace Debug.WriteLine to UnityEngine.Debug.Log in unity3d.
Below is Client Main method code and class
class PipeClient
{
private static Asynchronus_NamedPipe_Client client;
static void Main(string[] args)
{
client = new Asynchronus_NamedPipe_Client("mypipe7055");
while (client.Is_connected_to_server()) {
if (Console.ReadKey().Key == ConsoleKey.T)
{
client.Write_to_Server_Async("NEX CLIENT");
}
}
}
}
Asynchronus_NamedPipe_Client class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
using System.Security.Principal;
using System.Diagnostics;
using System.Threading;
namespace NamedPipes_CLIENT
{
public class Asynchronus_NamedPipe_Client
{
public readonly string pipe_address;
private System.IO.Pipes.NamedPipeClientStream clientStream;
public bool filter_message = true;
private string Server_Message = null;
public event ASYNC_pipe_status_callback ASYNC_external_Write_Completed;
public event ASYNC_pipe_status_callback ASYNC_external_Read_Completed;
public delegate void ASYNC_pipe_status_callback(string message);
private byte[] read_buffer = new byte[1024];
private byte[] write_buffer = new byte[1024];
private IAsyncResult read_result;
private IAsyncResult write_result;
private int read_id = 1;
public Asynchronus_NamedPipe_Client(string pipe_address)
{
try
{
this.pipe_address = pipe_address;
// if(clientStream.IsConnected){UnityEngine.Debug.Log("Server Already Running");}else{}
clientStream = new NamedPipeClientStream(".", this.pipe_address, PipeDirection.InOut, PipeOptions.Asynchronous);
clientStream.Connect(1);
if (clientStream.IsConnected)
{
Console.WriteLine("Connected to Server");
Read_from_Server_Async();
}
else { Console.WriteLine("Could NOT connect to Server"); }
}
catch (Exception oEX) { Console.WriteLine("Application Pipe Error: "+oEX.Message); }
}
public void Write_to_Server_Async(string message)
{
if (clientStream != null)
{
if (clientStream.CanWrite && clientStream.IsConnected)
{
clientStream.WaitForPipeDrain();
ASCIIEncoding.ASCII.GetBytes(message).CopyTo(write_buffer,0);
clientStream.BeginWrite(write_buffer, 0, write_buffer.Length, new AsyncCallback(Async_Write_Completed), 1);
} else { close_pipe(); }
}
}
public void Read_from_Server_Async()
{
if (clientStream.CanRead && clientStream.IsConnected)
{
clientStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(Async_Read_Completed), 2);
} else { close_pipe(); }
}
private void Async_Write_Completed(IAsyncResult result)
{
clientStream.EndWrite(result);
Debug.WriteLine("Written To Server => " + ASCIIEncoding.ASCII.GetString(write_buffer));
// close_pipe();
}
private void Async_Read_Completed(IAsyncResult result)
{
clientStream.EndRead(result);
Server_Message = ASCIIEncoding.ASCII.GetString(read_buffer);
this.Server_Message.Trim();
Console.WriteLine("Received from Server => " + Server_Message);
Debug.WriteLine("Received from Server => " + Server_Message);
if (clientStream.CanRead && clientStream.IsConnected)
{
Read_from_Server_Async();
}
else { close_pipe(); }
}
public Boolean Is_connected_to_server() {
return clientStream.IsConnected;
}
public void close_pipe()
{
if (clientStream != null)
{
if (clientStream.IsConnected)
{
clientStream.Close();
clientStream.Dispose();
Debug.WriteLine(" Pipe Closed");
}
}
}
}
}
Server side Main method implementation
static void Main(string[] args)
{
Asynchronus_NamedPipe_Server Async_server = new Asynchronus_NamedPipe_Server("mypipe7055");
while (true)
{
do
{
Async_server.Write_to_Client_Async("yeye");
Console.WriteLine("escape key");
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
}
}
Server Side Class -----
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using System.ComponentModel;
using System.Diagnostics;
namespace Application_Pipe
{
public class Asynchronus_NamedPipe_Server
{
public readonly string pipe_address;
private System.IO.Pipes.NamedPipeServerStream namedPipeServerStream;
private string Server_Message;
public delegate void ASYNC_pipe_status_callback(string message);
private byte[] read_buffer = new byte[1024];
private byte[] write_buffer = new byte[1024];
public Asynchronus_NamedPipe_Server(string pipe_address)
{
try
{
this.pipe_address = pipe_address;
namedPipeServerStream = new NamedPipeServerStream(this.pipe_address,
PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); //new NamedPipeServerStream(pipe_address);
Console.WriteLine("Connecting to Client...");
namedPipeServerStream.WaitForConnection();
Console.WriteLine("Connected to Client");
Read_from_Client_Async();
}
catch (Exception oEX) { Console.WriteLine(oEX.Message); }
}
public void Write_to_Client_Async(string message)
{
if (namedPipeServerStream != null)
{
if (namedPipeServerStream.CanWrite && namedPipeServerStream.IsConnected)
{
namedPipeServerStream.WaitForPipeDrain();
ASCIIEncoding.ASCII.GetBytes(message).CopyTo(write_buffer,0);
namedPipeServerStream.BeginWrite(write_buffer, 0, write_buffer.Length, new AsyncCallback(Async_Write_Completed), 2);
}
else { close_pipe(); }
}
}
public void Read_from_Client_Async()
{
if (namedPipeServerStream != null)
{
if (namedPipeServerStream.CanRead && namedPipeServerStream.IsConnected)
{
namedPipeServerStream.BeginRead(read_buffer, 0, read_buffer.Length, new AsyncCallback(Async_Read_Completed), 1);
} else { close_pipe(); }
}
}
private void Async_Read_Completed(IAsyncResult result)
{
namedPipeServerStream.EndRead(result);
this.Server_Message = ASCIIEncoding.ASCII.GetString(read_buffer);
this.Server_Message.Trim();
Debug.WriteLine("Received from Client => " + this.Server_Message+" <=REnd");
Read_from_Client_Async();
}
private void Async_Write_Completed(IAsyncResult result)
{
namedPipeServerStream.EndWrite(result);
Debug.WriteLine("Written To Client => " + ASCIIEncoding.ASCII.GetString(write_buffer));
}
public Boolean Is_connected_to_server()
{
return this.namedPipeServerStream.IsConnected;
}
public void close_pipe()
{
if(namedPipeServerStream.IsConnected){
namedPipeServerStream.Disconnect();
}
namedPipeServerStream.Close();
namedPipeServerStream.Dispose();
Debug.WriteLine(" Pipe Closed");
}
} //------class End
}
Is it possible to write something in the console while the program is writing something in this console ? It can be useful when you rename, or remove some files, when you do a repetitive action, and the program is writing a lot in the console. Then you will be able to write a command to stop the execution of the repetitive action while the program is continuing to write in the console. I think it's not very clear, well I illustrated you this fact with the code which I think the most apt (but I precise that it doesn't work ;) ). We have 3 classes.
The main class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static bool m_Write;
public static bool write
{
get { return m_Write; }
set { m_Write = value; }
}
static void Main(string[] args)
{
int index = 0;
Console.ReadLine();
m_Write = true;
Reader reader = new Reader();
while (m_Write)
{
index++;
Writer writer = new Writer(index.ToString());
}
}
}
}
The reading class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication1
{
class Reader
{
private Thread m_Reading_Thread;
private string m_text_To_Read;
public Reader()
{
m_Reading_Thread = new Thread(new ThreadStart(Read));
m_Reading_Thread.Start();
}
public void Read()
{
m_text_To_Read = Console.ReadLine();
if (m_text_To_Read == "Stop")
{
Program.write = false;
}
}
}
}
And the writing class :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication1
{
class Writer
{
private Thread m_Writing_Thread;
private string m_Text_To_Write;
public Writer(string text_To_Write)
{
m_Text_To_Write = text_To_Write;
m_Writing_Thread = new Thread(new ThreadStart(Write));
m_Writing_Thread.Start();
}
public void Write()
{
Console.WriteLine(m_Text_To_Write);
}
}
}
This isn't nearly as complicated as you're trying to make it. In general there are two ways you can do this. You can start a background thread to do the writing, and have the main thread block on the console waiting for the read, or you can have the main thread writing and have the background thread do the read. I like the first solution best:
public class Program
{
private static readonly ManualResetEvent StopWriting = new ManualResetEvent(false);
private static void Main(string[] args)
{
Thread t = new Thread(WriterFunc);
t.Start();
string input;
do
{
input = Console.ReadLine();
} while (input != "stop");
// Tell the thread to stop writing
StopWriting.Set();
// And wait for the thread to exit
t.Join();
}
private static void WriterFunc()
{
int index = 0;
while (!StopWriting.WaitOne(Timeout.Infinite))
{
++index;
Console.WriteLine(index.ToString());
}
}
}
Note that I used a ManualResetEvent here rather than a Boolean flag. An even better solution would be to use a CancellationToken. Using a flag can cause all kinds of interesting problems because the compiler might determine that the variable can't change (it assumes single-threaded access). Your thread might continue running even after the variable is changed.
If you want the main thread to do the writing, and the background thread to do the reading:
public class Program
{
private static readonly ManualResetEvent StopWriting = new ManualResetEvent(false);
private static void Main(string[] args)
{
Thread t = new Thread(ReaderFunc);
t.Start();
int index = 0;
while (!StopWriting.WaitOne(Timeout.Infinite))
{
++index;
Console.WriteLine(index.ToString());
}
// Wait for the background thread to exit
t.Join();
}
private static void ReaderFunc()
{
string input;
do
{
input = Console.ReadLine();
} while (input != "stop");
// Tell the main thread to stop writing
StopWriting.Set();
}
}
Something like this would work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var w = new Writer();
var r = new Reader();
while (!r.finish)
{
w.enabled = true;
string k = Console.ReadKey(false).KeyChar.ToString();
w.enabled = false;
string line = k + Console.ReadLine();
r.Read(line);
}
}
}
class Writer
{
public bool enabled = true;
public Writer()
{
var timer = new System.Timers.Timer(1000);
timer.Elapsed += (a, b) =>
{
if(enabled)
Console.WriteLine("Test");
};
timer.Start();
}
}
class Reader
{
public bool finish = false;
public void Read(string line)
{
if (line == "stop")
{
finish = true;
}
}
}
}
Don't worry if the Writer writes above what you are typing, the Console.ReadLine() only considers what you have typed.
In the case of a console application, no two threads can write data to the screen at the exact same time.
AFAIK, in the above answer, the Writes()'s constructor is continuously executed until it finishes running. Then the control will be passed to the Reader(). So I don't think that works for what you need. Correct me if I am wrong.
I'd like to write a loop that collects key presses (from the keyboard) and does an action every second or so. There would be some way of reading from the keyboard:
whenever (Console.KeyPressed != null) {
input_buffer.Add(Console.KeyPressed);
}
And there would be some loop happening:
while (!done) {
if (input_buffer.NotEmpty()) { do_stuff(input_buffer.Pop()); }
do_other_stuff();
wait(0.5 seconds);
}
So if the user presses a key, it gets dealt with during the next update. If they don't press a key, the next update happens anyhow.
If you're on .Net 4 you can use the code below. It uses ConcurrentQueue for storing the keypresses, ManualResetEventSlim for signaling, and Task from the Task Parallel Library for running the two code parts asynchronously.
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace Test
{
public class Program
{
private static ConcurrentQueue<ConsoleKeyInfo> _keypresses = new ConcurrentQueue<ConsoleKeyInfo>();
private static ManualResetEventSlim _stopEvent = new ManualResetEventSlim();
public static void Main()
{
Console.TreatControlCAsInput = true;
var keyReaderTask = Task.Factory.StartNew(ReadKeys);
var keyProcessingTask = Task.Factory.StartNew(ProcessKeys);
_stopEvent.Wait();
keyReaderTask.Wait();
keyProcessingTask.Wait();
}
public static void ReadKeys()
{
while (true)
{
var keyInfo = Console.ReadKey(true);
if (keyInfo.Modifiers == ConsoleModifiers.Control && keyInfo.Key == ConsoleKey.C)
{
break;
}
_keypresses.Enqueue(keyInfo);
}
_stopEvent.Set();
}
public static void ProcessKeys()
{
while (!_stopEvent.IsSet)
{
if (!_keypresses.IsEmpty)
{
Console.Write("Keys: ");
ConsoleKeyInfo keyInfo;
while (_keypresses.TryDequeue(out keyInfo))
{
Console.Write(keyInfo.KeyChar);
}
Console.WriteLine();
}
_stopEvent.Wait(1000);
}
}
}
}