Automating a PC to behave as a TV

Background

My Bulgarian grandparents had nothing to do all day after moving in with us, so my dad bought a subscription to watch Bulgarian TV over the internet. However, my grandparents are very old and can’t use computers at all – you can’t just say “oh just double click it” because they can’t even move the mouse effectively. So I decided to see if I can make it possible to connect the PC to the TV and automate it so that they don’t have to do anything other than turn it on.

First attempt

The connection was simple – the TV had a VGA port and an audio input so I just connected it like a monitor and speakers.

Automating the boot sequence was a bit more complicated, still easy. I initially set it up like this:

  1. The PC turns on
  2. Chrome turns on and opens the page with an embedded video
  3. Chrome is redirected to the login page
  4. LastPass automatically logs in
  5. Chrome is back to the video and loads it
  6. An autoit script that was run on startup slept 20 seconds from start up and now double clicks the video to make it full screen
  7. Tada!

This wasn’t enough for me though. They could only watch one channel, but there were 22 others that the site offered. It would be a waste of money to pay for all of them and not be able to watch them. So I looked into how I can make autoit change channels.

Second attempt

I realized that autoit can be used for a lot more than double clicking, so I embarked on a 3 hour journey into the mess and madness that is autoit scripting. It seems similar to Visual Basic, but then again, I’ve never used visual basic. Initially I started writing some really barbaric code, but as time went on I got pretty disgusted with my code and made it more compact and robust. Initially I tried making autoit trigger on regular key presses of the buttons 0-9, q-p, a-s. That ended badly because the events triggered by these buttons had to type in the url of the next video. That triggered more events and it got into an infinite loop. Apparently there are ways around it, but I didn’t find a reliable one and ended up using ctrl+button rather than just the buttons.

Now I had a way to choose one of the 22 channels by just pressing ctrl + the number or letter! I showed it to my grandparents in that state and my grandfather refused to touch it and my grandmother was confused about how to hold ctrl. So, I needed a mechanism like on the remote to change go to the next or previous channel. I assigned the INSERT and HOME keys to do that because they were beside each other and the labels didn’t mean anything for my grandparents. My grandmother seemed to hold the button for too long when she presses it so I had to make sure it doesn’t trigger again. I think that worked relatively well. At the end I had a pretty good script that works on a few assumptions:

  • LastPass is set up to log in automatically
  • chrome is used
  • the title of the page is “www.djTacho.com”
  • the urls of the channels won’t change
  • the wireless turns on as soon as the pc turns on
  • chrome is the default browser
  • chrome is always full screen
  • buttons are not pressed too fast one after the other

It seems like a long list now that I wrote it out. I’m considering making a JavaScript page that uses an iframe to load the video, which will significantly reduce the chances of the whole thing breaking. I’ll still need the autoit script to make it full screen though.

This is the final script:

Local $channels[128]
;These correspond to the ascii codes of their shortcuts
$channels[48] = "DIEMA";0
$channels[49] = "";1
$channels[50] = "NOVA";2
$channels[51] = "BTV";3
$channels[52] = "PROBG";4
$channels[53] = "KANAL3";5
$channels[54] = "PLANETA";6
$channels[55] = "DIEMA2";7
$channels[56] = "DIEMAFAMILY";8
$channels[57] = "FOXLIFE";9
$channels[113] = "RINGBG";q
$channels[119] = "TV7";w
$channels[101] = "BTVCOMEDY";e
$channels[114] = "NG";r
$channels[116] = "EUROSPORT";t
$channels[121] = "BTVCINEMA";y
$channels[117] = "TVPLUS";u
$channels[105] = "NOVASPORT";i
$channels[111] = "for-kids";o
$channels[112] = "filmi";p
$channels[97] = "chalga";a
$channels[115] = "pop";s
Local $bound
Local $url = "http://www.djtacho.com/members/tv.php?id="
Local $default_channel = '1'
Local $keys[22] = ['1','2','3','4','5','6','7','8','9','0','q','w','e','r','t','y','u','i','o','p','a','s']
Local $current = $default_channel
Local $pause = False


;wait for the page to open
Run(@Comspec & " /c start " & $url & $channels[Asc($default_channel)])
WinWaitActive("www.djTacho.com - Google Chrome")
Sleep(3000)
ToggleFullscreen()

BindHotKeys()

Func NextChannel()
  ;this stop working at the end anyways so that's good enough
  $found = False
  For $key In $keys
    If $found Then
      ChangeToChannel($key)
      $found = False
      ExitLoop
    EndIf
    If $key == $current Then
      $found = True
    EndIf
  Next
  If $found Then
    ChangeToChannel($keys[0])
  EndIf
EndFunc

Func PrevChannel()
  If $current <> $keys[0] Then ;stop at the beginning
    $last = $keys[0]
    For $key In $keys
      If $key == $current Then
        ChangeToChannel($last)
        ExitLoop
      EndIf
      $last = $key
    Next
  Else
    ChangeToChannel($keys[21])
  EndIf
EndFunc

Func ProcessKey()
  ChangeToChannel(StringTrimLeft(@HotKeyPressed, 1))
EndFunc

Func ToggleFullscreen()
  MouseClick("left", 250, 250)
  MouseClick("left", 250, 250)
EndFunc

Func GoToURL($url)
  MouseClick("left", 700, 700)
  Send("{F6}")
  Send($url)
  Send("{ENTER}")
EndFunc

Func ChangeToChannel($channel)
  If Not $pause Then
    $pause = True
    $current = $channel
    ToggleFullscreen()
    GoToURL($url & $channels[Asc($channel)])
    Sleep(2000)
    ToggleFullscreen();on
    $pause = False
  EndIf
EndFunc

Func BindHotKeys()
  For $key in $keys 
    HotKeySet("^" & $key, "ProcessKey")
  Next
  HotKeySet("{HOME}", "NextChannel")
  HotKeySet("{INSERT}", "PrevChannel")
  HotKeySet("{SPACE}", "ToggleFullscreen")
  HotKeySet("{PAUSE}", "ToggleBindings")
  $bound = True
EndFunc

Func UnbindHotKeys()
  For $key in $keys 
    HotKeySet("^" & $key)
  Next
  HotKeySet("{INSERT}")
  HotKeySet("{HOME}")
  HotKeySet("{SPACE}")
  $bound = False
EndFunc

Func ToggleBindings()
  If $bound Then
    UnbindHotKeys()
  Else
    BindHotKeys()
  EndIf
EndFunc

While 1
  ;
WEnd

PS: I made spacebar toggle fullscreen. That way if something breaks, they can try to fix it by pressing space. Somehow I doubt they’ll remember that, but it’s worth a try.

PPS: If anyone knows how to get the length of an array, please tell me. Then I wouldn’t have to hardcode “21” on line 68.

Best spam/advertising bot ever

I wouldn’t be surprised if someone has already done this, but I came up with this after seeing so many bots trying to troll me unsuccessfully.

  1. Make a chat bot
  2. Take a whole bunch of chat histories (parse them with regex magic and put them in a db?)
  3. Use the first line of a random conversation as a conversation starter for your bot
  4. Every time the user says anything, find the closest match in the conversation histories and use the response given there; if there is nothing even close, use a random line
  5. Eventually provide the user with a link to your site
  6. Check if the user clicked on the link and optionally how long he stayed on your site
  7. Save each successful conversation as a new conversation and discard each failure to persuade the user to click on the link; optionally increase the weight of the lines used in proportion to how long the user stayed on the site
  8. The better responses will start being used more often
  9. ???
  10. Profit!

Downloading torrents by text message

Inspiration

I was often stranded on a bus or somewhere else without wifi and wished I could start a torrent download before I forget to do it. I needed a way to use my cell phone to do it without having access to the internet. Twitter is the best place I could think of which will provide me with a simple way of transcending from the world of SMS into the world of interwebz. So I wrote a little python script that connects twitter, demonoid.com and a torrent server.

Typical use case

  1. You need a torrent, let’s say “Paintings of Van Gogh Collection”
  2. You make sure your cell phone is connected to your twitter accounts so you can tweet through text messages
  3. You text twitter with “@torrenter download Paintings of Van Gogh Collection”
  4. The torrent server runs this python script periodically, checking for new messages directed at its twitter account (or any twitter account I guess)
  5. The torrent server sees a new request, searches demonoid for the most seeded torrent that is relevant and starts downloading it

The setup

(It’s assumed that you have a linux based server you want to control through your cell phone)

  1. Make a twitter account for your torrenter
  2. Set up your phone to tweet through text messages
  3. Put the python script below on your torrent server
  4. Configure the variables inside the script (demonoid username and password, download path and twitter username for the torrenter)
  5. Set up cron to run it periodically
  6. Set up your torrent client to load torrent files from the folder you chose to download the torrents to in the config

Edit: Demonoid seems to have changed their domain to demonoid.me, so if anyone wants to try this, see if just changing the domain will work. If not I guess you’ll have to figure it out yourself.

import urllib, urllib2, json, re, cookielib
urllib2.install_opener(urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.CookieJar())))

demonoid_user = ''
demonoid_password = ''
save_folder = ''
torrenter_twitter = ''

def torrenter_download(command):
    q = ' '.join(command[2:])
    listing = urllib2.urlopen('http://www.demonoid.com/files/?'+urllib.urlencode({
        'query' : q,
        'category' : 0,
        'subcategory' : 'All',
        'seeded' : 0,
        'external' : 2,
        'uid':0,
        'sort':'S',
    }))
    torrent = re.findall(r'<a href="([/a-zA-Z0-9]+)"><img src="/images/downbg.gif"', listing.read())[0]
    download = open(save_folder + q + '_' + str(torrent.rsplit('/')[4]) + '.torrent', 'wb')
    download.write(
        urllib2.urlopen('http://www.demonoid.com/account_handler.php',
            urllib.urlencode({
                'nickname' : demonoid_user,
                'password' : demonoid_password,
                'returnpath' : torrent
                })
        ).read()
    )
    download.close()

try:
    f = open(save_folder+'last_id.txt', 'r')
    last_id = f.read()
except:
    last_id = ''

results = json.loads(
    urllib2.urlopen('http://search.twitter.com/search.json', 
        urllib.urlencode({
            'q' : '@'+torrenter_twitter,
            'rpp' : 10,
            'result_type':'recent',
            'since_id':str(last_id)
        })
    ).read()
)['results']

for req in results:
    command = req['text'].rsplit(' ')
    commands = {
        'download' : torrenter_download,
    }
    try:
        commands[command[1]](command)
    except:
        pass

if len(results) > 0:
    f = open(save_folder+'last_id.txt', 'w')
    f.write(str(results[0]['id']))