Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Dropbox File Picker V2.py
#!python3
#original code https://gist.github.com/omz/fb180c58c94526e2c40b
#bosco added changes dropbox 2 functionality
#minor edits done to run in python3
#see forum post https://forum.omz-software.com/topic/4425/dropbox-file-picker-needs-update
# IMPORTANT SETUP INSTRUCTIONS:
#
# 1. Go to http://www.dropbox.com/developers/apps (log in if necessary)
# 2. Select "Create App"
# 3. Select the following settings:
# * "Dropbox API app"
# * "Files and datastores"
# * "(No) My app needs access to files already on Dropbox"
# * "All file types"
# * (Choose any app name)
# 4. On the newly-created app's summary page, click the "Generate"
# button under "Generated access token"
# 5. Copy the generated token (a long string of gibberish) and
# paste it below (replace YOUR_TOKEN_HERE).
# 6. (optional) Open the "wrench" (actions) menu in Pythonista and add
# this script, so you can run it from everywhere.
# Notes:
# All selected files are downloaded into the root folder of the Pythonista
# script library. If a file with the same name already exists, a numeric
# suffix is appended automatically.
TOKEN = 'YOUR_TOKEN_HERE'
import requests
import urllib
import os
import ui
import functools
import json
def list_folder(folder_path='/'):
headers = {'Authorization': 'Bearer %s' % (TOKEN,),'Content-Type': 'application/json' }
if folder_path == '/': folder_path = ''
data = {'path':folder_path}
r = requests.post('https://api.dropboxapi.com/2/files/list_folder', headers=headers, data=json.dumps(data))
result = r.json()
return result.get('entries', None)
def download_file(path, dest_filename, progress=None):
data = {'path':path}
headers = {'Authorization': 'Bearer %s' % (TOKEN,),'Dropbox-API-Arg': json.dumps(data)}
url = 'https://content.dropboxapi.com/2/files/download'
r = requests.post(url, stream=True, headers=headers)
dest_path = os.path.join(os.path.expanduser('~/Documents'), dest_filename)
i = 1
while os.path.exists(dest_path):
base, ext = os.path.splitext(dest_filename)
dest_path = os.path.join(os.path.expanduser('~/Documents'), base + '-' + str(i) + ext)
i += 1
size = int(r.headers.get('Content-Length', 0))
bytes_written = 0
canceled = False
with open(dest_path, 'wb') as f:
for chunk in r.iter_content(1024*10):
f.write(chunk)
bytes_written += len(chunk)
if size > 0 and callable(progress):
p = float(bytes_written) / float(size)
should_cancel = progress(p)
if should_cancel:
canceled = True
break
if canceled:
os.remove(dest_path)
class DropboxView (ui.View):
def __init__(self, path='/'):
tv = ui.TableView()
tv.frame = self.bounds
tv.flex = 'WH'
ds = ui.ListDataSource([])
ds.action = self.item_selected
tv.data_source = ds
tv.delegate = ds
self.tableview = tv
self.add_subview(self.tableview)
self.name = 'Dropbox'
label = ui.Label(frame=self.bounds)
label.flex = 'WH'
label.background_color = (1, 1, 1, 0.95)
label.text = 'Loading...'
label.touch_enabled = True
label.alignment = ui.ALIGN_CENTER
self.path = path
self.add_subview(label)
self.status_label = label
self.canceled = False
def will_close(self):
self.canceled = True
def item_selected(self, sender):
item = sender.items[sender.selected_row]
if item.get('is_dir', False):
self.status_label.text = 'Loading Folder...'
self.status_label.hidden = False
self.path = item['path']
self.load_folder()
elif item.get('up', False):
self.status_label.text = 'Loading Folder...'
self.status_label.hidden = False
self.path = os.path.split(self.path)[0]
self.load_folder()
else:
path = item.get('path')
self.download_file(path)
@ui.in_background
def download_file(self, path):
self.status_label.text = 'Downloading %s...' % (path,)
self.status_label.hidden = False
download_file(path, os.path.split(path)[1], self.download_progress)
self.status_label.hidden = True
def download_progress(self, p):
self.status_label.text = '%i %% Downloaded...' % (p*100,)
return self.canceled
@ui.in_background
def load_folder(self):
infos = list_folder(self.path)
items = []
if self.path != '/':
items.append({'title': '..', 'image': 'ionicons-arrow-up-c-32', 'up': True})
if not infos:
import console
console.alert('Error', 'Could not load folder. Please check if you entered the access token correctly.', 'OK', hide_cancel_button=True)
self.status_label.hidden = True
return
for info in infos:
path = info.get('path_display')
name = os.path.split(path)[1]
if name.startswith('.'):
continue
is_dir = True if info.get('.tag') == 'folder' else False
item = {'title': name, 'image': 'ionicons-folder-32' if is_dir else 'ionicons-ios7-download-outline-32', 'accessory_type': 'disclosure_indicator' if is_dir else 'none', 'is_dir': is_dir, 'path': info['path_display']}
items.append(item)
def cmp(a, b):
return (a > b) - (a < b )
def c(o1, o2):
u_cmp = -1 * cmp(o1.get('up', False), o2.get('up', False))
if u_cmp != 0:
return u_cmp
d_cmp = -1 * cmp(o1.get('is_dir', False), o2.get('is_dir', False))
if d_cmp == 0:
return cmp(o1.get('path', '').lower(), o2.get('path', '').lower())
return d_cmp
items.sort(key=functools.cmp_to_key(c))
self.tableview.data_source.items = items
self.status_label.hidden = True
self.name = self.path
root_view = DropboxView()
root_view.present('fullscreen')
root_view.load_folder()
@encela95dus

This comment has been minimized.

Copy link
Owner Author

encela95dus commented Oct 8, 2017

Line 154 indentation done peoperly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.