Created
October 12, 2011 19:20
-
-
Save hendrikswan/1282234 to your computer and use it in GitHub Desktop.
sync-putio-files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
credentials.txt | |
series_sort.py | |
*.pyc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# encoding: utf-8 | |
# Created by Put.io. | |
# Copyright (c) 2010 Put.io. | |
# Licensed under the Apache License, Version 2.0 (the "License"); you may | |
# not use this file except in compliance with the License. You may obtain | |
# a copy of the License at | |
# | |
# http://www.apache.org/licenses/LICENSE-2.0 | |
# | |
# Unless required by applicable law or agreed to in writing, software | |
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
# License for the specific language governing permissions and limitations | |
# under the License. | |
""" | |
Basic Tutorial: | |
from putio import * | |
# connecting your put.io with your api key and api secret | |
api = Api("123456","abcdef") | |
# getting your items | |
items = api.get_items() | |
for it in items: | |
print "%5s %s" % (it.id, it.name) | |
# creating a folder | |
newitem = api.create_folder(name="blabla") | |
# getting one item | |
item = api.get_items(id=newitem.id)[0] | |
#item = api.get_items()[0] | |
# getting an item info | |
item = item.update_info() | |
print item.name, item.id, item.is_dir, item.__dict__ | |
# renaming an item | |
print "old name: %s" % item.name | |
newitem = item.rename_item("renamed by api") | |
print "new name: %s" % newitem.name | |
# moving an item to a target folder | |
# 0 being root of your files | |
newitem.move_item(target=0) | |
# deleting an item | |
newitem.delete_item() | |
# searching items | |
sresults = api.search_items("avi from:me type:video") | |
See the site for more info. | |
Todos: | |
* oAuth support | |
* Creating and getting MP4 Files | |
* File Uploading | |
* User Methods | |
""" | |
import sys | |
import socket | |
import urllib | |
import urllib2 | |
try: | |
import json | |
except ImportError: | |
import simplejson as json | |
# setup | |
RPC_URL = "http://api.put.io/v1" | |
# constants | |
UNITS = ['B', 'K', 'M', 'G', 'T', 'P', 'E'] | |
TIMEOUT = 60 #seconds | |
VERSION = "0.91" | |
# 0.92 transfers/add change | |
# 0.91 tidying up for the release; unicode human_size, user_idi user info | |
# bugs; some user, friend and item methods | |
# 0.90 updated auth, "v1" | |
# 0.85 reformated input and output. big changes on the api server. | |
# 0.84b typos | |
# 0.84 item_search to search_items, get_items orderby, get_friends | |
# 0.83 new stream url | |
def human_size(size): | |
""" | |
Converts bytes to human readable strings | |
Takes : An Integer | |
Returns: A String | |
Example: | |
>>> print human_size(12.66) # 12.7B | |
>>> print human_size(12345) # 12.1K | |
>>> print human_size(12345678) # 11.8M | |
>>> print human_size(12345678910) # 11.5G | |
>>> print human_size(12345678910111) # 11.2T | |
""" | |
if isinstance(size, unicode): size = int(size) | |
s = float(size * 1.0) | |
i = 0 | |
while size >= 1024.00 and i < len(UNITS): | |
i += 1 | |
size /= 1024.00 | |
return "%.1f%s" % (size, UNITS[i]) | |
def _send(obj, path, post=None, **args): | |
""" | |
Chats with API Server. | |
Takes : A dict. | |
Returns: JSON | |
To format the output, call _result() method. | |
Request Format: | |
{ | |
"user_id" : INTEGER, | |
"api_key" : STRING, | |
"api_secret" : STRING, | |
"params" : DICTIONARY | |
} | |
Response Format: | |
{ | |
"user_id" : INTEGER, | |
"response" : { | |
"results" : [{ | |
.... data .... | |
}] | |
}, | |
"error" :null, | |
"error_message" :null | |
} | |
""" | |
post_request = dict() | |
if not obj: | |
raise PutioError("You need to login first") | |
else: | |
post_request['api_key'] = obj.api_key | |
post_request['api_secret'] = obj.api_secret | |
url = RPC_URL + path | |
if args: url += "?" + urllib.urlencode(args) | |
# print url | |
# print "0. REQUEST: %s: %s" % (type(post), post) | |
post_request['params'] = dict() | |
for k in post.keys(): | |
#if k not in ("user_id", "api_key", "api_secret"): | |
if k not in ("api_key", "api_secret"): | |
post_request['params'][k] = post[k] | |
else: | |
post_request[k] = post[k] | |
# print "POSTREQUEST: %s" % post_request | |
pre_post = {} | |
pre_post['request'] = json.dumps(post_request) | |
error_data = "" | |
try: | |
# print "1. POST: %s: %s" % (type(pre_post), pre_post) | |
request = urllib2.Request(url, urllib.urlencode(pre_post)) | |
# default timeout time is 60 seconds. | |
socket.setdefaulttimeout(TIMEOUT) | |
if (sys.version_info[0] == 2 and sys.version_info[1] > 5) \ | |
or sys.version_info[0] > 2: | |
u = urllib2.urlopen(request, timeout=TIMEOUT) | |
else: | |
u = urllib2.urlopen(request) | |
data = u.read() | |
# print "2. RECEIVED DATA: %s" % data | |
return _result(obj, data) | |
except urllib2.HTTPError, e: | |
error_data = e.read() | |
if e.code == 500: | |
raise PutioError("An error occured. This may be a bug. Please \ | |
report to the application provider.", e) | |
elif e.code == 404: | |
raise PutioError("Unknown method, service or parameters.", e) | |
else: | |
raise PutioError("Service unavailable. Please try again.", e) | |
except urllib2.URLError, e: | |
raise PutioError("Request failed. (%s)" % str(e), e) | |
except UnboundLocalError, e: | |
raise PutioError("Service unavailable. This may be a bug on the api \ | |
server side. Please report following info: (%s)" % str(e), e) | |
def _result(obj, data): | |
""" | |
Takes : JSON | |
Returns: A Dict | |
Checks if the api server returned an error or not. | |
Returns the error message or the success message. | |
JSON Format that API Server returns: | |
{ | |
"error": false, | |
"error_message": null, | |
"user_id": some_integer, | |
"user_name": "username" | |
"response": { | |
"results": [ ...Always an array of things... ] | |
} | |
} | |
""" | |
try: | |
result = json.loads(data) | |
# print "3. RESULT DATA: %s" % result | |
except ValueError, e: | |
#logger.error('Error: %s' % e) | |
#logger.error('Data: %s' % data) | |
#logger.error('Result: %s' % result) | |
raise PutioError("Json error.", e) | |
# It's now a python dictionary. Json.loads() makes necessary | |
# conversions like "false" to "False", "null" to "None", etc. | |
# print "3. JSON TO DICT: ", result | |
if result['error'] is False: | |
obj.user_name = result['user_name'] | |
obj.user_id = result['id'] | |
return result['response']['results'] | |
else: | |
#raise PutioError(result['error_message']) | |
return None | |
def strip_tags(value): | |
""" | |
Return the given HTML with all tags stripped. | |
You may use this to strip the html tags from | |
Put.io Dashboard Messages. (Optional) | |
Usage: | |
print strip_tags(MessageInstance.title) | |
""" | |
import re | |
return re.sub(r'<[^>]*?>', '', value) | |
class BaseObj(object): | |
# Creates an object with given dictionary. | |
def __init__(self, dictionary=None, **args): | |
if dictionary: | |
self.__dict__ = dictionary | |
if len(args) > 0: | |
for k,v in args.iteritems(): | |
self.__dict__[k] = v | |
# def __getattr__(self, k): | |
# return self.__dict__[k] | |
def _convert_to_string(self): | |
if self.__dict__.has_key('file_type'): | |
self.file_type = Item._int_to_filetype(self.file_type) | |
if self.__dict__.has_key('dl_handler'): | |
self.dl_handler = UrlBucket.dl_handler[str(self.dl_handler)] | |
if self.__dict__.has_key('dltype'): | |
self.dltype = UrlBucket.dltype[str(self.dltype)] | |
class PutioError(Exception): | |
""" | |
PutioError Exception Class | |
""" | |
def __init__(self, message='', original=None): | |
self.message = message | |
self.original = original | |
def __str__(self): | |
if self.original: | |
original_name = type(self.original).__name__ | |
return '%s (Original Exception: %s, "%s")' % (self.message, | |
original_name, | |
self.original.args) | |
else: | |
return self.message | |
class User(BaseObj): | |
""" | |
Sample user: | |
u.name : 'aft' | |
u.friends_count : 497 | |
u.bw_avail_last_month : '0' | |
u.bw_quota : '161061273600' | |
u.shared_items : 3 | |
u.bw_quota_available : '35157040261' | |
u.disk_quota : '206115891200' | |
u.disk_quota_available : '158153510402' | |
u.shared_space : 0 | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
class Friend(BaseObj): | |
""" | |
Sample friend | |
f.dir_id : '1407' | |
f.id : '2' | |
f.name : 'hasan' | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
def get_items(self, **args): | |
""" | |
Takes : A friend instance | |
Returns: A List of item objects. | |
Shortcut for listing a friends shared items. | |
""" | |
return self.api.get_items(parent_id = self.dir_id, **args) | |
class Message(BaseObj): | |
""" | |
Dashboard message objects. | |
Message Methods: | |
message.delete() | |
Message Attributes: | |
message.id (Integer) | |
message.user_id (Integer) | |
message.title (String) | |
message.description (None) | |
message.importance (Integer) | |
message.file_name (String) | |
message.file_type (String) | |
message.user_file_id (Integer) | |
message.from_user_id (Integer. If None, message is from Put.io) | |
message.channel (Integer) | |
message.hidden (Integer, 1 or 0) | |
Sample: | |
user_file_id = 4 | |
user_id = 17 | |
description = None | |
title = '<a rel="userfile" href="/file/4">abcd.mp4 | |
</a> <span class="dash-gray">(89.86K) | |
downloaded</span>' | |
importance = 0 | |
file_name = 'abcd.mp4' | |
id = 3773 | |
file_type = 'audio' | |
hidden = 0 | |
from_user_id = None | |
channel = 2 | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, *args) | |
self.file_type = Item._int_to_filetype(self.file_type) | |
self.api = api | |
def delete(self): | |
""" | |
Deletes messages. Returns none if unsuccessful. | |
""" | |
args = {"id":self.id} | |
result = _send(self.api, path="/messages", post=args, method="delete") | |
if not result: return None | |
class Api(object): | |
""" | |
A python interface into the Put.io API | |
Example usage: | |
To create an instance of the putio.Api class, with authentication: | |
>>> from putio import * | |
>>> api = api(YOUR_API_KEY, YOUR_API_SECRET) | |
To get the list of your files: | |
>>> items = api.get_items() | |
>>> for i in items: print i.id, i.name | |
To get the item list in a specified folder: | |
>>> items = api.get_items(id=123) | |
>>> for i in items: print i.id, i.name | |
Api Methods: | |
api.get_items() | |
api.get_transfers() | |
api.get_user() | |
api.is_ready() | |
api.create_folder() | |
api.search_items() | |
api.get_messages() | |
api.create_subscription() | |
api.get_subscription() | |
api.get_folder_list() | |
api.update_user_token() | |
api.get_user_info() | |
api.create_bucket() | |
""" | |
def __init__(self, api_key, api_secret): | |
self.user_id = None | |
self.user_name = None | |
self.access_token = None | |
self.api_key = api_key | |
self.api_secret = api_secret | |
# Token is required only for streaming links | |
self.access_token = self._get_user_token() | |
self.api = self | |
def update_user_token(self): | |
""" | |
Before streaming a video/audio file, its best to update the token. | |
This method doesn't return anything. It just updates the Api instance. | |
""" | |
self.access_token = self._get_user_token() | |
def get_user_name(self): | |
""" | |
Takes : Nothing | |
Returns: A String | |
Returns the name of the authenticated user. You can use this to | |
welcome your user. | |
""" | |
return self.user_name | |
def is_ready(self): | |
""" | |
Takes : Nothing. | |
Returns: True or False | |
Checks if the authentication is successful. Returns False if it isn't. | |
Probably, you won't be using this much. | |
Example: | |
>>> api = Api("key", "secret") | |
>>> if api.is_ready(): print "Vuhuu!" | |
""" | |
try: | |
return self.user_name | |
except: | |
return None | |
def get_items(self, limit=20, offset=0, parent_id=0, **arguments): | |
""" | |
Takes : Item attributes [Optional] | |
Returns: An Array of Item objects | |
Example: | |
>>> import putio | |
>>> api = putio.Api(YOUR_API_KEY, YOUR_API_SECRET) | |
>>> items = api.get_items() #without an argument | |
>>> items = api.get_items(type="video") #with an argument | |
>>> for i in items: print i.name, i.id, i.type | |
You can use these optional parameters while selecting item(s): | |
id = STRING or INTEGER | |
parent_id = STRING or INTEGER | |
offset = INTEGER (Default:0) | |
limit = INTEGER (Default: 20) | |
type = STRING (See Item class for available types) | |
orderby = STRING (Default: createdat_desc) | |
Orderby parameters: | |
id_asc | |
id_desc | |
type_asc | |
type_desc | |
name_asc | |
name_desc | |
extention_asc | |
extention_desc | |
createdat_asc | |
createdat_desc (Default) | |
See Item Class doc for the available attributes. | |
""" | |
items = [] | |
args = {"limit":limit, "offset":offset, "parent_id":parent_id} | |
for k,v in arguments.iteritems(): args[k] = v | |
if "type" in arguments: | |
args['type'] = Item._filetype_to_int(arguments["type"]) | |
result = _send(self.api, path="/files", post=args, method="list") | |
if result: | |
self.update_user_token() | |
for r in result: | |
items.append(Item(self.api, r)) | |
return items | |
else: | |
raise PutioError("You have no items to show.") | |
def get_transfers(self): | |
""" | |
Takes : Nothing | |
Returns: An Array of Transfer objects | |
Example: | |
>>> trans = api.get_transfers() | |
>>> if newtransfers: | |
>>> for t in newtransfers: | |
>>> print t.name, t.status, t.percent_done | |
>>> else: print "you have no active transfers" | |
See Transfer Class doc for the available attributes. | |
""" | |
transfers = [] | |
args = {} | |
transferlist = _send(self, path="/transfers", post=args, method="list") | |
if len(transferlist) > 0: | |
for k in transferlist: | |
transfers.append(Transfer(self.api, k)) | |
return transfers | |
else: | |
return None | |
raise PutioError('You have no active transfers at the moment.') | |
def create_folder(self, name="New Folder", parent_id=0): | |
""" | |
Takes : A String [Optional], and | |
An Integer [Optional] | |
Returns: A Single Item object if successful. | |
Example: | |
>>> newfolder = api.create_folder(name="Created by Api") | |
>>> if newfolder: print "%s is created." % newfolder.name | |
""" | |
args = {"name":name, "parent_id":parent_id} | |
newfolder = _send(self.api, | |
path="/files", | |
post=args, | |
method="create_dir") | |
if newfolder and isinstance(newfolder, list): | |
newfolder = newfolder[0] | |
newfolder['id'] = int(newfolder['id']) | |
return Item(self.api, newfolder) | |
else: | |
#raise PutioError('Folder could not be created.') | |
return None | |
def search_items(self, query): | |
""" | |
Takes : A String | |
Returns: An Array of Item objects | |
Returns search results. You may add search parameters to the string | |
such as: | |
"from:'me'" (from:shares|jack|all|etc.) | |
"type:'video'" (audio|image|iphone|all|etc.) | |
"ext:'mp3'" (avi|jpg|mp4|all|etc.) | |
"time:'today'" (yesterday|thismonth|thisweek|all|etc.) | |
Example: | |
>>> searchresults = api.search_items("'jazz' from:'me' type:'audio'") | |
>>> if searchresults: | |
>>> for sr in searchresults: print sr.name | |
""" | |
search_results = [] | |
args = {"query":query} | |
result = _send(self, path="/files", post=args, method="search") | |
if result: | |
self.update_user_token() | |
for r in result: search_results.append(Item(self.api, r)) | |
return search_results | |
else: | |
return None | |
def get_messages(self): | |
""" | |
Takes : Nothing | |
Returns: An Array of Message objects | |
Returns your dashboard messages. | |
Example: | |
>>> msgs = api.get_messages() | |
>>> if msgs: | |
>>> for m in msgs: print m.title | |
""" | |
messages = [] | |
args = {} | |
result = _send(self, path="/messages", post=args, method="list") | |
if result: | |
for r in result: messages.append(Message(self.api, r)) | |
return messages | |
else: | |
return None | |
def create_subscription(self, name="My LegalTorrents Subscription", | |
url="http://www.legaltorrents.com/rss.xml", | |
**arguments): | |
""" | |
Takes : A String for name, a string for URL, and optional args. | |
Returns: A Single Subscription object | |
Creates a new subscription and returns it. | |
Example: | |
>>> newsub = api.create_subscription(name="Mininova", | |
url="http://www.mininova.org/rss.xml") | |
>>> if newsub: print "%s created." % newsub.name | |
See Subscription Class for available attributes | |
""" | |
args = {"title":name, "url":url} | |
for k in arguments.keys(): args[k] = arguments[k] | |
result = _send(self, path="/subscriptions", post=args, method="create") | |
if result: | |
return Subscription(self.api, result[0]) | |
else: | |
return None | |
def get_subscriptions(self, **arguments): | |
""" | |
Takes: Nothing | |
Returns: An Array of Subscription objects | |
Returns a list of your subscriptions. | |
Example: | |
>>> subs = api.get_subscriptions() | |
>>> if newsub: | |
>>> for s in subs: print subs.name | |
See Subscription Class for available attributes | |
""" | |
subscriptions = [] | |
args = {} | |
result = _send(self, path="/subscriptions", post=args, method="list") | |
if len(result) > 0: | |
for r in result: | |
if len(arguments) > 0: | |
for k,v in arguments.iteritems(): | |
if r[k] == v: | |
subscriptions.append(Subscription(self.api, r)) | |
else: | |
subscriptions.append(Subscription(self.api, r)) | |
return subscriptions | |
else: | |
return None | |
def get_folder_list(self): | |
""" | |
Takes : Nothing | |
Returns: An Array of item objects. | |
Notice that this method returns a flat list of your folders. Create | |
your own method if you need a tree like list. | |
Parent_id is id of the container folder | |
Example: | |
>>> folderlist = api.get_folder_list() | |
>>> if folderlist: | |
>>> for f in folderlist: print f.name | |
Here is the returned item before being processed: | |
{ | |
u'dirs': [...{sub folder 1}, {sub folder 2}...], # or [] | |
u'shared': None, | |
u'id': u'4220', | |
u'name': u'renamed (4)', | |
u'default_shared': None | |
} | |
See Folder Class for available attributes | |
""" | |
folders = [] | |
args = {} | |
result = _send(self, path="/files", post=args, method="dirmap") | |
# flattens the folder list | |
def recursive(folderarray): | |
if len(folderarray['dirs']) > 0: | |
for fa in folderarray['dirs']: | |
folders.append(Folder(self.api, fa)) | |
recursive(fa) | |
else: folders.append(Folder(self.api, folderarray)) | |
if result: | |
for r in result['dirs']: | |
if len(r['dirs']) > 0: | |
recursive(r) | |
else: folders.append(Folder(self.api, r)) | |
return folders | |
else: | |
return None | |
def get_user_info(self): | |
""" | |
Takes : Nothing | |
Returns: A Single User object if successful. | |
Gives information about the authenticated user. Use this to inform | |
user about its quotas, sharing size, current available space, etc. | |
All sizes are in bytes. Use human_size(byte) to convert if necessary. | |
Returned Attributes: | |
info.bw_quota | |
info.disk_quota | |
info.bw_quota_available | |
info.disk_quota_available | |
info.name | |
info.shared_space | |
info.friends_count | |
info.shared_items | |
""" | |
args = {} | |
result = _send(self, path="/user", post=args, method="info")[0] | |
if result: | |
return User(self.api, result) | |
else: | |
return None | |
def _get_user_token(self): | |
""" | |
Internal method for getting the user token. | |
""" | |
args = {} | |
result = _send(self, path="/user", post=args, method="acctoken") | |
if result: | |
return result['token'] | |
def get_friends(self): | |
""" | |
Takes : Nothing | |
Returns: An Array of Friend objects | |
Returns friends of the authenticated user. | |
Friend attributes: | |
friend.id | |
friend.name | |
friend.dir_id | |
Example: | |
>>> friends = api.get_friends() | |
>>> if friends: | |
>>> for f in friends: print f.name | |
To get a friend's files, use dir_id as a parent_id with get_items() | |
Option 1: | |
>>> for f in friends: | |
>>> items[f] = api.get_items(parent_id=f.dir_id) | |
>>> for i in items['jack']: print i.name | |
Option 2: | |
>>> for f in friends: | |
>>> f_items = f.get_items(limit=1) | |
>>> for fi in f_items: print fi.name | |
Returns None if the friend has no items. | |
""" | |
friends = [] | |
args = {} | |
result = _send(self, path="/user", post=args, method="friends") | |
if result: | |
for r in result: friends.append(Friend(self.api, r)) | |
return friends | |
else: | |
return None | |
def create_bucket(self): | |
""" | |
Takes : Nothing | |
Returns: An empty bucket object. | |
You'll need buckets to analyze and fetch URLs. Bucket is basicly a | |
container of one or more URLs, which then you can analyze and make | |
Put.io fetch the successfully analyzed URLs. | |
To fetch some URLs, you'll need to: | |
* Create a bucket (or use already existing one) | |
* Use Add method to add some URLs to the bucket | |
* Make Put.io analyze the bucket | |
* Add more or delete some of them | |
* And make Put.io fetch the URLs in the bucket. | |
After the analyzation, you can get a report about the bucket content | |
and the user quotas. For this, use get_report() method of UrlBucket | |
class. | |
""" | |
return UrlBucket(self.api) | |
class Item(BaseObj): | |
""" | |
An item can be a file or a folder. | |
Avaiable Item methods are: | |
item.rename_item() | |
item.move_item() | |
item.delete_item() | |
item.update_info() | |
item.get_download_url() | |
item.get_zip_url() | |
item.get_stream_url() | |
Available Item attributes: | |
Sizes are in bytes. Use human_size(byte) to convert if necessary. | |
item.id | |
item.name | |
item.type | |
item.size | |
item.is_dir | |
item.parent_id | |
item.screenshot_url | |
item.thumb_url | |
item.file_icon_url | |
item.download_url | |
Example Folder Item: | |
"id":"4394", | |
"name":"Billie Ray Martin The Crackdown Project - Vol 1", | |
"type":"folder", | |
"size":"23472048", | |
"is_dir":true, | |
"parent_id":"0", | |
"screenshot_url":"http://put.io/screenshot/b/dgRraFxlXmNl.jpg", | |
"thumb_url":"http://put.io/screenshot/dgRraFxlXmNl.jpg", | |
"file_icon_url":"http://put.io/images/file_types/folder.png", | |
"folder_icon_url":"", | |
"download_url":"http://node2.endlessdisk.com/download-file/17/4394", | |
"zip_url":"/stream-basket/17/4394"} | |
at the moment, type can be a: | |
folder | |
file | |
audio | |
movie | |
image | |
compressed | |
ms_doc | |
text | |
swf | |
unknown | |
""" | |
filetypes = { | |
"folder" : 0, | |
"file" : 1, | |
"audio" : 2, | |
"movie" : 3, | |
"image" : 4, | |
"compressed" : 5, | |
"pdf" : 6, | |
"ms_doc" : 7, | |
"text" : 8, | |
"swf" : 9 | |
} | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
@staticmethod | |
def _filetype_to_int(filetype): | |
if Item.filetypes.has_key(str(filetype.lower())): | |
return Item.filetypes[filetype] | |
else: raise PutioError("Unknown type. Please use one of these: " \ | |
"folder, file, audio, movie, image," \ | |
"compressed, pdf, ms_doc, text, swf") | |
@staticmethod | |
def _int_to_filetype(filetypeint): | |
""" | |
This method is not used because Api Server gives file types as string | |
""" | |
newfiletypes = dict() | |
# changes {"key":intvalue} to {"strvalue":"key"} first | |
for k,v in Item.filetypes.iteritems(): newfiletypes[str(v)] = k | |
# then finds value in keys | |
if newfiletypes.has_key(str(filetypeint)): | |
return newfiletypes[str(filetypeint)] | |
else: | |
return "unknown" | |
def rename_item(self, name): | |
""" | |
Takes : A String [Required] | |
Returns: A Single Item object | |
Example: | |
>>> print "Old Name: %s" % item.name | |
>>> item = item.rename_item("New Item Name") | |
>>> print "New Name: %s" % item.name | |
Renames the item. | |
""" | |
args = {"name":name, "id":self.id} | |
result = _send(self.api, path="/files", post=args, method="rename") | |
if result: return Item(self.api, result[0]) | |
else: return None | |
def move_item(self, target=0): | |
""" | |
Takes : An Integer of target folder id. [Optional] | |
Returns: A Single Item object | |
Example: | |
>>> item = item.move_item(target=1221) | |
>>> if item: | |
>>> print "New Location: %s" % api.get_items(id=item.id).name | |
Moves the item to another folder. Parent_id = 0 is the root folder | |
of your disk space. | |
""" | |
args = {"id":self.id, "parent_id":target} | |
result = _send(self.api, path="/files", post=args, method="move") | |
if result: return Item(self.api, result[0]) | |
else: return None | |
def delete_item(self): | |
""" | |
Takes : Nothing | |
Returns: Nothing if successful. | |
Example: | |
>>> item.delete_item() | |
Destroys the item permanently. | |
""" | |
args = {"id":self.id} | |
result = _send(self.api, path="/files", post=args, method="delete") | |
# fixme, check and return the result | |
return result | |
def update_info(self): | |
""" | |
Takes : Nothing | |
Returns: A Single Item object | |
Example: | |
>>> item = item.update_info() | |
>>> print item.__dict__ | |
Refreshes the items attributes. Useful for folders, because folders | |
can be updated via subscriptions in the background. | |
Raises an exception if unsuccessful. | |
""" | |
args = {"id":self.id} | |
result = _send(self.api, path="/files", post=args, method="info") | |
if result: | |
return Item(self.api, result[0]) | |
else: | |
raise PutioError("Update failed. Item may be unavailable.") | |
def get_download_url(self): | |
""" | |
Returns: A String | |
Example: | |
>>> item = item.update_info() #if necessary | |
>>> print item.get_download_url() | |
""" | |
if self.is_dir == False: | |
return self.download_url | |
else: | |
return None | |
def get_stream_url(self): | |
""" | |
Takes : Nothing | |
Returns: A String | |
Returns the stream url of files. If item is a folder, then download | |
url will be returned. | |
""" | |
result = self.update_info() | |
if result: | |
if self.is_dir == False: | |
sturl = str(self.stream_url) + "/atk/" \ | |
+ self.api.access_token | |
return sturl | |
else: | |
return self.get_download_url() | |
else: raise PutioError("Error: Item not found.") | |
def create_mp4(self): | |
"""TODO""" | |
pass | |
def create_folder(self, name="New Folder", **args): | |
""" | |
Takes : Nothing | |
Returns: An Item object | |
Creates and returns a folder in another folder. | |
""" | |
return self.api.create_folder(name = name, parent_id = self.id,**args) | |
class Folder(Item): | |
""" | |
Folders are an Item object. Check Item class documentation for more info. | |
Sample: | |
folder.id = 4394 | |
folder.name = "Billie Ray Martin The Crackdown Project" | |
folder.type = "folder" | |
folder.size = 23472048 | |
folder.is_dir = True | |
folder.parent_id = 0 | |
folder.screenshot_url = "/images/file_types/file.png" | |
folder.thumb_url = "/images/file_types/file.png" | |
folder.file_icon_url = "/images/file_types/folder.png" | |
folder.folder_icon_url = "" | |
folder.download_url = "http://XX.put.io/download-file/17/4394" | |
folder.zip_url = "http://XX.put.io/stream-basket/17/4394" | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
Item.__init__(self, dictionary, **args) | |
self.api = api | |
def create_folder(self, name="New Folder", **args): | |
""" | |
Creates a folder in another folder. This method is not being used | |
at the moment. | |
""" | |
return self.api.create_folder(name = name, parent_id = self.id,**args) | |
class Subscription(BaseObj): | |
""" | |
Subscription Methods: | |
edit() | |
delete() | |
toggle_status() | |
undate_info() | |
add_do_filters() | |
add_dont_filters() | |
Subscription Attributes: | |
subsitem.id (integer) | |
subsitem.url (string) | |
subsitem.name (string) | |
subsitem.do_filters (strings, seperated by commas) | |
subsitem.dont_filters (strings, seperated by commas) | |
subsitem.parent_folder_id (integer) | |
subsitem.last_update_time (string) | |
subsitem.next_update_time (string) | |
subsitem.paused (boolean) | |
Example: | |
>>> subsitem = api.get_subscriptions()[0] | |
>>> if subsitem: print subsitem.name | |
Sample Values: | |
subsitem.id = 860 | |
subsitem.url = "http://legaltorrents.com/music/rss.xml" | |
subsitem.name = "Jazz Radio" | |
subsitem.do_filters = "jazz, mp3" | |
subsitem.dont_filters = "smooth, wav" | |
subsitem.parent_folder_id = 234 | |
subsitem.last_update_time = "2010-01-01 00:00" | |
subsitem.next_update_time = "2010-01-01 00:00" | |
subsitem.paused = False | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
def edit(self, **arguments): | |
""" | |
Takes : A Dictionary of attributes to change | |
Returns: A Single Subscription object | |
Example: | |
>>> newsub = subsitem.edit(name="newname", url="http://newurl", ...) | |
>>> if newsubs: print "Subscription updated." | |
Changes values of any given subscription attribute. | |
""" | |
args = {"id":self.id, "title":self.name, "url":self.url} | |
for k in arguments.keys(): args[k] = arguments[k] | |
result = _send(self.api, | |
path="/subscriptions", | |
post=args, | |
method="edit") | |
if result: return Subscription(self.api, result[0]) | |
else: return None | |
def delete(self): | |
""" | |
Deletes the subscription item permanently. | |
Example: | |
>>> subsitem.delete() | |
>>> if newsubs: print "Subscription updated." | |
""" | |
args = {"id":self.id} | |
result = _send(self.api, path="/subscriptions", post=args, method="delete") | |
# fixme, better solution? | |
if not result: return None | |
def toggle_status(self): | |
""" | |
Toggles the activity status of a subscription item. You may also | |
change this value by editing the subscription item. This is just a | |
shortcut we use. | |
Example: | |
>>> print subsitem.paused # print True | |
>>> subsitem.toggle_status() | |
>>> print subsitem.paused # print False | |
""" | |
args = {"id":self.id} | |
result = _send(self.api, path="/subscriptions", post=args, method="pause") | |
if result: | |
self.paused = result[0]['paused'] | |
return Subscription(self.api, result[0]) | |
else: | |
return None | |
def update_info(self): | |
""" | |
Refreshes the subscription info. Use this to get the latest info | |
about the subscriptions. | |
Example: | |
>>> subs.update_info() | |
or | |
>>> subs = subs.update_info | |
""" | |
args = {"id":self.id} | |
result = _send(self.api, path="/subscriptions", post=args, method="info") | |
if result: | |
return Subscription(self.api, result[0]) | |
else: | |
raise PutioError("Subscription update failed.") | |
def add_do_filters(self, *arguments): | |
""" | |
Takes : An Array of strings | |
Returns: Updated Subscription object | |
Adds keyword(s) to "do fetch" filter | |
""" | |
args = self._modify_filter("add", *arguments) | |
result = _send(self.api, path="/subscriptions", post=args, method="edit") | |
if result: | |
return Subscription(self.api, result[0]) | |
else: | |
return False | |
def add_dont_filters(self, *arguments): | |
""" | |
Takes : An Array of strings | |
Returns: Updated Subscription object | |
Adds keyword(s) to "don't fetch" filter | |
""" | |
args = self._modify_filter("add", *arguments) | |
result = _send(self.api, path="/subscriptions", post=args, method="edit") | |
if result: | |
return Subscription(self.api, result[0]) | |
else: | |
return False | |
def del_do_filters(self, *arguments): | |
""" | |
Takes : An Array of strings | |
Returns: Updated Subscription object | |
Deletes keyword(s) from "do fetch" filter | |
""" | |
args = self._modify_filter("remove", *arguments) | |
result = _send(self.api, path="/subscriptions", post=args, method="edit") | |
if result: | |
return Subscription(self.api, result[0]) | |
else: | |
return False | |
def del_dont_filters(self, *arguments): | |
""" | |
Takes : An Array of strings | |
Returns: Updated Subscription object | |
Deletes keyword(s) from "dont fetch" filter | |
""" | |
args = self._modify_filter("remove", *arguments) | |
result = _send(self.api, path="/subscriptions", post=args, method="edit") | |
if result: | |
return Subscription(self.api, result[0]) | |
else: | |
return False | |
def _modify_filter(self, task, *arguments): | |
if self.do_filters is None: self.do_filters = "" | |
if self.dont_filters is None: self.dont_filters = "" | |
if task == "remove": | |
self.do_filters = self._remove_filter(self.do_filters, *arguments) | |
self.dont_filters = self._remove_filter(self.dont_filters, *arguments) | |
else: | |
self.do_filters = self._add_filter(self.do_filters, *arguments) | |
self.dont_filters = self._add_filter(self.dont_filters, *arguments) | |
args = { | |
"id":self.id, | |
"title":self.name, | |
"url":self.url, | |
"do_filters":self.do_filters, | |
"dont_filters":self.dont_filters | |
} | |
return args | |
@staticmethod | |
def _add_filter(filt, *arguments): | |
filters = list(filt.split(',')) | |
for a in arguments:filters.append(a) | |
for n in range(len(filters)): filters[n] = str(filters[n]).strip() | |
filters_str = ",".join(filters) | |
return filters_str | |
@staticmethod | |
def _remove_filter(filt, *arguments): | |
filters = list(filt.split(',')) | |
for a in arguments:filters.append(a) | |
for n in range(len(filters)): filters[n] = str(filters[n]).strip() | |
filters_str = ",".join(filters) | |
return filters_str | |
class Transfer(BaseObj): | |
""" | |
Transfer Methods: | |
instance.destroy_transfer() | |
Transfer Attributes: | |
instance.id | |
instance.name | |
instance.status | |
instance.percent_done | |
human_size : 200.0M | |
name : The.Messenger.DVDRip.XviD-AMIABLE.part1.rar | |
url : http://rapidshare.com/files/3232/abc.part1.rar' | |
needs_pass : 0, | |
source : rapidshare.com', | |
paid_bw : 209715200', | |
error : None, | |
type : file', | |
size : 209715200' | |
Samples: | |
instance.status = 'Completed' | |
instance.percent_done = '100' | |
instance.id = '45' | |
instance.name = 'A video file.avi' | |
instance.status : 'Waiting' | |
instance.percent_done : '0' | |
instance.id : '47' | |
instance.name : 'abcde.mp4' | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
def destroy_transfer(self): | |
""" | |
Destroys an active transfer irreversibly. | |
Example: | |
>>> instance.destroy_transfer() | |
""" | |
args = {"id":self.id} | |
result = _send(self.api, path="/transfers", post=args, method="cancel") | |
if result: return True | |
else: return None | |
def send_password(self): | |
"""TODO""" | |
pass | |
class UrlBucket(object): | |
""" | |
Url bucket is a completion of urls ready to fetch. | |
UrlBucket Methods: | |
bucket.add() | |
bucket.analyze_and_add_urls() | |
bucket.get_report() | |
bucket.fetch() | |
Static Methods: | |
extract_urls() | |
crawl_webpage() | |
Abilities: | |
* Add urls to the bucket | |
* Get report of the bucket if you need to. | |
* Fetch the urls | |
You can also: | |
* Analyze urls and add | |
* Crawl a web page and extract URLs | |
* Extract URLs from a text block | |
""" | |
def __init__(self, api, singleurl=[], torrenturl=[], multiparturl=[], **info): | |
self.api = api | |
self.report = {} | |
self.last_analyzed_bw_avail = None | |
self.last_analyzed_disk_avail = None | |
self.req_space = None | |
self.paid_bw = None | |
self.links = {"multiparturl":[], "torrenturl":[], "singleurl":[], "error":[]} | |
self._add(singleurl=singleurl, torrenturl=torrenturl, multiparturl=multiparturl) | |
def _add(self, singleurl=[], torrenturl=[], multiparturl=[], error=[], **info): | |
""" | |
Internal method. Use add() instead, or better yet use analyze(). | |
""" | |
for v in [singleurl, torrenturl, multiparturl, error]: | |
if not isinstance(v, list): | |
raise PutioError("Add method takes only arrays.") | |
if len(multiparturl) > 0: | |
for m in multiparturl: | |
self.links['multiparturl'].append(m) | |
if len(torrenturl) > 0: | |
for i in torrenturl: | |
self.links['torrenturl'].append(i) | |
if len(singleurl) > 0: | |
for i in singleurl: | |
self.links['singleurl'].append(i) | |
if len(error) > 0: | |
for i in error: | |
self.links['error'].append(i) | |
if len(info.keys()) > 0: | |
self.last_analyzed_bw_avail = info["last_analyzed_bw_avail"] | |
self.last_analyzed_disk_avail = info["last_analyzed_disk_avail"] | |
self.req_space = info["req_space"] | |
self.paid_bw = info["paid_bw"] | |
return self | |
def add(self, url): | |
""" | |
Takes: String or array | |
Returns: Dictionary of bucket items | |
Adds url(s) to the bucket to analyze or fetch. We recommend using | |
analyze_and_add_urls() method. | |
""" | |
if url and isinstance(url, str): | |
arg = {"url":url} | |
self.links['singleurl'].append(Url(self.api, arg)) | |
elif url and isinstance(url, list): | |
for u in url: | |
arg = {"url":url} | |
self.links['singleurl'].append(Url(self.api, arg)) | |
else: | |
raise PutioError("Add method takes a string or a list") | |
return self.links | |
def get_report(self): | |
""" | |
Returns the report of your bucket's last analyzation. Each UrlBucket | |
has its own report. After updating a bucket, remember to check its | |
new report. | |
Analyzed urls return like this one: | |
{ | |
'dl_handler': 1, | |
'name': 'Itemname.ext', | |
'file_type': 1, | |
'error': None, | |
'url': 'http://torrent.a.b/file.torrent', | |
'paid_bw': 0, | |
'file_size': 244091464, | |
'type_name': 'file', | |
'dltype': 2, #fixme whats this? | |
'human_size': '232.78M' | |
} | |
""" | |
return {"Current Available Disk Space": self.last_analyzed_disk_avail, | |
"Current Available Bandwidth": self.last_analyzed_bw_avail, | |
"Required Space": self.req_space, | |
"Bandwidth to be deducted from quota": self.paid_bw, | |
"Urls":self.links} | |
def fetch(self): | |
""" | |
Takes : A bucket instance | |
Returns: Array of transfers. (All the active transfers, to be exact.) | |
Initiates fetching all the links of the given URL Bucket instance. | |
Returns newly added transfers. Erroneous transfers will have the word | |
"Error" in "status". | |
Also you may edit below to raise exceptions, if result.error is not | |
false. | |
""" | |
go_fetch = [] | |
for k in self.links.keys(): | |
for i in self.links[k]: | |
if k != "error": go_fetch.append(i.url) | |
self.links = {} | |
args = {"links":go_fetch} | |
result = _send(self.api, path="/transfers", post=args, method="add") | |
transfers = [] | |
if result: | |
for r in result: | |
transfers.append(Transfer(self.api, r)) | |
return transfers | |
else: | |
return None | |
def analyze(self, links=None): | |
""" | |
Takes : An Array of URLs. | |
Returns: An Array of Link objects. | |
Example: | |
Link objects can be fetched one by one by iterating the array. | |
>>> links = bucket.analyze(array) | |
>>> for l in links: l.fetch() | |
or | |
The whole bucket can be fetched with a single request. | |
>>> bucket.analyze(array) | |
>>> mytransfers = bucket.fetch() | |
""" | |
multipart_urls = [] | |
single_urls = [] | |
torrent_urls = [] | |
error_urls = [] | |
paid_bw = 0 | |
req_space = 0 | |
#args = {"links":urllib.quote(text)} | |
if links and isinstance(links, list): | |
args = {"links":links} | |
elif links and isinstance(links, str): | |
raise PutioError("Analyze method takes a list. Use " + \ | |
"extract_urls() to convert string of urls to a list.") | |
else: | |
go_analyze = [] | |
for k in self.links.keys(): | |
for i in self.links[k]: | |
if k != "error": go_analyze.append(i.url) | |
args = {"links":go_analyze} | |
result = _send(self.api, path="/urls", post=args, method="analyze") | |
if result: | |
if len(result['items']['multiparturl']) > 0: | |
for r in result['items']['multiparturl']: | |
# unicode to int | |
paid_bw += int(r['paid_bw']) | |
req_space += int(r['size']) | |
for p in r["parts"]: | |
multipart_urls.append(Multipart(self.api, p)) | |
if len(result['items']['torrent']) > 0: | |
for r in result['items']['torrent']: | |
torrent_urls.append(Torrent(self.api, r)) | |
paid_bw += int(r['paid_bw']) | |
req_space += int(r['size']) | |
if len(result['items']['singleurl']) > 0: | |
for r in result['items']['singleurl']: | |
single_urls.append(Url(self.api, r)) | |
paid_bw += int(r['paid_bw']) | |
req_space += int(r['size']) | |
if len(result['items']['error']) > 0: | |
for r in result['items']['error']: | |
error_urls.append(Url(self.api, r)) | |
self.links = {"multiparturl":[], "torrenturl":[], | |
"singleurl":[], "error":[]} | |
self._add(multiparturl=multipart_urls, | |
singleurl=single_urls, | |
torrenturl=torrent_urls, | |
error=error_urls, | |
last_analyzed_disk_avail=result['disk_avail'], | |
last_analyzed_bw_avail=result['bw_avail'], | |
paid_bw=paid_bw, | |
req_space=req_space | |
) | |
return self.get_report() | |
else: | |
return None | |
def crawl_webpage(self, url): | |
""" | |
Takes : A String of a web page URL | |
Returns: A String of cleaned url list | |
Example: | |
>>> newbucket = api.create_bucket() | |
>>> cleaned_urls = newbucket.crawl_webpage("http://a.b.c/downloads") | |
""" | |
return self.extract_urls(url) | |
def extract_urls(self, text): | |
""" | |
Takes : A String | |
Returns: A list of cleaned urls | |
Example: | |
>>> txt = "Check these out: http://a.b/c.torrent and ftp://a.b/c.rar" | |
>>> urls = bucket.extract_urls(txt) | |
>>> print urls | |
["http://a.b/c.torrent", "ftp://a.b/c.rar"] | |
Extracts URLs from a block of text. | |
* Links in the text are recognized by the protocol names such as http, | |
ftp, etc. | |
* Torrent file links do have to have .torrent extention. | |
""" | |
extracted_urls = [] | |
args = {"txt":text} | |
result = _send(self.api, path="/urls", post=args, method="extracturls") | |
if result: | |
for r in result: extracted_urls.append(r['url']) | |
#return " \n".join(extracted_urls) | |
return extracted_urls | |
else: | |
return [] | |
class Url(BaseObj): | |
""" | |
For us, Url is a downloadable file link. These files can be any type. | |
Sources can be ftp, http, etc. | |
Url Attributes: | |
instance.dl_handler = 'Single Url' | |
instance.name = 'name_of_the_file.mp4' | |
instance.file_type = 'file' | |
instance.error = None | |
instance.url = 'ftp://a.b.c/name_of_the_file.mp4' | |
instance.paid_bw = 0 | |
instance.file_size = '92014' | |
instance.type_name = 'file' | |
instance.dltype = 3 | |
instance.human_size = '89.86K' | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
class Error(BaseObj): | |
""" | |
SingleRapid is a Rapidshare url, which is generally an archive file. If | |
the downloaded file have a multiple volume, it's a Multipart object. | |
Url Attributes: | |
instance.dl_handler = 'Rapid' | |
instance.name = 'ABCDE.rar' | |
instance.file_type = 'file' | |
instance.error = None | |
instance.url = 'http://rapidshare.com/files/abcde.rar' | |
instance.paid_bw = '104961263' | |
instance.file_size = '104961263' | |
instance.type_name = 'file' | |
instance.dltype = 1 | |
instance.human_size = '100.10M' | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
class Torrent(BaseObj): | |
""" | |
Torrent objects are fetched via our Torrent clients. It can contain | |
single, multi part archive files, or any other file type. Send the | |
torrent URL, we figure out the rest. | |
Torrent Attributes: | |
instance.dl_handler = 'Torrent' | |
instance.name = 'ABCDE.avi' | |
instance.file_type = 'file' | |
instance.file_size = 244091464 | |
instance.url = 'http://a.b/c.torrent' | |
instance.paid_bw = 0 | |
instance.error = None | |
instance.type_name = 'file' | |
instance.dltype = 2 | |
instance.human_size = '232.78M' | |
""" | |
def __init__(self, api, dictionary=None, url=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
class Multipart(BaseObj): | |
""" | |
Multipart objects are files, which contains patterns like "part1", | |
"001", etc. These files are automatically extracted and saved to your | |
space. | |
Multipart Attributes: | |
instance.name = 'ABCDE' | |
instance.size = 366500388 | |
instance.human_size = 350.0M | |
instance.paid_bw = 366500388 | |
instance.parts = [ | |
{ | |
"url":"http:\/\/rapidshare.com\/files\/1\/M.part3.rar", | |
"size":"47711664", | |
"paid_bw":"47711664", | |
"source":"rapidshare.com", | |
"name":"Mdb35.part3.rar", | |
"human_size":"45.5M", | |
"type":"file", | |
"needs_pass":0, | |
"error":null | |
}, | |
{ | |
"url":"http:\/\/rapidshare.com\/files\/2\/M.part1.rar", | |
"size":"55000000", | |
"paid_bw":"55000000", | |
"source":"rapidshare.com", | |
"name":"Mdb35.part1.rar", | |
"human_size":"52.5M", | |
"type":"file", | |
"needs_pass":0, | |
"error":null | |
} | |
] | |
instance.error = None | |
""" | |
def __init__(self, api, dictionary=None, **args): | |
BaseObj.__init__(self, dictionary, **args) | |
self.api = api | |
if __name__ == '__main__': | |
print "This file should not be executed." | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import putio | |
import urllib2 | |
import base64 | |
import utils | |
import os | |
import time | |
from datetime import timedelta | |
import datetime | |
import time | |
putio_uname = "your.put.io.username" | |
putio_secret_key = "your.put.io.secret.key" | |
movies_folder = "c:\media\movies" | |
series_folder = "c:\media\series" | |
series_downloads_folder = "c:\media\downloads" | |
def get_root_folder(api, folder_name): | |
folders = filter(lambda it: it.name==folder_name, api.get_items()) | |
if len(movies_folder) == 0: return | |
return folders[0] | |
def download_file(url, file_name, target_dir): | |
file_path = target_dir + file_name | |
try: | |
base64string = base64.encodestring('%s:%s' % (putio_uname, putio_secret_key))[:-1] | |
req = urllib2.Request(url) | |
req.add_header("Authorization", "Basic %s" % base64string) | |
u = urllib2.urlopen(req) | |
f = open(file_path, 'wb') | |
meta = u.info() | |
file_size = int(meta.getheaders("Content-Length")[0]) | |
print "Downloading: %s Bytes %s" % (file_name, file_size) | |
start_time = datetime.datetime.now() | |
print start_time | |
file_size_dl = 0 | |
block_sz = 48 * 1024 | |
while True: | |
buffer = u.read(block_sz) | |
if not buffer: | |
break | |
elapsed = datetime.datetime.now() - start_time | |
hours, remainder = divmod(elapsed.seconds, 3600) | |
minutes, seconds = divmod(remainder, 60) | |
elapsed_seconds = elapsed.seconds if elapsed.seconds > 0 else 1 | |
size_per_second = (file_size_dl/1000) / elapsed_seconds | |
file_size_dl += len(buffer) | |
f.write(buffer) | |
status = r"%10d [%3.2f%%] - time since start '%sh%sm%ss' - %3.2fkB/s" % (file_size_dl, file_size_dl * 100. / file_size, hours, minutes, seconds, size_per_second) | |
status = status + chr(8)*(len(status)+1) | |
print status, | |
f.close() | |
except: | |
try: | |
os.remove(file_path) | |
except: | |
print "couldn't delete the file %s" % file_path | |
raise | |
def download_movie(api, mov): | |
print "downloading movie %s" % (mov.name) | |
if len(api.get_items(id=mov.id)) == 0: | |
print "the movie has been removed" | |
return False | |
friendly_movie_name = mov.name.replace("-", " ").strip().replace(".", "_").replace(" ", "_") | |
movie_target = movies_folder + "/" + friendly_movie_name + "/" | |
if not os.path.isdir(movie_target): | |
os.mkdir(movie_target) | |
print "created movie directory ", movie_target | |
if mov.type == "movie": | |
#download_file(mov.download_url, mov.name, movie_target) | |
download_file(mov.download_url, mov.name, movie_target) | |
return True | |
movie_files = filter(lambda it: not it.is_dir, api.get_items(parent_id=mov.id)) | |
#utils.print_items(movie_files) | |
for it in movie_files: | |
download_file(it.download_url, it.name, movie_target) | |
return True | |
def download_movies(api): | |
movies_folder = get_root_folder(api, "movies") | |
new_movies = api.get_items(parent_id=movies_folder.id) | |
for mov in new_movies: | |
utils.reflect_item(mov) | |
if download_movie(api, mov): | |
mov.delete_item() | |
def download_series(api): | |
put_series_folder = get_root_folder(api, "series") | |
new_series = api.get_items(parent_id=put_series_folder.id) | |
print "found ", len(new_series), " series files, starting download ....." | |
for it in new_series: | |
if len(api.get_items(id=it.id)) == 0: | |
continue | |
download_file(it.download_url, it.name, series_downloads_folder + "/" ) | |
it.delete_item() | |
if __name__=="__main__": | |
api = putio.Api(putio_uname, putio_secret_key) | |
while True: | |
try: | |
download_movies(api) | |
download_series(api) | |
#except Exception as inst: | |
# print "error occurred.." | |
# utils.reflect_item(inst) | |
finally: | |
time.sleep(10) | |
# todo: do not download sample.avi files |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def print_items(items): | |
for it in items: | |
print it.id, it.name | |
reflect_item(it) | |
def reflect_item(item): | |
for property, value in vars(item).iteritems(): | |
print "\t", property, ':', value |
I guess the credentials in credentials.txt aren't up to date anymore, but still... :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i realize this is a blast from the past, but what library it
import putio
from?