Last active
March 28, 2023 23:40
-
-
Save brpowell/c8b778af7b51f69bdccc to your computer and use it in GitHub Desktop.
Dropbox ROM syncing
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
# - write token and cursor to .romsync | |
# * update cursor every delta check | |
# * config file format | |
# token=token_string | |
# cursor=cursor_string | |
# db_roms=path_to_dropbox_roms | |
# local_roms=path_to_local_roms | |
# * upload new config to dropbox | |
import os | |
import dropbox | |
app_key = os.environ['DROPBOX_APP_KEY'] | |
app_secret = os.environ['DROPBOX_APP_SECRET'] | |
DEBUG = 0 | |
class Config(object): | |
settings = {} | |
path = '' | |
def __init__(self, path=os.getenv("HOME") + '/.romsync'): | |
self.path = path | |
self.load() | |
# Return value of setting | |
def get(self, key): | |
return self.settings[key] | |
# Update the cursor | |
def set_cursor(self, cursor): | |
self.settings['cursor'] = cursor | |
# Write settings to config | |
def write(self): | |
open(self.path, 'w').close() # Flush config before writing | |
with open(self.path, 'w') as cfg: | |
for key in self.settings: | |
cfg.write(key + '=' + self.settings[key] + '\n') | |
# Load settings from config | |
def load(self): | |
if os.path.isfile(self.path): | |
with open(self.path, 'r') as cfg: | |
for line in cfg: | |
key = line.replace(" ", "").split('=')[0] | |
value = line.replace(" ", "").split('=')[1].rstrip() | |
self.settings[key] = value | |
else: | |
with open(self.path, 'w') as cfg: | |
# Begin flow | |
flow = dropbox.client.DropboxOAuth2FlowNoRedirect(app_key, app_secret) | |
authorize_url = flow.start() | |
# Get authorization code | |
print('1. Go to: ' + authorize_url) | |
print('2. Click "Allow" (you might have to log in first)') | |
print('3. Copy the authorization code.') | |
code = input('Enter the authorization code here: ').strip() | |
local_path = input('Enter your local roms directory: ') | |
access_token, user_id = flow.finish(code) | |
# Write code to config | |
cfg.write('access_token=' + access_token + '\n') | |
cfg.write('db_roms=/romsync\n') | |
cfg.write('local_roms=' + local_path + '\n') | |
cfg.write('cursor= ' + '\n') | |
# Download/remove files and directories | |
# return: dictionary of modified files | |
def sync(client, delta, config): | |
dirs = [] | |
files = [] | |
file_change = {'added': [], 'removed': []} | |
entries = delta['entries'] | |
local_path = config.get('local_roms') | |
db_path = config.get('db_roms') | |
for e in entries: | |
if(e[1] != None): | |
path = e[1]['path'].replace(db_path, local_path) | |
if(e[1]['is_dir']): | |
if(len(path) > 0): | |
os.makedirs(path) | |
else: | |
out = open(path, 'wb') | |
with client.get_file(e[1]['path']) as rom: | |
out.write(rom.read()) | |
file_change['added'].append(path.replace(local_path, '')) | |
else: | |
path = e[0].replace(db_path, local_path) | |
try: | |
if os.path.isdir(path): | |
shutil.rmtree(path) | |
for child in os.listdir(path): | |
file_change['removed'].append(child) | |
else: | |
os.remove(path) | |
file_change['removed'].append(path.replace(local_path, '')) | |
except: | |
if(DEBUG): | |
print(path, ' does not exist') | |
return file_change | |
def main(): | |
config = Config() | |
config.load() | |
# Get client | |
client = dropbox.client.DropboxClient(config.get('access_token')) | |
delta = client.delta(path_prefix=config.get('db_roms'), cursor=config.get('cursor')) | |
if DEBUG: | |
print(delta) | |
if(len(delta['entries']) > 0): | |
print('Syncing roms...') | |
file_change = sync(client, delta, config) | |
added = len(file_change['added']) | |
removed = len(file_change['removed']) | |
if(added > 0): | |
print('\n'+'Fetched %s rom(s)' % str(added)) | |
for entry in file_change['added']: | |
print(entry) | |
if(removed > 0): | |
print('\n'+'Removed %s rom(s)' % str(removed)) | |
for entry in file_change['removed']: | |
print(entry) | |
print('') | |
else: | |
print('No need to sync') | |
config.set_cursor(delta['cursor']) | |
config.write() | |
if __name__ == "__main__": | |
main() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there a way to configure this to only save the...save files? My Dropbox account is already almost full, and save files (sram and savestate files) are really the only ones I'm concerned with backing up; my ROM folder is on Google Drive since they offer more space for free.