# tivo proxy server



## ejonesss

i made some progress on the proxy server

http://www.tivocommunity.com/tivo-vb/showthread.php?t=490198

it turns there are some command changes in python 3.x that Allanon's post will not run.

i made the changes after much google work

unfortunately it looks like a windows thing because of the references to curl.exe so me on a mac it will not work.

i had to change the 192.168 to a 10.0 number since apple's time capsule is a network router too

however it seems to run and respond since i am getting

/download/U.S.%20Drug%20Wars.TiVo?Container=%2FNowPlaying&id=25139&Format=video/x-tivo-mpeg
http://10.0.1.5/download/U.S. Drug Wars.TiVo?Container=/NowPlaying&id=25139&Format=video/x-tivo-mpeg
127.0.0.1 - - [17/Nov/2012 15:43:46] "GET /download/U.S.%20Drug%20Wars.TiVo?Container=%2FNowPlaying&id=25139&Format=video/x-tivo-mpeg HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 57436)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/socketserver.py", line 306, in _handle_request_noblock
self.process_request(request, client_address)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/socketserver.py", line 332, in process_request
self.finish_request(request, client_address)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/socketserver.py", line 345, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/socketserver.py", line 666, in __init__
self.handle()
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/http/server.py", line 400, in handle
self.handle_one_request()
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/http/server.py", line 388, in handle_one_request
method()
File "/Users/<your user name goes here>/Downloads/Tivo Proxy Server.py", line 102, in do_GET
processID = findPID('curl.exe')
File "/Users/<your user name goes here>/Downloads/Tivo Proxy Server.py", line 15, in findPID
a = os.popen4('tasklist /FI "IMAGENAME eq '+exename+'"')
AttributeError: 'module' object has no attribute 'popen4'

import cgi, os, socketserver, sys, time, subprocess, urllib.request
from http.server import SimpleHTTPRequestHandler
from io import StringIO

# Modify these variables so the values reflect 
# your computer's and TiVo's IP and MAK address 
Tivo_MAK = 'xxxxxxxxxx'
Server_URL = '127.0.0.1'
Tivo_URL = '10.0.1.5'
Port = 10000

# Find the ProcessID of a running application
def findPID(exename):
a = os.popen4('tasklist /FI "IMAGENAME eq '+exename+'"')
a[0].flush()
try:
info=a[1].readlines()[3].split()
except:
info=[exename,"NotFound"]
return info[1]

# Get XML Now Playing List from TiVo and write a simple RSS feed 
# This probably should have used XMLLib but I made a quick hack to
# get the data from the Tivo XML file
def writeRSS(wfile):
global Server_URL
global Tivo_MAK
global Tivo_URL
global Port

#Get the XML Now Playing list from TiVo
link = 'curl --insecure --digest --user tivo:{0:s} "http://{1:s}/TiVoConnect?Command=QueryContainer&Container=%2FNowPlaying&Recurse=Yes&AnchorOffset=0"'.format(Tivo_MAK,Tivo_URL)
print( link)
XML = subprocess.Popen(link,shell=True,stdout=subprocess.PIPE)

# Write the RSS feed
wfile.write('<?xml version="1.0"?>\n')
wfile.write('<rss version="2.0">\n')
wfile.write('<channel>\n')
wfile.write('\tNow Playing List\n')

#parse data from TiVo XML 
data = XML.stdout.read()
b = 0
while True:
a = data.find('<Item>',b)
if a == -1:
break
b = data.find('</Item>',a)
b = b + 7
item = data[a:b]
wfile.write('\t<item>\n')
if item.find('') != -1:
wfile.write('\t\t' + item[item.find('')+7:item.find('')] + '\n')
if item.find('<EpisodeTitle>') != -1:
wfile.write('\t\t<episodetitle>' + item[item.find('<EpisodeTitle>')+14:item.find('</EpisodeTitle>')] + '</episodetitle>\n')
if item.find('<Description>') != -1:
wfile.write('\t\t<description>' + item[item.find('<Description>')+12:item.find('</Description>')] + '</description>\n')
if item.find(Tivo_URL) != -1:
wfile.write('\t\t<enclosure url="http://'+ Server_URL + ':' + str(Port) + item[item.find('/download/'):item.find('</Url>')]+ '"' + ' length="' + item[item.find('<SourceSize>')+12:item.find('</SourceSize>')] + '" type="video/mpeg" />\n')
wfile.write('\t</item>\n')
wfile.write('</channel>\n')
wfile.write('</rss>')
wfile.flush()

class Handler(SimpleHTTPRequestHandler):

def do_GET(self):
global Tivo_MAK
global Tivo_URL
global Port

print (self.path)

if self.path =='/rss':
# Send RSS feed
self.send_response(200)
self.send_header("Content-type", "text/xml")
self.end_headers()
writeRSS(self.wfile)
print( 'RSS Feed Send\n')
else:
 # Check if the self.path is a TiVo URL
if self.path.find('/download/') != -1:

# Create TiVo URL
link = 'http://' + Tivo_URL + self.path
link = link.replace(';amp','')
print( link)

# Send header 
self.send_response(200)
self.send_header("Content-type", "video/mpeg")
self.end_headers()

# Get and decode the Tivo file 
decode = subprocess.Popen('curl.exe --digest -k -c cookies.txt -u tivo:{0:s} "{1:s}" | tivodecode -m {0:s} -- -'.format(Tivo_MAK,link),shell=True,bufsize=0,stdout=subprocess.PIPE)
processID = findPID('curl.exe')

# Send decoded data to the client
while True:
chunk = decode.stdout.read(4096)
if not chunk:
break
try:
self.wfile.write(chunk)
except:
os.popen('TASKKILL /PID '+ processID +' /F')
time.sleep(1)
break

# Start Proxy Server
httpd = socketserver.TCPServer(("", Port), Handler)
print( "serving at port", Port)
httpd.serve_forever()

maybe someone on a mac can get it to work

note:

1. you need to change tivo url to what ever your tivo uses it will be based on your router most routers use 192.168 based numbers

2. the mak is a 10 digit number used for accessing the media

3. it seems to work by using 127.0.0.1 for the server address


----------



## Allanon

The program was tested using Python 2.5 and Windows XP. When writing it I didn't care if it was cross platform, I am only using it on a Windows computer.

The os.popen4() command in the findPID() function executes the Window's tasklist command which allows the program to get the process ID of a running program. I tried using the standard ways of get a process ID in python but that didn't work so I resorted to this method. On the mac you can probably replace the findPID() function with a standard python function that gets the process ID of a running program. This is needed so curl.exe can be terminated if the user wants to stop or switch videos.

Curl.exe is a Windows program that downloads from the internet. I think mac has a built in curl command. You will also need tivodecode which is a open source program that converts tivo files in to mpg files.


----------



## vanclute

ejonesss, did you ever get this working on your Mac? I'm also trying to run it on my Mac media server but so far have struck out as I indicated in the original thread about the script. Would love to know if you made further progress!


----------



## prin1113ci

Use the streaming proxy server to significantly improve on the inadequate support TiVo provides for online streaming stations.


----------

