-
Notifications
You must be signed in to change notification settings - Fork 2
/
bitcasa.py
173 lines (154 loc) · 5.59 KB
/
bitcasa.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# Bitcasa Python Class (Unofficial)
# Michael Thomas, 2013
# TODO #
########
# Test for Python2 & Python3
# Error Handling that works well.
# Implement File Methods
# DONE: download file to cache
# upload file from cache
# Import Section
import urllib2, urllib
import json
import base64
import sys
import os
# Upload Progress Helper
# @todo - May switch Download to this as well.
class Progress(object):
def __init__(self):
self._seen = 0.0
def update(self, total, size, name):
self._seen += size
pct = (self._seen / total) * 100.0
print '%s progress: %.2f' % (name, pct)
class file_with_callback(file):
def __init__(self, path, mode, callback, *args):
file.__init__(self, path, mode)
self.seek(0, os.SEEK_END)
self._total = self.tell()
self.seek(0)
self._callback = callback
self._args = args
def __len__(self):
return self._total
def read(self, size):
data = file.read(self, size)
self._callback(self._total, len(data), *self._args)
return data
# e.g.
# path = 'large_file.txt'
# progress = Progress()
# stream = file_with_callback(path, 'rb', progress.update, path)
# req = urllib2.Request(url, stream)
# res = urllib2.urlopen(req)
# Bitcasa Class
class Bitcasa:
# Start Client & Load Config
def __init__ (self, config_path):
# Config file
self.config_path = config_path
try:
with open(self.config_path, 'r') as config_file:
self.config = json.load(config_file)
except:
sys.exit("Could not find configuration file.")
# Set configuation variables
self.api_url = self.config['api_url'].encode('utf-8')
self.client_id = self.config['client_id'].encode('utf-8')
self.secret = self.config['secret'].encode('utf-8')
self.redirect_url = self.config['redirect_url'].encode('utf-8')
self.auth_token = self.config['auth_token'].encode('utf-8')
self.access_token = self.config['access_token'].encode('utf-8')
# Adding support for File Cache
self.cache_dir = self.config['cache_dir'].encode('utf-8')
# Check to see if cache_dir is valid & exists
if(self.cache_dir == None):
self.cache_dir = os.path.dirname(os.path.realpath(__file__)) + ".cache"
self.save_config()
# Now Make sure it exists
if not os.path.exists(self.cache_dir):
os.makedirs(self.cache_dir)
# See if we need our tokens
if(self.auth_token == "") or (self.access_token == ""):
return self.authenticate()
else:
return None
def save_config (self):
with open(self.config_path, 'w') as outfile:
json.dump(self.config, outfile, indent=4)
def authenticate (self):
print("### ENTER THE FOLLOWING URL IN A BROWSER AND AUTHORIZE THIS APPLICATION ###")
print(self.api_url + "/oauth2/authenticate?client_id=" + self.client_id + "&redirect=" + self.redirect_url)
print("### ONCE YOU HAVE AUTHORIZED THE APPLICATION, ENTER THE AUTH TOKEN HERE (WILL BE IN URL) ###")
auth = raw_input("Auth Token: ")
self.auth_token = auth
self.config['auth_token'] = self.auth_token
request = urllib2.Request("https://developer.api.bitcasa.com/v1/oauth2/access_token?secret="+ self.secret +"&code=" + self.auth_token)
try:
response = json.load(urllib2.urlopen(request))
self.access_token = response['result']['access_token']
self.config['access_token'] = self.access_token
self.save_config()
return True
except urllib2.HTTPError, e:
error = e.read()
return error
def list_folder (self, path = ""):
request = urllib2.Request(self.api_url + "/folders" + path + "?access_token=" + self.access_token)
try:
response = json.load(urllib2.urlopen(request))
except urllib2.HTTPError, e:
error = e.read()
response = json.loads(error)
if(response['result'] == None):
return response
else:
return response['result']['items']
def add_folder (self, path, folder_name):
payload = {"folder_name":folder_name}
request = urllib2.Request(self.api_url + "/folders/" + path + "?access_token=" + self.access_token, urllib.urlencode(payload))
try:
response = json.load(urllib2.urlopen(request))
except urllib2.HTTPError, e:
response = e.read()
return response
def delete_folder (self, path):
payload = {"path":path}
request = urllib2.Request(self.api_url + "/folders/?access_token=" + self.access_token, urllib.urlencode(payload))
request.get_method = lambda: 'DELETE'
response = json.load(urllib2.urlopen(request))
return response
# File API Methods
def download_file (self, file_id, path, file_name, file_size):
f = open(self.cache_dir + "/" + file_name, 'wb')
print "Downloading file from: " + self.api_url + "/files/"+file_id+"/"+ file_name +"?access_token=" + self.access_token + "&path=/" + path
u = urllib2.urlopen(self.api_url + "/files/"+file_id+"/"+file_name+"?access_token=" + self.access_token + "&path/" + path)
print "Downloading: %s Bytes: %s" % (file_name, file_size)
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
print status
print "Closing new File"
f.close()
return self.cache_dir + "/" + file_name
def upload_file (self, path, file_name, file_size):
return
# def rename_folder (self, path, new_filename, exists = "rename"):
# # Encode path
# if(path != ""):
# path = base64.b64encode(path)
# else:
# return "You must specify a file to rename."
# payload = { "operation" = "" }
# data = urllib.urlencode(payload)
# request = urllib2.Request(Bitcasa.api_url + "/folders/" + path + "?access_token=" + self.access_token, data)
# response = json.load(urllib2.urlopen(request))
# return response;