onlinecklicker-bot

This is a small WPF/C# project to annoy our professor. Accidentally, he is the one who created OnlineClicker.org.

I like his lectures. You don't feel like a idiot listening to his stuff. It's entertaining and you can hear, that the likes what he does.

But: Sometimes it's funny to annoy people.

Disclaimer!

You are using this program at your own risk. Please be gentle and do not overuse it. After all, you are probably using OnlineClicker.org in a lecture!

Contents

Using it

This is a WPF/C#/.NET solution. It's using .NET Framework 6.2 and WPF. If you want to use it, you need to compile it yourself.

I will not provide a pre-build version! I want to prevent the overuse of this bot!

Everything else is simple. Run it, enter a poll number and click a few buttons.

You can add additional votes by clicking on one of the ProgressBars/answers.

Screenshots

OnlineClicker and Bot

Balance Mode

Technical details

This project utilizes WPF running at .NET Framework 6.2. Almost all UI features are using the MVVM-Pattern. You can learn more about MVVM at https://learn.microsoft.com/en-us/dotnet/architecture/maui/mvvm (for MAUI but is also applies to WPF).

For people who understand German: Weitere Details sind bezüglich MVVM können der Dokumentation meiner Abschlussarbeit zum Anwendungsentwickler entnommen werden. Diese ist unter https://github.com/janwiesemann/WPF-Translate/tree/master/doc (Project documentation (German).pdf -> Seite 9 bzw. Seite 15 in der PDF.; Project presentation (German).pdf -> Folie 17) und https://it-berufe-podcast.de/projektdokumentation-von-jan-wiesemann-mit-98-bewertet/ bzw. https://it-berufe-podcast.de/projektpraesentation-von-jan-wiesemann-mit-96-bewertet/ zu finden.

Analyzing OnlineClicker.org

This Section describes, how I analyzed OnlineClicker.org and how I was abe to communicate with it.

All PHP-Code was written by Thorsten Thormählen and is released under the MIT License. You can find further details in the 'About' section on OnlineClicker.org.

Clicking

I clicked a few links, read some details and found this: The next section

Source Code

The software is open source and released under the MIT license (source code).

That's what I want to see! So I've downloaded it and continued.

Local testing/debugging

I didn't want to spam OnlineClicker.org server with all kinds of trash, while I was developing this. This is why I quickly spun up my local php environment. It's based on nginx, php 8.2 and most important: Xdebug.

There was only one issue: The downloaded source was missing a few minor things. Mainly jquery. I had to download it and then placed it in the corresponding directory. Now I was able to create, vote and view Polls.

Digging (a grave for our beloved hamster Chad :'( )

Sadly, our Hamster died. It was quite sad.

He was cute and fluffy.

His cuteness: https://www.reddit.com/r/Eyebleach/comments/xyo7my/hamster/

Digging (again)

clicker.php

is the 'main' file. It's providing a endpoint to all requests.

The first interesting part is:

// read post parameters
$poll = filter_input(INPUT_POST, 'pollNumber', FILTER_VALIDATE_INT);
$answers = filter_input(INPUT_POST, 'answersNumber', FILTER_VALIDATE_INT);
$requestType = filter_input(INPUT_POST, 'requestType', FILTER_VALIDATE_INT);

// check input
if (!$poll || !$answers || !$requestType) {
  die('Internal error: Wrong post format ' . ' poll=' . $poll . ' answers=' . > $answers . " requestType=" . $requestType);
}

As you can see, requests are stopped, as soo as one parameter is missing. Personally, I don't like this approach since it can lead to confusion down the road. But It reduces the complexity, since you only need one request for everything.

Next, we can see a few branches:

if ($requestType == "1") { // create poll
    [...]
}

if ($requestType == "2") { // get poll result
    [...]
}

if ($requestType == "3") { // get number of answer options
    [...]
}

if ($requestType == "4") { // vote
    [...]
}

As a C/C++ and C# person, this looks like a nightmare. Why are Integers compared to Strings? Why is this possible? Are they even Integers? Why isn't there a Enum date type? But anyways...

We now know what $requestType's exist and what they mean. I'm not digging deeper into it.

clicker.js

Yes, I don't like PHP and guess what, I don't like JS either. This is why I'm skipping it for now.

Web Inspector (or whatever it's called on other Browsers)

All 'modern' browsers contain a debugging feature. The often contain a feature, to see what requests are made and what kind of data is being send.

Now comes the hard part: Thinking. What do we need to know?

  1. I want to view how many votes a specific answer has gotten.
  2. I want to add new votes.

First, I'll create a new Poll and use it for testing: We need to create a new vote: OnlineClicker.org -> For speaker -> Admin -> Number = 2227; Options = 3;

Get number of votes

After you've created a Poll, you'r able to see the results. Let's take a look at the Network Inspector:

  1. Requests are being made to clicker.php. Thy contain POST date with these values:

    pollNumber: 2227
    answersNumber: 1
    requestType: 2
    

    The response is:

    Success:0 0 0 0
    

    Great... we still know noting and I'm not even John Snow! JSON would be nice...

  2. Let's open a new browser tab and add a vote. Our response now looks like this:

    Success:1 0 1 0
    

    ...

  3. Let's add another few votes:

    Success:3 0 2 1
    

Interesting. The first number seams to be the sum of the following numbers. This means, we have 3 total votes, 1: 0 votes, 2: 2 votes and 3: 1 vote.

Now we know how to read such responses.

Add vote

This shouldn't be as much thinking. Let's add a vote and see what kind of data is being send.

  1. The number of possible options is being looked up. The request contains these POST values:

    pollNumber: 2227
    answersNumber: 1
    requestType: 3
    

    If you take a look back at clicker.php you can see, that request type 3 is used for // get number of answer options. This should return the number 3 as a result, since we have a poll with 3 options.

    And it does:

    Success:3
    
  2. Let's add a vote to option 2:

    pollNumber: 2227
    answersNumber: 2
    requestType: 4
    

    I don't care about the response but this has added a new vote to option 2.

We now also know how to cast a vote.

Finally! I can stop looking at PHP and JavaScript.

WPF (finally!)

This is kind of simple, if you know how to C#. (Why do Java developers wear glasses? Because they can't C#)

The application utilizes the MVVM pattern. This means, almost no code connects the UI and the actual data.

If you want to see additional details, check out the source code. A quick view of all the files can be seen below.

Views

The V in MVVM

MainWindow.xaml

is a simple MetroWindow with a ContentControl. The Window uses the DataContext (ViewModel) MainWindowViewModel. It also defines Templates on how the ContentControl has to present a few different Types. This can then be used to implement a browser like navigation based on what type of data is presented.

WelcomeState.xaml

Presents the data of WelcomeState.cs.

ValidatePollNumberState.xaml

Presents the data of ValidatePollNumberState.cs.

ErrorState.xaml

Presents the data of ErrorState.cs.

PollState.xaml

Presents the data of PollState.cs. This will show a few ProgressBars and some text to present a poll. This also requires some additional components to work properly.

ToPercentageConverter.cs

Is used to convert the number of votes to a percentage.

DataContextProxy.cs

Is used to to access the DataContext of a overlaying Control. See https://code.4noobz.net/wpf-mvvm-proxy-binding/ for details.

ViewModels

The VM in MVVM

MainWindowViewModel.cs

is the ViewModel used in the MainWindow. It contains the Poll-Number and the current 'State' which is being presented. If this changes, the UI changes to present data for this Object.

PollStateBase.cs

is a base type which contains some basic information like the Poll-Number. It also contains the method .SendRequestAndGetResponse(RequestType type, int awnserNumber). This method handles all web requests and returns the result. The result is a List<int>. It contains all numbers from a response. A response (see Get number of votes or Add vote) is composed of a series of numbers.

WelcomeState.cs

is the initial State and presents the README.MDyou are reading.

ValidatePollNumberState.cs

is used to validate the entered Poll-Number. This then replaced with next State PollState.cs or ErrorState.cs.

ErrorState.cs

is used to show Exception's.

PollState.cs ('Main' interface)

is the 'Main' interface or at least it's date. It's used to present the current number of votes, refreshes it and submits additional votes.