def run(self): config.log.info('syncer starts running') self.conn = sqlite3.connect(DAEMON_DB_PATH, isolation_level = None) self.conn.row_factory = sqlite3.Row self.cursor = self.conn.cursor() # when switch is set, the thread should stop while not self.switch.is_set(): # block until there is something in the queue self.empty_lock.wait() # clear task queue while not self.switch.is_set() and not self.queue.empty(): entry = self.queue.get() try: self.merge_dir(entry) except live_api.AuthError as e: config.log.error(e.__class__.__name__ + ': ' + str(e)) app_tokens = self.api.refresh_token(config.APP_CONFIG['token']['refresh_token']) self.api.set_access_token(app_tokens['access_token']) config.save_token(app_tokens) config.save_config() self.enqueue(entry[0], entry[1]) except live_api.NetworkError: config.log.error('Network error. Wait for {} seconds.'.format(NETWORKERR_WAIT_INTERVAL)) time.sleep(NETWORKERR_WAIT_INTERVAL) self.enqueue(entry) self.queue.task_done() self.empty_lock.clear() config.log.debug('queue is now empty.') self.conn.close() config.log.info('syncer stops.')
def show_auth_dialog(self): print('=' * 30) if not query_yes_no( 'Do you want to authorize onedrive-d to access your OneDrive account?' ): print(' Skipped.') return print( '\nYou will need to visit the OneDrive authorization page manually, ' ) print( 'log in and authorize the onedrive-d, and then copy and paste the ' ) print('callback URL, which should start with \n"%s".\n' % self.api.client_redirect_uri) print( 'The callback url is the URL when the authorization page finally goes blank.\n' ) print('Please visit the authorization page via URL:\n') print(self.api.get_auth_uri()) callback_uri = input('\nPlease paste the callback URL:\n') try: app_tokens = self.api.get_access_token(uri=callback_uri) config.save_token(app_tokens) config.save_config() print('\nonedrive-d has been successfully authorized.') except OneDrive_Error as e: print( 'CRITICAL: failed to authorize the client with the given URL.') print('%s' % e)
def handle(self, event_id, event_args=None): print('Dialog object received {} event.'.format(event_id)) if event_id == 'refresh_code': app_tokens = self.api.get_access_token(uri=event_args) config.save_token(app_tokens) config.save_config() elif event_id == 'child_close': pass
def run(self): config.log.info('worker starts running.') self.conn = sqlite3.connect(DAEMON_DB_PATH, isolation_level = None) self.conn.row_factory = sqlite3.Row self.cursor = self.conn.cursor() while True: self.sem.acquire() if self.switch.is_set(): break config.log.debug('I passed two locks.') row = self.fetch_one_task() if row == None: continue config.log.debug('I get a row from tasks table.') try: if row['task_type'] == 'get': config.log.info('Downloading "' + row['local_path'] + '".') f = open(row['local_path'], 'wb') f.write(self.api.get(entry_id = row['remote_id'])) f.close() #new_mtime = timegm) #os.utime(t.p1, (new_mtime, new_mtime)) self.do_postwork(row) self.delete_task(row) self.add_notify('local', row['local_path'], 'downloaded') elif row['task_type'] == 'put': config.log.info('Uploading "' + row['local_path'] + '".') if os.path.isdir(row['local_path']): # if the path is a dir, recursive put ne = self.op_mkdir(row) for item in os.listdir(row['local_path']): self.add_work('put', row['local_path'] + '/' + item, remote_parent_id = ne['id'], postwork = 'n') else: update = self.api.put(name = os.path.basename(row['local_path']), folder_id = row['remote_parent_id'], local_path = row['local_path']) self.do_postwork(row, update) self.delete_task(row) self.add_notify('local', row['local_path'], 'uploaded') elif row['task_type'] == 'mkdir': self.op_mkdir(row) self.add_notify('remote', row['local_path'], 'created') # no special postwork to do elif row['task_type'] in ['rm', 'moved_from']: config.log.info('Delete remotely "' + row['local_path'] + '"') self.api.rm(entry_id = row['remote_id']) self.do_postwork(row) self.add_notify('remote', row['local_path'], 'deleted') # TODO: update entries db. elif row['task_type'] == 'cp': config.log.info('Copying remotely "' + row['local_path'] + '" to dir "' + row['remote_parent_id'] + '"') self.api.cp(target_id = row['remote_id'], dest_folder_id = row['remote_parent_id']) # TODO: update entries db. elif row['task_type'] == 'mv': dirname, basename = os.path.split(row['local_path']) config.log.info('Moving remotely "' + row['local_path'] + '" to dir "' + row['remote_parent_id'] + '"') ret = self.api.mv(target_id = row['remote_id'], dest_folder_id = row['remote_parent_id']) self.cursor.execute('UPDATE entries SET parent_path=?, name=?, id=?, ' + 'parent_id=?, client_updated_time=?, status="synced" WHERE id=?', (dirname, basename, ret['id'], ret['parent_id'], ret['client_updated_time'], row['remote_id'])) #t = config.str_to_timestamp(ret['client_updated_time']) #os.utime(row['local_path'], (t, t)) # self.cursor.execute() self.conn.commit() elif row['task_type'] == 'clean': # move the local path to local trash. # the path has been deleted remotely. self.move_to_trash(row['local_path']) self.add_notify('local', row['local_path'], 'moved to trash') self.delete_task(row) time.sleep(WORKER_EVENT_INTERVAL) except live_api.AuthError as e: config.log.error(e.__class__.__name__ + ': ' + str(e)) app_tokens = self.api.refresh_token(config.APP_CONFIG['token']['refresh_token']) self.api.set_access_token(app_tokens['access_token']) config.save_token(app_tokens) config.save_config() self.reset_task(row) except live_api.NetworkError: config.log.error('Network error. Wait for {} seconds.'.format(NETWORKERR_WAIT_INTERVAL)) time.sleep(NETWORKERR_WAIT_INTERVAL) self.reset_task(row) #except live_api.OneDrive_Error as e: # config.log.error(e.__class__.__name__ + ': ' + str(e)) except OSError as e: config.log.error('OSError {0}: {1}. Path: {2}.'.format(e.errno, e.strerr, e.filename)) self.parent.notify_all() self.conn.close() config.log.info('worker stops.')
def main(): # print help info if '--help' is a cmd arg if '--help' in sys.argv: print_help() sys.exit(0) api = live_api.OneDrive_API(config.APP_CLIENT_ID, config.APP_CLIENT_SECRET) app_tokens = config.get_token() if app_tokens == None: token_invalid = True if config.has_token(): # try to refresh the token try: app_tokens = api.refresh_token(config.APP_CONFIG['token']['refresh_token']) config.save_token(app_tokens) config.save_config() token_invalid = False except live_api.NetworkError: print('Failed to reach OneDrive server. Please check your internet connection.') sys.exit(1) except live_api.AuthError: print('The client authorization has expired.') if '--no-prompt' in sys.argv: print('Please run `onedrive-prefs` to authorize the client.') sys.exit(1) if token_invalid: # failed to renew the token, show pref dialog # the pref program should guide users to set up all confs. if '--no-gui' in sys.argv: pass else: pass if not config.test_base_path(): print('Path of local OneDrive repository is unset or invalid. Exit.') sys.exit(1) api.set_access_token(config.APP_CONFIG['token']['access_token']) # now start the threads # the MainThread is used for heart-beating from daemon import OneDrive_DaemonThread daemon_lock = threading.Event() daemon_thread = OneDrive_DaemonThread(api, daemon_lock) ui_component = '' for arg in sys.argv: if arg.startswith('--ui='): ui_component = arg.split('=')[1] break observer_thread = None if ui_component == 'gtk': from observer_gtk import OneDrive_Observer observer_thread = OneDrive_Observer() elif ui_component != '': print('The UI component "' + ui_component + '" is not found. Exit.') sys.exit(1) if observer_thread != None: daemon_thread.add_observer(observer_thread) observer_thread.start() # heart-beating for MainThread try: daemon_thread.start() while True: daemon_lock.set() time.sleep(DAEMON_PULL_INTERVAL) except KeyboardInterrupt: config.log.info('propagating stop signals.') daemon_thread.stop() if observer_thread != None: observer_thread.stop() observer_thread.join() daemon_thread.join() sys.exit(0)