Added move file to trash, some comments

This commit is contained in:
richard@richard.do 2013-02-04 21:15:18 +00:00
parent 7333801e86
commit 5723218006
4 changed files with 75 additions and 12 deletions

View file

@ -1,6 +1,6 @@
# Mega.py # Mega.py
Python library for the Mega.co.nz API, currently supporting login, uploading & downloading of files. Python library for the Mega.co.nz API, currently supporting login, uploading, downloading & deleting of files.
This is a work in progress, further functionality coming shortly. This is a work in progress, further functionality coming shortly.

View file

@ -3,6 +3,7 @@ import json
import base64 import base64
import struct import struct
import binascii import binascii
import random
def aes_cbc_encrypt(data, key): def aes_cbc_encrypt(data, key):
aes_cipher = AES.new(key, AES.MODE_CBC, '\0' * 16) aes_cipher = AES.new(key, AES.MODE_CBC, '\0' * 16)
@ -128,3 +129,11 @@ def get_chunks(size):
del chunks[pp] del chunks[pp]
return chunks return chunks
# more general functions
def make_id(length):
text = ''
possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
for i in range(length):
text += random.choice(possible)
return text

70
mega.py
View file

@ -18,6 +18,7 @@ class Mega(object):
self.timeout = 160 #max time (secs) to wait for response from api requests self.timeout = 160 #max time (secs) to wait for response from api requests
self.sid = None self.sid = None
self.sequence_num = random.randint(0, 0xFFFFFFFF) self.sequence_num = random.randint(0, 0xFFFFFFFF)
self.request_id = make_id(10)
@classmethod @classmethod
def login(class_, email, password): def login(class_, email, password):
@ -25,7 +26,6 @@ class Mega(object):
instance.login_user(email, password) instance.login_user(email, password)
return instance return instance
def login_user(self, email, password): def login_user(self, email, password):
password_aes = prepare_key(str_to_a32(password)) password_aes = prepare_key(str_to_a32(password))
uh = stringhash(email, password_aes) uh = stringhash(email, password_aes)
@ -35,7 +35,6 @@ class Mega(object):
raise errors.RequestError(resp) raise errors.RequestError(resp)
self._login_process(resp, password_aes) self._login_process(resp, password_aes)
def _login_process(self, resp, password): def _login_process(self, resp, password):
encrypted_master_key = base64_to_a32(resp['k']) encrypted_master_key = base64_to_a32(resp['k'])
self.master_key = decrypt_key(encrypted_master_key, password) self.master_key = decrypt_key(encrypted_master_key, password)
@ -76,19 +75,22 @@ class Mega(object):
req = requests.post( req = requests.post(
'{0}://g.api.{1}/cs'.format(self.schema,self.domain), params=params, data=json.dumps([data]), timeout=self.timeout) '{0}://g.api.{1}/cs'.format(self.schema,self.domain), params=params, data=json.dumps([data]), timeout=self.timeout)
json_resp = req.json() json_resp = req.json()
#if numeric error code response #if numeric error code response
if isinstance(json_resp, int): if isinstance(json_resp, int):
raise errors.RequestError(json_resp) raise errors.RequestError(json_resp)
return json_resp[0] return json_resp[0]
def get_files(self): def get_files(self):
'''
Get all files in account
'''
files = self.api_request({'a': 'f', 'c': 1}) files = self.api_request({'a': 'f', 'c': 1})
files_dict = {} files_dict = {}
for file in files['f']: for file in files['f']:
files_dict[file['h']] = self.process_file(file) files_dict[file['h']] = self.process_file(file)
return files_dict return files_dict
def download_url(self, url): def download_url(self, url):
path = self.parse_url(url).split('!') path = self.parse_url(url).split('!')
file_id = path[0] file_id = path[0]
@ -108,6 +110,57 @@ class Mega(object):
user_data = self.api_request({'a': 'ug'}) user_data = self.api_request({'a': 'ug'})
return user_data return user_data
def delete_url(self, url):
#delete a file via it's url
path = self.parse_url(url).split('!')
file_id = path[0]
return self.move(file_id, 4)
def delete(self, file_id):
#straight delete by id
return self.move(file_id, 4)
def move(self, file_id, target):
#TODO node_id improvements
'''
Move a file to another parent node
params:
a : command
n : node we're moving
t : id of target parent node, moving to
i : request id
targets
2 : root
3 : inbox
4 : trash
'''
#get node data
node_data = self.api_request({'a': 'f', 'f': 1, 'p': file_id})
target_node_id = str(self.get_node_by_type(target)[0])
node_id = None
#determine node id
for i in node_data['f']:
if i['h'] is not u'':
node_id = i['h']
return self.api_request({'a': 'm', 'n': node_id, 't': target_node_id, 'i': self.request_id})
def get_node_by_type(self, type):
'''
Get a node by it's numeric type id, e.g:
0: file
1: dir
2: special: root cloud drive
3: special: inbox
4: special trash bin
'''
nodes = self.get_files()
for node in nodes.items():
if(node[1]['t'] == type):
return node
def download_file(self, file_id, file_key, is_public=False): def download_file(self, file_id, file_key, is_public=False):
if is_public: if is_public:
@ -127,7 +180,7 @@ class Mega(object):
attribs = decrypt_attr(attribs, k) attribs = decrypt_attr(attribs, k)
file_name = attribs['n'] file_name = attribs['n']
print "Downloading %s (size: %d), url = %s" % (attribs['n'], file_size, file_url) print "downloading {0} (size: {1}), url = {2}".format(attribs['n'], file_size, file_url)
input_file = requests.get(file_url, stream=True).raw input_file = requests.get(file_url, stream=True).raw
output_file = open(file_name, 'wb') output_file = open(file_name, 'wb')
@ -168,6 +221,9 @@ class Mega(object):
raise ValueError('Mismatched mac') raise ValueError('Mismatched mac')
def get_public_url(self, file_id, file_key): def get_public_url(self, file_id, file_key):
'''
Get a files public link including decrypted key
'''
if file_id and file_key: if file_id and file_key:
public_handle = self.api_request({'a': 'l', 'n': file_id}) public_handle = self.api_request({'a': 'l', 'n': file_id})
decrypted_key = a32_to_base64(file_key) decrypted_key = a32_to_base64(file_key)
@ -237,12 +293,6 @@ class Mega(object):
def process_file(self, file): def process_file(self, file):
""" """
Process a file... Process a file...
Possible node types are:
0: File
1: Dir
2: Special - Root/Cloud drive
3: Special - Inbox
4: Special - Trash
""" """
if file['t'] == 0 or file['t'] == 1: if file['t'] == 0 or file['t'] == 1:
key = file['k'][file['k'].index(':') + 1:] key = file['k'][file['k'].index(':') + 1:]

View file

@ -21,8 +21,12 @@ def test():
#upload file #upload file
print(m.upload('test.py')) print(m.upload('test.py'))
#trash a file, by id or url
#print(m.delete('C5pxAbr'))
#print(m.delete_url('https://mega.co.nz/#!C5pxAbrL!SPxZH0Ovn2DLK_n5hLlkGQ2oTD8HcU6TYiz_TPg78kY'))
#download file from url #download file from url
m.download_url('https://mega.co.nz/#!utYjgSTQ!OM4U3V5v_W4N5edSo0wolg1D5H0fwSrLD3oLnLuS9pc') m.download_url('https://mega.co.nz/#!6hBW0R4a!By7-Vjj5xal8K5w_IXH3PlGNyZ1VvIrjZkOmHGq1X00')
if __name__ == '__main__': if __name__ == '__main__':
test() test()