Recommended Posts

Posted

Hey everyone, 

 

We have some sample code in case anyone finds this helpful. 

 

 filename: api_sample.py 

import httplibimport urllibimport jsonimport osimport subprocessimport base64import shutilimport timeimport platformAPI_KEY = 'XXX' # INSERT YOUR API KEY HERE!btsyncbin_mac = 'BitTorrent Sync.app/Contents/MacOS/BitTorrent Sync'btsyncbin_win = 'BTSync.exe'btsyncbin_linux = 'btsync'config_param_posix = '--config'config_param_win = '/config'class SyncInstance:    def __init__(self, configName, storagePath, port):        self.port = port        self.configPath = os.path.join(os.getcwd(), configName)        self.storagePath = os.path.join(os.getcwd(), storagePath)         shutil.rmtree(self.storagePath, True)         os.mkdir(self.storagePath)         config = {}         config['storage_path'] = self.storagePath         config['use_gui'] = False        webuiConfig = {}        webuiConfig['login'] = 'apitest'        webuiConfig['password'] = 'apipass'        webuiConfig['listen'] = '127.0.0.1:%d' % port        webuiConfig['api_key'] = API_KEY        config['webui'] = webuiConfig        configFile = open(self.configPath, 'w')        json.dump(config, configFile)        configFile.close()    def launch(self):        if platform.system() == 'Windows':            btsyncbin = btsyncbin_win            configParam = config_param_win        elif platform.system() == 'Darwin':            btsyncbin = btsyncbin_mac            configParam = config_param_posix        else:            btsyncbin = btsyncbin_linux            configParam = config_param_posix           binaryPath = os.path.join(os.getcwd(), btsyncbin)         subprocess.Popen([binaryPath, configParam, self.configPath])    def request(self, request):        try:            conn = httplib.HTTPConnection('localhost:%d' % self.port)            headers = {'Authorization': 'Basic ' + base64.b64encode('apitest:apipass')}            params = urllib.urlencode(request)            conn.request('GET', '/api?' + params, '', headers)            resp = conn.getresponse()            if resp.status == 200:                return json.load(resp)            else:                return None        except:            return Nonedef writeFile(folder, filename, count):    f = open(os.path.join(folder, filename), 'w+')    for i in range(1, count):        f.write('%d' % i )    f.close()def main():    if API_KEY == 'XXX':        print 'In order to run this sample code please insert a valid API key!'        return 1    instance1 = SyncInstance('sync1.conf', 'storagepath1', 8888)    instance2 = SyncInstance('sync2.conf', 'storagepath2', 8889)    instance1.launch()    instance2.launch()    print 'Waiting for the BitTorrent Sync instances to start...'    while True:        version1 = instance1.request({'method' : 'get_version'})        version2 = instance2.request({'method' : 'get_version'})        if version1 is not None and version2 is not None:            break        time.sleep(0.2)    print 'Generating secrets on the first instance...'    secret = instance1.request({'method' : 'get_secrets', 'type' : 'encryption'})    print secret    syncFolderPath1 = os.path.join(os.getcwd(), 'path1')    shutil.rmtree(syncFolderPath1, True)    os.mkdir(syncFolderPath1)    writeFile(syncFolderPath1, 'file1', 300)    writeFile(syncFolderPath1, 'file2', 500)    print 'Adding a folder on the first instance via read-write secret...'    addFolderRes = instance1.request({'method' : 'add_folder', 'dir' : syncFolderPath1, 'secret' : secret['read_write']})    if 'error' in addFolderRes and addFolderRes['error'] != 0:        print 'Error %d while adding folder' % addFolderRes['error']    folders = instance1.request({'method' : 'get_folders', 'secret' : secret['read_write']})    print folders    print 'Waiting while the files are being indexed...'    while True:        folders = instance1.request({'method' : 'get_folders', 'secret' : secret['read_write']})        if folders and folders[0]['indexing'] == 0 and folders[0]['files'] == 2:            break        time.sleep(0.2)    print folders    print 'Getting a file list on the first instance...'    files = instance1.request({'method' : 'get_files', 'secret' : secret['read_write']})    print files    syncFolderPath2 = os.path.join(os.getcwd(), 'path2')    shutil.rmtree(syncFolderPath2, True)    os.mkdir(syncFolderPath2)    print 'Adding a folder to the second instance via read-only secret...'    addFolderRes = instance2.request({'method' : 'add_folder', 'dir' : syncFolderPath2, 'secret' : secret['read_only'], 'selective_sync' : 1})    if 'error' in addFolderRes and addFolderRes['error'] != 0:        print 'Error %d while adding folder' % addFolderRes['error']    print 'Receiving the file list on the second instance...'    while True:        files = instance2.request({'method' : 'get_files', 'secret' : secret['read_only']})        if files:            break        time.sleep(0.2)        print 'Selecting "file2" for download on the second instance...'    fileRes = instance2.request({'method' : 'set_file_prefs', 'secret' : secret['read_only'], 'path' : 'file2', 'download' : 1})    print fileRes        print 'Downloading "file2"...'    while True:        fileRes = instance2.request({'method' : 'get_files', 'secret' : secret['read_only'], 'path' : 'file2'})        if fileRes and fileRes[0]['have_pieces'] == fileRes[0]['total_pieces']:            break        time.sleep(0.2)     print fileRes    print 'Download finished'    print 'Shutting down the BitTorrent Sync instances...'    instance1.request({'method' : 'shutdown'})    instance2.request({'method' : 'shutdown'})main()
Posted

Nice code, but seems not to run, i think i need a valid api key :) (i've tried to substitute XXX with a casual string :) )

 

I asked for api with the form yesterday, but still received nothing on my email :(.

 

Actually the problem (i think API KEY related) is 

Process

[btsync] <defunct>

 

Application waiting

"Waiting while the files are being indexed..."

 

Hope i receive (if i'm fine with my intent) the API KEY

Thank you

Antimo

Posted

How is the API key checked? Does it require a network connection? Or is it "self-contained" for offline use? How is it intended if one wants to ship an application where sync is integrated, is one allowed to distribute one's API key (which would be readable to every user due to the config file) or would every user need to get their own API key?

 

Thanks for clarifying!

Posted

API is self contained - so it will work offline.

 

When distributing the app you have one key per app and generate login/password for each users. Please make sure to make it unique. 

  • 10 months later...
Posted

Is this code expected to successfully run as-is? I subbed in my API key, obviously. But it hangs with this output:

 

Waiting for the BitTorrent Sync instances to start...

Generating secrets on the first instance...

{u'read_only': u'EBZCSES4ELT4TO4TXG6EKDTQZYWVIWMNS3K3Q3B67LBHDPOBW7HKXA2MMN4', u'encryption': u'FBZCSES4ELT4TO4TXG6EKDTQZYWVIWMNS', u'read_write': u'D7KY7CVTW7N6SQFT2GDOYP4U3HOSVIB2X'}

Adding a folder on the first instance via read-write secret...

Error 105 while adding folder

[]

Waiting while the files are being indexed...

Posted

It was designed to work out of the box, though some changes in 1.4 broke it. The error "105" means "folder not empty" and simply need to be overridden with "force=1" parameter. Please see below the adjusted script - should work fine with 1.4. I also adjusted API manual article to reflect ability to "force" folder creation.
 
 

import httplibimport urllibimport jsonimport osimport subprocessimport base64import shutilimport timeimport platformAPI_KEY = 'XXX' # INSERT YOUR API KEY HERE!btsyncbin_mac = 'BitTorrent Sync.app/Contents/MacOS/BitTorrent Sync'btsyncbin_win = 'BTSync.exe'btsyncbin_linux = 'btsync'config_param_posix = '--config'config_param_win = '/config'class SyncInstance:    def __init__(self, configName, storagePath, port):        self.port = port        self.configPath = os.path.join(os.getcwd(), configName)        self.storagePath = os.path.join(os.getcwd(), storagePath)         shutil.rmtree(self.storagePath, True)         os.mkdir(self.storagePath)         config = {}         config['storage_path'] = self.storagePath         config['use_gui'] = False        webuiConfig = {}        webuiConfig['login'] = 'apitest'        webuiConfig['password'] = 'apipass'        webuiConfig['listen'] = '127.0.0.1:%d' % port        webuiConfig['api_key'] = API_KEY        config['webui'] = webuiConfig        configFile = open(self.configPath, 'w')        json.dump(config, configFile)        configFile.close()    def launch(self):        if platform.system() == 'Windows':            btsyncbin = btsyncbin_win            configParam = config_param_win        elif platform.system() == 'Darwin':            btsyncbin = btsyncbin_mac            configParam = config_param_posix        else:            btsyncbin = btsyncbin_linux            configParam = config_param_posix           binaryPath = os.path.join(os.getcwd(), btsyncbin)         subprocess.Popen([binaryPath, configParam, self.configPath])    def request(self, request):        try:            conn = httplib.HTTPConnection('localhost:%d' % self.port)            headers = {'Authorization': 'Basic ' + base64.b64encode('apitest:apipass')}            params = urllib.urlencode(request)            conn.request('GET', '/api?' + params, '', headers)            resp = conn.getresponse()            if resp.status == 200:                return json.load(resp)            else:                return None        except:            return Nonedef writeFile(folder, filename, count):    f = open(os.path.join(folder, filename), 'w+')    for i in range(1, count):        f.write('%d' % i )    f.close()def main():    if API_KEY == 'XXX':        print 'In order to run this sample code please insert a valid API key!'        return 1    instance1 = SyncInstance('sync1.conf', 'storagepath1', 8888)    instance2 = SyncInstance('sync2.conf', 'storagepath2', 8889)    instance1.launch()    instance2.launch()    print 'Waiting for the BitTorrent Sync instances to start...'    while True:        version1 = instance1.request({'method' : 'get_version'})        version2 = instance2.request({'method' : 'get_version'})        if version1 is not None and version2 is not None:            break        time.sleep(0.2)    print 'Generating secrets on the first instance...'    secret = instance1.request({'method' : 'get_secrets', 'type' : 'encryption'})    print secret    syncFolderPath1 = os.path.join(os.getcwd(), 'path1')    shutil.rmtree(syncFolderPath1, True)    os.mkdir(syncFolderPath1)    writeFile(syncFolderPath1, 'file1', 300)    writeFile(syncFolderPath1, 'file2', 500)    print 'Adding a folder on the first instance via read-write secret...'    addFolderRes = instance1.request({'method' : 'add_folder', 'dir' : syncFolderPath1, 'secret' : secret['read_write'], 'force' : '1'})    if 'error' in addFolderRes and addFolderRes['error'] != 0:        print 'Error %d while adding folder' % addFolderRes['error']    folders = instance1.request({'method' : 'get_folders', 'secret' : secret['read_write']})    print folders    print 'Waiting while the files are being indexed...'    while True:        folders = instance1.request({'method' : 'get_folders', 'secret' : secret['read_write']})        if folders and folders[0]['indexing'] == 0 and folders[0]['files'] == 2:            break        time.sleep(0.2)    print folders    print 'Getting a file list on the first instance...'    files = instance1.request({'method' : 'get_files', 'secret' : secret['read_write']})    print files    syncFolderPath2 = os.path.join(os.getcwd(), 'path2')    shutil.rmtree(syncFolderPath2, True)    os.mkdir(syncFolderPath2)    print 'Adding a folder to the second instance via read-only secret...'    addFolderRes = instance2.request({'method' : 'add_folder', 'dir' : syncFolderPath2, 'secret' : secret['read_only'], 'selective_sync' : 1, 'force' : '1'})    if 'error' in addFolderRes and addFolderRes['error'] != 0:        print 'Error %d while adding folder' % addFolderRes['error']    print 'Receiving the file list on the second instance...'    while True:        files = instance2.request({'method' : 'get_files', 'secret' : secret['read_only']})        if files:            break        time.sleep(0.2)        print 'Selecting "file2" for download on the second instance...'    fileRes = instance2.request({'method' : 'set_file_prefs', 'secret' : secret['read_only'], 'path' : 'file2', 'download' : 1})    print fileRes        print 'Downloading "file2"...'    while True:        fileRes = instance2.request({'method' : 'get_files', 'secret' : secret['read_only'], 'path' : 'file2'})        if fileRes and fileRes[0]['have_pieces'] == fileRes[0]['total_pieces']:            break        time.sleep(0.2)     print fileRes    print 'Download finished'    print 'Shutting down the BitTorrent Sync instances...'    instance1.request({'method' : 'shutdown'})    instance2.request({'method' : 'shutdown'})main()

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.