Twtpoll auto voter

Just a short entry today on a fun little project I came across.  I had a friend that for “educational purposes” wanted to know how to write a little WPF program that would Auto Vote on a twtpoll poll that was enabled for a 24 hour period.

To plug twtpoll a little, it’s a pretty neat system.  It allows a user to simply fire up a poll and get it running with instant results rather quickly, and allows short urls with no login voting.  I like the system.

www.twtpoll.com

Normally, a project like this isn't worth of a blog, but primarily doing Silverlight development these days,I found myself using lots of skills that I hadn’t touched in a while, as a good refresher, it was kind of fun to hack through it.

Ok, so to get started, the tools I used:

Fiddler 2 : http://www.fiddlertool.com/fiddler/version.asp

IE 8 Developer Extensions

Visual Studio 2010: http://www.microsoft.com/visualstudio/en-us/visual-studio-2010-launch?CR_CC=100340688&WT.mc_id=SEARCH&WT.srch=1&CR_SCC=100340688

C# / .NET 4.0 / WPF

Really the .NET 4.0 and the WPF components aren’t required, a windows forms app using .NET 2.0 would have been fine, but why go backwards.

 

So my first step in this process, was to head out to the Polls URL and take a look at the HTML.  I did this using IE 8 and “View Source”  - IE 8 has a great html source viewer that allowed me to see we were using a typical form post method to submit the poll without any weird javascript callbacks or anything strange.

I’ve created a temporary poll just to test the application located here:

http://twtpoll.com/ov097x

Here we see the line of HTML we were looking for

image

 

Once we know that we can actually do the form post.  It’s time to fire up Fiddler, this gives us all the info we need to actually create our application to do the submission automatically.

image

Submitting the form out on twtpoll, we can see that we get a Fiddler response line of the form post.  This is exactaly what we were looking for, which exposes all the form variables that were submitted as part of the post.

Great, now on to our program!  Keep track of these form variables, you’ll need them when we do the FORM POST through our C# application

At this point, I fire up Visual Studio 2010 and open a brand new WPF project.

The meat of the project is accomplished in this little class, which is nothing new or revolutionary.  It wires up a new web request through the System.Net namespace, and uses some URL encoding to make sure there is no weirdness when adding the form variables to the post.

In this example the posting URL is hardcoded, but this could absolutely be configurable.

 public class WebPostRequest
    {
        WebRequest theRequest;
        HttpWebResponse theResponse;
        ArrayList theQueryData;
 
        public WebPostRequest(string url)
        {
            theRequest = WebRequest.Create(url);
            theRequest.Method = "POST";
            theQueryData = new ArrayList();
        }
 
        public void add(string key, string value)
        {
            theQueryData.Add(String.Format("{0}={1}", key, HttpUtility.UrlEncode(value)));
        }
 
        public string GetResponse()
        {
            theRequest.ContentType = "application/x-www-form-urlencoded";
            string Parameters = String.Join("&", (String[])theQueryData.ToArray(typeof(string)));
            theRequest.ContentLength = Parameters.Length;
 
            StreamWriter sw = new StreamWriter(theRequest.GetRequestStream());
            sw.Write(Parameters);
            sw.Close();
 
            theResponse = (HttpWebResponse)theRequest.GetResponse();
            StreamReader sr = new StreamReader(theResponse.GetResponseStream());
            return sr.ReadToEnd();
        }
 
 
    }

 

Once you’ve got this class implemented into your project, it’s pretty simple to utilize:  In my example I’ve enabled some threading to vote LOTS.  :)

Here’s the code behind the form.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AutoVoter.Members;
using System.Threading;
using System.Collections.ObjectModel;
 
namespace Voter
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        int voteCount = 0;
        ObservableCollection<Thread> threads;
        private delegate void UpdateTextBox(string newValue);
        UpdateTextBox textUpdate;
 
        public MainWindow()
        {
            InitializeComponent();
            threads = new ObservableCollection<Thread>();
            textUpdate = new UpdateTextBox(DoTextUpdate);
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }
 
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            lb1.ItemsSource = threads;
        }
 
        private void DoTextUpdate(string newValue)
        {
            this.Title = voteCount.ToString();
        }
 
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i <= 20; i++)
            {
                Thread t = new Thread(DoVote);
                t.Name = i.ToString();
                t.Priority = ThreadPriority.Normal;
                t.IsBackground = true;
                threads.Add(t);
                t.Start();
            }
        }
 
        private void DoVote()
        {
            while (true)
            {
                WebPostRequest myPost = new WebPostRequest(@"http://twtpoll.com/php/form_handler_20.php");
                myPost.add("1_am_id", "738051");
                myPost.add("1_q", "86107");
                myPost.add("2_am_id", "738056");
                myPost.add("2_q", "86110");
                myPost.add("3_am_id", "738054");
                myPost.add("3_q", "86109");
                myPost.add("4_am_id", "73057");
                myPost.add("4_q", "86111");
                myPost.add("s", "837");
                myPost.add("psi", "102409");
                myPost.add("tt", "edq0ru");
                myPost.add("sif", "0");
                myPost.add("qt", "0,0,0,0");
                myPost.add("rf", "0,0,0,0,0");
                Thread.Sleep(100);
                try
                {
                    myPost.GetResponse();
                    voteCount++;
                    Dispatcher.BeginInvoke(textUpdate, voteCount.ToString());
                }
                catch
                {
                    //Ignore the Exception
                }
            }
 
        }
    }
}
 
And finally, the least important part.  My horrendous UI, wired up specifically to get the job done, no more and no less:
 
<Window x:Class="Voter.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox Margin="0,0,0,90" x:Name="lb1" />
        <Button Margin="123,227,138,12" Content="Vote" Click="Button_Click" />
    </Grid>
</Window>

 

Have fun with this, good luck and happy coding,

 

Bryan

1 Comment

Comments have been disabled for this content.