Hackaday Unleashes A Troll Sniffing Rat

Sometimes we like to take a few minutes away from Hackaday to spend time with our families. But just when you take your eyes off of the incoming comments, Trolls are bound to strike. Well, [Caleb] and I found a solution to the problem in the form of a troll sniffing rat. This beady-eyed vermin sits on my desk and waits. When a trolling comment is detected its eyes glow red and an alarm is sounded. Join us after the break for more about this silly project.


To pull this off I need a few things to happen. First, a way to parse our incoming comments. That’s easy, we use WordPress as our content management system and that means there’s already an RSS feed for global comments. I just need to grab that data and traverse the comment authors for known trolls (who haven’t been banned). That’s not hard to do with a Python script, especially if you take advantage of the Beautiful Soup module which sanitizes and navigates HTML and XML. My script checks the feed every two minutes, stores the number that identifies each comment so as not to have duplicate alarms, and makes decisions based on the author of that comment. A simple list of usernames is used to search for trolls, but it could be used just to notify whenever one of your favorite readers leaves a comment. The script then records a message on the standard output, and sends a coded command via a serial connection.

Here’s what the terminal output looks like:

And here’s the Python script:


trolls = [ 'Mike Szczys' , 'Caleb Kraft' ]
signalAllComments = True
signalAllAudibly = False

import urllib2, time, serial
from BeautifulSoup import BeautifulSoup

#start a list of comments to prevent duplicate alerts
dupe = []

#setup Arduino communications
ser = serial.Serial('/dev/ttyUSB0', 9600)


#get list of comment identifiers
while True:

  #Reset Arduino from the last trigger

  #Get the comments
  html = urllib2.urlopen("http://hackaday.com/comments/feed").read()
  soup = BeautifulSoup(html)

  #Check each one
  for item in soup('item'):
      thisID = item('guid')[0].string.split('comment-')[1]

      if thisID not in dupe:
              #Add to the duplicate list for next time

              #Convert post time to local time
              postT = item('pubdate')[0].string
              parsedT = time.strptime(postT, "%a, %d %b %Y %H:%M:%S +0000")
              offsetT = time.mktime(parsedT) - time.timezone
              localPostTime = time.strftime("%m/%d/%y %H:%M:%S", time.localtime(offsetT))

              #Check if this is a post we're watching
              author = item('dc:creator')[0].string
              if author in trolls:
                  print "(" + localPostTime + ") Troll Alert: " + author + " just posted a comment"
                  print "    " + item('guid')[0].string
              elif signalAllComments:
                  print "(" + localPostTime + ") New Comment from: " + author
                  print "    " + item('guid')[0].string
                  #audible signal?
                  if (signalAllAudibly):



Next, I needed a way to sound the alarm when the parsing script identifies a troll. In my mind the easiest/quickest way to develop hardware connected to a computer is to use an Arduino connected via USB. I have an Arduino that I’ve never actually used for a project so I thought this would be a great start. I dug up a piezo buzzer and some LEDs and started looking around to see what code examples I could repurpose.

I found a post on making music using a piezo buzzer, so I altered that code to make the sounds I desired. I also looked at the serial communication examples that come with the Arduino IDE to get communications up and running. Like I mentioned above, I’m sending an ASCII char via serial connection from my Python script. The sketch below just looks for those chars and acts accordingly. I can make the hardware light the LEDs and play a bad sound when ‘A’ is received. It plays a good sound and does nothing with the LEDs when ‘B’ comes through. Any other letter turns the LEDs off, which is what the Python script uses to reset the LEDs two minutes after the last troll alert.

//Piezo code from:

void setup() {
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

#define PIEZO_PIN 8
// defines for the frequency of the notes (.5 x freq of mid C)
#define AN    220     // 440 Hz
#define AS    233     // 466 Hz
#define BN    247     // 493 Hz
#define CN    261     // 523 Hz
#define CS    277     // 554 Hz
#define DN    294     // 588 Hz
#define DS    311     // 622 Hz
#define EN    330     // 658 Hz
#define FN    349     // 698 Hz
#define FS    370     // 740 Hz
#define GN    392     // 784 Hz
#define GS    415     // 830 Hz
// defines for the duration of the notes (in ms)
#define wh    1024
#define h      512
#define dq     448
#define q      256
#define qt     170
#define de     192
#define e      128
#define et      85
#define oo7      1    // 007 jingle


void play_tune(int tune){               // play a tune . . .
  switch (tune) {                       // a case for each tune
  case 1:
    for (unsigned char i=0; i<4; i++)
  case 2:

void ToneOut(int pitch, int duration){  // pitch in Hz, duration in ms
  int delayPeriod;
  long cycles, i;

  //pinMode(PIEZO_PIN, OUTPUT);           // turn on output pin
  delayPeriod = (500000 / pitch) - 7;   // calc 1/2 period in us -7 for overhead
  cycles = ((long)pitch * (long)duration) / 1000; // calc. number of cycles for loop

  for (i=0; i<= cycles; i++){           // play note for duration ms
    digitalWrite(PIEZO_PIN, HIGH);
    digitalWrite(PIEZO_PIN, LOW);
    delayMicroseconds(delayPeriod - 1); // - 1 to make up for digitaWrite overhead
  //pinMode(PIEZO_PIN, INPUT);            // shut off pin to avoid noise from other operations

void loop() {

  if (Serial.available() > 0) {
    int inByte = Serial.read();
    // do something different depending on the character received.
    // The switch statement expects single number values for each case;
    // in this exmaple, though, you're using single quotes to tell
    // the controller to get the ASCII value for the character.  For
    // example 'a' = 97, 'b' = 98, and so forth:

    switch (inByte) {
    case 'a':
      digitalWrite(7, HIGH);
    case 'b':
      digitalWrite(7, LOW);

The final piece of the puzzle was to put two red LEDs inside of a plush rat that we had lying around the house. The eyes were embroidered so I clipped the LED leads at an angle to make then sharp enough to pierce through to the inside. I used a Dremel sanding drum to make the clear LED package cloudy and to shave off most of the extra plastic. I then used a couple of KK connector patch wires I had around to attach to the leads on the inside of the rat head. After removing the stuffing from the body I pushed the connector all the way on and then bent the leads over the connectors. There’s picture of this below, but without the leads bent.

I restuffed the rat and stapled up the seam that I cut open to do the work. I love the outcome. It’s clearly audible throughout the house, and I had fun along the way.

It turns out that an $8 webcam and an Ubuntu box don’t make up a great video setup. But if you must see a demonstration, here it is:

Follow me on Twitter


79 thoughts on “Hackaday Unleashes A Troll Sniffing Rat

  1. Now that is nicely done. THAT is what a HAD post is supposed to look like. Complete, Concise, all the info is there and well laid out unlike the Fake posts that have just a picture that was probably photo-shopped.

    Remember kiddies, full disclosure of how and what you did or you faked it.

    THIS is what you do as a HAD post- Bravo!

  2. I did look at the python just now. My main worry would be the list “dupe”. I don’t know how many comments HAD gets per period of time, or how long this script is intended to run, but I guess as the list fills the system performance may become affected?

    It might be a good idea to put some kind of counter on there that resets it at a predefined point. Or to reset the list at the start of every day using the information from post times.

  3. As one of the co-creators of the original Trolldetektor 1.0b

    I would like to point out, -that even if Sea-lions and Lions share the same name, both of them are not capable to bite your head of. They are not even related as species.

    This misunderstanding, that the phenomena Internet trolls are being real Trolls are in a conservation point of view troublesome. Because as you perhaps know, Trolls are very rare, even perhaps near extinction. The trolly creatures on the net on the other hand….

    So support your local WTF, World Trolllife Foundation, and help bringing this message out! As we all know, nature is you me, and everybody. So please take lovingly care of it.

    PS, Nice project! Perhaps some kinetics in the rats whiskers when bad language are detected? Flexinol wires are perhaps cool to use.

    Sincerely yours,
    Stig | Nullohm

  4. Big brother’s watching… He has the face of a rat and the mind of a python.
    AFAIK, there’s only one way to kill a troll sniffing rat, and that’s with a bad grammar sniffing cat. Of course, grammar cats aren’t too smart and can’t actually detect bad grammar. Like troll rats, they merely assume the prejudices of their creators.
    Sure, there may be some collateral damage, but all is fair in love and flame-war.

  5. While a simple/kind of boring hack, I really LOVE the detail Hackaday puts into their writeups. Half the hacks skip huge steps in their writeup or (as a SENG this kills me most) don’t post the source code.

  6. -Not a hack!
    -It has an Arduino blinking LEDs…
    -It should’ve been done differently…
    -Arduino is overkill…
    -You could’ve used a couple of 555s…
    -Nooo!!! Arduino!!….

    Did I miss any of the filter phrases? :D
    Did the rat go crazy? :D

    Nice project!

  7. Hmmm, I am known all over the internut but I bet the rat doesn’t light up on my comment.
    I am quite infamous, having been on computer chat since 1983.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.