Simple bot for browser based game - c#

I'm trying to create simple bot for a browser-based game. I was using GecoFX, it's perfect. I can do everything that I want with that library. (posting forms, getting values, clicking buttons etc. everything you want). Also I'm able to use proxy with GeckoFX too. But I'm having big trouble with this library. When you set proxy once, it's global. I mean you set a proxy and created 2 geckoFX controls, both of them using same proxy and same cookies. when geckoFX1 logins to game if you go to same URL with geckoFX2 the pages are same with geckoFX1. Because their profiles are same, using same cookies and proxies...
What should I do? Do you know another method to do my job?
Also geckoFX is open source project. Can I edit the proxy and profile properties to make them un-global?
This is how you set proxy:
Gecko.GeckoPreferences.User["network.proxy.ssl"] = txtIP.Text;
Gecko.GeckoPreferences.User["network.proxy.ssl_port"] = intPort;
Gecko.GeckoPreferences.User["network.proxy.type"] = 1;
Gecko.ProfileDirectory = ""; // That property stores cookies
And maybe I can edit and make this like:
geckoWebBrowser1.Preferences.User["proxy"] = IP;
geckoWebBrowser1.Preferences.User["proxy"] = Port;
geckoWebBrowser1.Preferences.User["proxy"] = IP;
geckoWebBrowser1.PorfileDir = ""
Please don't reply like "yes, you can". Of course I can, I already know that but how? Where should I edit?

Create a class that does what you want it to do, then make 2 objects based on that class. This way, you can isolate them and they won't affect each other anymore. Then, in your main() method, initialize both of them:
pseudocode:
GeckoContainer gkc1 = new GeckoContainer(127.0.0.1, 1142);
GeckoContainer gkc2 = new GeckoContainer(127.0.0.1, 1123);
gkc1.Start();
gkc2.Start();
or whatever.
You have to implement the class by yourself.

Related

sending and retrieving data to API

I have a solution with 2 projects:
Contains the API
the module where i can select data (combobox etc...)
in the second module i select the API as reference that way i should be able to use data from the first module (my API) using Mollie.Api;
The First thing i want to do is fill a combobow with all the issuers, they should be in issuers.data:
Issuers issuers = mollieClient.GetIssuers();
foreach (Issuer issuer in issuers.data)
{
comboBox1.Items.Add(issuer.name);
}
the problem i have is: mollieClient does not exist in current context
i want to fill another combobox with methods but when i try to do it how they say i should do it doesnt work:
Method methods = new Method();
methods = Mollie.Api.Method.all();
however when i do:
Mollie.Api.Method.* the helper gives me then all the possible methods at *, but how can i get them automaticly in my combobox?
The second thing is when the method and issuer is selected i want to send that data back to the API. The API should be able to proces this and send me a message back that the transaction was a succes.
It appears like you're using mollie-api-csharp. You've written mollieClient, but according to the source Mollie.Api.MollieClient should start with a capital letter.
EDIT: Looks like you're following the how-to-use tutorial from the repo.
I think you forgot to create the MollieClient instance before getting the issuers.
MollieClient mollieClient = new MollieClient();
mollieClient.setApiKey("your_api_key_here");

Where to store global settings for my SPItemEventReceivers?

I have a SPItemEventReceiver that does nothing else than notify another HTTP server at a given IP and Port abouth the events using POST requests.
The HTTP server runs on the same computer as sharepoint, so I used to send the notification at localhost and a fixed Port number. But since the eventreceiver can be called in other servers in the serverfarm, localhost:PORT will not be available then.
So, everytime my HTTP server starts, it needs to save its IP address and Port somewhere in SharePoint where all EventReceivers have access, no matter on what server they are called.
What would be a good place to store such globally available information?
I tought about SPWebService.ContentService.Properties , but I'm not really sure if that's a good idea. What do you think?
Well, if you are using Sharepoint 2010 I would consider store those values in the property bag. Using client object model or even Javascript/ECMAScript Client Object Model. These codes maybe help you.
using (var context = new ClientContext("http://localhost"))
{
var allProperties = context.Web.AllProperties;
allProperties["testing"] = "Hello there";
context.Web.Update();
context.ExecuteQuery();
}
Or using javascript:
function getWebProperty() {
var ctx = new SP.ClientContext.get_current();
var web = ctx.get_site().get_rootweb();
this.props = web.get_allProperties();
this.props.set_item(“aProperty”, “aValue”);
ctx.load(web);
ctx.executeQueryAsync(Function.createDelegate(this, gotProperty), Function.createDelegate(this, failedGettingProperty));
}
function gotProperty() {
alert(this.props.get_item(“aProperty”));
}
function failedGettingProperty() {
alert("failed");
}
Sources:
https://sharepoint.stackexchange.com/questions/49299/sharepoint-2010-net-client-object-model-add-item-to-web-property-bag
https://www.nothingbutsharepoint.com/sites/devwiki/articles/Pages/Making-use-of-the-Property-Bag-in-the-ECMAScript-Client-Object-Model.aspx
There are actually several ways of saving configuration values in SharePoint:
Property Bags of SharePoint objects SPWebApplication, SPFarm,SPSite, SPWeb, SPList, SPListItem`
A "configuration" list in SharePoint - just a regular list you might set to Hidden = TRUE
The web.config file - specifically the <AppSettings>
Wictor Wilen actually explains the 6 ways to store settings in SharePoint.
As you are talking about an external process trying to save its settings somewhere, generally I would recommend the web.config, but each change in the web.config would lead to an IISRESET making it not a good option. I would strongly advise to use either a property bag (e.g. the SPWebApplication.Properties bag) or a hidden list in your favorite web site. You would set the property bag like so:
SPWebApplication webApplication = ...
object customObject = ...
// set value in hashtable
webApp.Add("MySetting", customObject);
// persist the hashtable
webApp.Update();
See what is cool about this? You can actually store an object with the web application which could contain multiple settings as long as you keep your object serializable.

What would be considered the best way to architect sending email from a C# web application?

I am working on a web application that will be going live soon, and I am now trying to figure out the best way for handling sending email from the application. I understand completely HOW to send email from the application using the MailMessage and SmtpClient classes, however my question is from a different angle. My main purpose at my job before this project was support of old applications that had been developed before my time. In these applications, when they needed to send email, they hard coded any of the messages into the actual message with all of the HTML tags embeded directly into the C# code.
The application that I am working on will have a template for the emails to be sent in, as a sort of styling container, and the different messages will be embeded into the main content div's of the template. I would like to avoid hardcoding these templates in this application, so I have been trying to figure out the best way to layout my project. I have thought of using a t4 template, and reading the different t4's into the application and applying a String.Format with the specified parameters to add names/emails to the messages to be sent. However, I am not sure this is the best way to do it.
My other idea was to define a class for each type of message, however this would end up hardcoding messages again, which as I said I don't want to do.
My question is, how have you approached this in the past? What worked, and what didn't and for what reasons? I have looked all over online, but either the only content out there is on HOW to send the message, or I have not used the right Google power words.
I do it this way:
Code it the usual way with ViewModel and Razor Template
By creating the e-mail, use http://razorengine.codeplex.com/ to load and parse the template
Be aware to not use Html and Url helper if you want to send e-mails in a thread, because they rely on HttpContext which you don't have in that case. Build your own helpers if needed.
For example, if you have a ViewModel Car in your application which is displayed somewhere, you could also use this ViewModel as #model in a Razor Template for e-mail.
I've had to do this on a couple of occasions. I originally used the ASP.Net template engine based on I think a Rick Strahl blog post. It worked but there was always some issue I was banging my head against.
I switched to using the NVelocity template engine and found it a really simple way to create and maintain email templates. There are a number of other template engines and I suspect next time I might have a serious look at the Razor engine.
The code for merging values into the template:
private string Merge(ManualTypeEnum manualType, Object mergeValues)
{
var body = "";
var templateFile = string.Format("{0}MailTemplate.vm", manualType);
var velocity = new VelocityEngine();
var props = new ExtendedProperties();
props.AddProperty("file.resource.loader.path", Config.EmailTemplatePath);
velocity.Init(props);
var template = velocity.GetTemplate(templateFile);
var context = new VelocityContext();
context.Put("Change", mergeValues);
using (var writer = new StringWriter())
{
template.Merge(context, writer);
body = writer.ToString();
}
return body;
}
The values to merge are passed as an anonymous object, and can include various types including lists etc e.g.
var emailBody = Merge(newDocument.ManualType, new
{
ManualType = newDocument.ManualType.ToString(),
Message = change.Message,
NewTitle = newDocument.Title ?? "",
NewVersion = newDocument.Version ?? "",
Contact = From,
Changes = change.ToList(),
});

Grabbing Cookies in Web Browser Control - WP7

In order to log into a certain part of a website the users of my application require their cookie. To do this I need to grab it and pass it to url.
Does anyone know how to grab a certain websites cookie from the browser control?
I saw this method but wasn't quite clear.
Thanks, TP.
As of WP 7.1 Mango "release", if one may call it, please see the WebBrowser Control Overview for Windows Phone. It has been recently updated a little bit, and it turns out that they actually have added some support for cookie-retrieval from the WebBrowser. On the bottom of the page you will find a tiny link GetCookies(WebBrowser) pointing to description of a new class: WebBrowserExtensions with this very handy method. Yes, this class has only that one single member. It's an extension method, I suppose no explanations needed on that.
I have not played with this method much, but it seems that this will allow you to access the very same thing as the JS trick: the cookieset for the current URL. It probably will not allow to set anything, nor to peek cookies for other URLs. Maybe if you play hard with the CookieContainer you will receive, but I doubt.
On the 7.0 release, I've been struggling quite hard to achieve "cookie transparency" for my App. Long story short, my app was doing some background HTTP requests, and also had a WebBrowser to show some online content -- and "it would be great" if both sources of connections would emit the same cookies to the server.. And guess what, my application had to make the first request, then let the browser navigate. With such requirements, there was virtually is no way to achieve consistency of the cookies - bah, even with the current new and glorious GetCookie method, I suppose it would be damn hard. So, to the point - it was possible, but needed to use some hidden API, that is present publicitly on the Phone, but is hidden in the SDK. The API is available the (public) class System.Net.Browser.WebRequestCreator, freely available. The quirk is: in the SDK this class has a single public static property "IWebRequestCreate ClientHttp" with a method "Create" that you can use to "factory" your "raw http" connections - in case you dont want to use the WebClient for some reason. On the phone, and on the emulator, there is a second public static property called "IWebRequestCreate BrowserHttp", easily returned by Reflection:
PropertyInfo brwhttp = typeof(System.Net.Browser.WebRequestCreator)
.GetProperty("BrowserHttp")
with this property, you will be able to obtain a "special" internal instance of IWebRequestCreate that is used internally by the WebBrowser. By opening your background HTTP requests with this class, you will get your cookies automatically set as if they were created/sent by the WebBrowser control, but in turn - you will NOT be able to modify http headers, userprovide http user authentication and neither do a few lowlevel things - because all that settings will be synced with the WebBrowser's data stored for current 'system user instance', if I'm allowed to call it as such on the single-user Phone device heh. The interoperation between connections and the WebBrowser works both ways - if your HTTP connection (created with use of the 'hidden property') receives any settings/cookies/etc -- then the WebBrowser will instantly notice them and update its own cache. No cookie/session loss on neither of the sides!
If you need to passively get cookies for your subsequent connections after some first WebBrowser navigation - please use the GetCookie or the JS way.
But if you need your code to be first, and then pass authz to the WebBrowser -- you will probably have to dig deeper and use the above.. It's been hidden, so please resort to the other means first!
..and don't ask me how did I found it or how much time it took :P
have a nice fun with it
//edit: I've just found out, that the BrowserHttp property is a normal Silverlight's way to access the Browser's connection factory, please see BrowserHttp. It seems that it is only has been hidden in the 'miniSilverlight' written for the WP7 platform!
The approach being described in the post you linked is to use the WebBrowser control's InvokeScript method to run some javascript. However the post appears to use a "cookies" collection which doesn't actually exist.
string cookie = myWebBrowser.InvokeScript("document.cookie") as string;
Now for the hard part the string you get contains all pertinent cookie name/value pairs for the page with the values still being Url encoded. You will need to parse the returned string for the value you need.
See document.cookie property documentation.
Edit:
Looking at it fresh instead of relying on the post, InvokeScript invokes named function on the window of the host browser. Hence the page being displayed in the WebBrowser would itself need to include a function like:-
function getCookie() { return document.cookie; }
Then the InvokeScript would look like:-
string cookie = myWebBrowser.InvokeScript("getCookie");
As #quetzalcoatl already suggested, you can use internal instance of WebRequestCreator to share cookies between browser instances and instances of WebRequest. You don't get to access the cookies directly though, I think that's just a security measure by Microsoft.
This code below creates a WebReqeust object, connected to CookieContainer of WebBrowser instance. It then posts to a url to log in the user and store cookies in the container.
After it's done, all browser instances within the app instance will have required set of cookies.
var browser = new WebBrowser();
var brwhttp = typeof (WebRequestCreator).GetProperty("BrowserHttp");
var requestFactory = brwhttp.GetValue(browser, null) as IWebRequestCreate;
var uri = new Uri("https://www.login.com/login-handler");
var req = requestFactory.Create(uri);
req.Method = "POST";
var postParams = new Dictionary<string, string> {
{"username", "turtlepower"},
{"password": "ZoMgPaSSw0Rd1"}
};
req.BeginGetRequestStream(aReq => {
var webRequest = (HttpWebRequest)aReq.AsyncState;
using (var postStream = webRequest.EndGetRequestStream(aReq)) {
// Build your POST request here
var postDataBuilder = new StringBuilder();
foreach (var pair in paramsDict) {
if (postDataBuilder.Length != 0) {
postDataBuilder.Append("&");
}
postDataBuilder.AppendFormat("{0}={1}", pair.Key, HttpUtility.UrlEncode(pair.Value));
}
var bytes = Encoding.UTF8.GetBytes(postDataBuilder.ToString());
postStream.Write(bytes, 0, bytes.Length);
}
// Receive response
webRequest.BeginGetResponse(aResp => {
var webRequest2 = (HttpWebRequest) aResp.AsyncState;
webRequest = (HttpWebRequest)aResp.AsyncState;
string resp;
using (var response = (HttpWebResponse)webRequest2.EndGetResponse(aResp)) {
using (var streamResponse = response.GetResponseStream()) {
using (var streamReader = new System.IO.StreamReader(streamResponse)) {
resp = streamReader.ReadToEnd();
}
}
}
}, webRequest);
}, req);
One of the issues I couldn't solve though was exceptions thrown when server returns 302 - it seems to throw WebException error with "Not found" description.
// Ensure this is set to true BEFORE navigating to the page
webBrowser1.IsScriptEnabled = true;
// Once the page has loaded, you can read the cookie string
string cookieString = webBrowser1.InvokeScript("eval", new string[] { "document.cookie;" }) as string;
The cookieString variable will contain the full cookie for the document. You can then parse the string.
There is an WebBrowser Extension class which is exactly developed for this:
CookieCollection tempCookies = Microsoft.Phone.Controls.WebBrowserExtensions.GetCookies(this.BrowserControl);

Help With Proxy Username & Pass with GeckoFX?

I am trying to set the proxy username and password. I saw this posting (http://geckofx.org/viewtopic.php?id=832) and I thought it might be a similar setting for the username/password, such as :
Skybound.Gecko.GeckoPreferences.User["network.proxy.user"] = (user);
Skybound.Gecko.GeckoPreferences.User["network.proxy.password"] = (password);
But, nothing has worked so far. Can anyone help? I would really appreciate it!!!
I am using VB.net if that helps. Thanks!!
You probably need to set proxy type to 1.
To detect proxy settings automatically, try this:
Uri website = new Uri("http://stackoverflow.com");
System.Net.IWebProxy defaultproxy = System.Net.WebRequest.GetSystemWebProxy();
Uri proxy = defaultproxy.GetProxy(website); //no actual connect is done
if (proxy.AbsoluteUri != website.AbsoluteUri) {
Skybound.Gecko.GeckoPreferences.User["network.proxy.http"] = proxy.Host;
Skybound.Gecko.GeckoPreferences.User["network.proxy.http_port"] = proxy.Port;
Skybound.Gecko.GeckoPreferences.User["network.proxy.ssl"] = proxy.Host;
Skybound.Gecko.GeckoPreferences.User["network.proxy.ssl_port"] = proxy.Port;
Skybound.Gecko.GeckoPreferences.User["network.proxy.type"] = 1;
//0 – Direct connection, no proxy. (Default)
//1 – Manual proxy configuration.
//2 – Proxy auto-configuration (PAC).
//4 – Auto-detect proxy settings.
//5 – Use system proxy settings (Default in Linux).
}
You're trying to set them among the settings. You can access all available settings by typing about:config in the firefox addressbar, and there is no user or password setting there. I assume this is because the usernames and passwords needs to be stored securely.
I think that if you leave them unset when you try to connect to the proxy it'll ask you for them and then store them somewhere secure, and it will then use that username and password automatically.
If you do need to store them manually, I'd suggest that it might be worth to look at the Password Manager, maybe GeckoFX supports some way of accessing that?

Categories