def delete_variant(request, project_id, resource_id, variant): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) if variant == '0': variant = '' variant_to_delete = resource.variants.get(tags=variant) if resource.variants.count() == 1: return json_failure("You cannot delete the last remaining variant of a resource.") try: variant_to_delete.delete() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_delete_variant', data={ 'data': { 'filename': resource.file_name, 'kind': 'resource', 'resource-kind': resource.kind, 'variant': variant } }, project=project, request=request) return json_response({'resource': { 'variants': [x.get_tags() for x in resource.variants.all()] }})
def delete_project(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) if not bool(request.POST.get('confirm', False)): return json_failure("Not confirmed") try: project.delete() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_delete_project', project=project, request=request) return json_response({})
def login_action(request): username = request.REQUEST['username'] password = request.REQUEST['password'] user = authenticate(username=username, password=password) if user is None: return json_failure(_("Invalid username or password")) if not user.is_active: return json_failure(_("Account disabled.")) login(request, user) return json_response()
def load_source_file(request, project_id, file_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) source_file = get_object_or_404(SourceFile, pk=file_id, project=project) try: content = source_file.get_contents() try: folded_lines = json.loads(source_file.folded_lines) except ValueError: folded_lines = [] send_keen_event('cloudpebble', 'cloudpebble_open_file', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) except Exception as e: return json_failure(str(e)) else: return json_response({ "success": True, "source": content, "modified": time.mktime(source_file.last_modified.utctimetuple()), "folded_lines": folded_lines })
def import_github(request): name = request.POST['name'] repo = request.POST['repo'] branch = request.POST['branch'] add_remote = (request.POST['add_remote'] == 'true') match = re.match( r'^(?:https?://|git@|git://)?(?:www\.)?github\.com[/:]([\w.-]+)/([\w.-]+?)(?:\.git|/|$)', repo) if match is None: return HttpResponse(json.dumps({ "success": False, 'error': _("Invalid Github URL.") }), content_type="application/json") github_user = match.group(1) github_project = match.group(2) try: project = Project.objects.create(owner=request.user, name=name) except IntegrityError as e: return json_failure(str(e)) if add_remote: project.github_repo = "%s/%s" % (github_user, github_project) project.github_branch = branch project.save() task = do_import_github.delay(project.id, github_user, github_project, branch, delete_project=True) return json_response({'task_id': task.task_id, 'project_id': project.id})
def save_source_file(request, project_id, file_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) source_file = get_object_or_404(SourceFile, pk=file_id, project=project) try: expected_modification_time = datetime.datetime.fromtimestamp(int(request.POST['modified'])) if source_file.last_modified.replace(tzinfo=None, microsecond=0) > expected_modification_time: send_keen_event('cloudpebble', 'cloudpebble_save_abort_unsafe', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) raise Exception("Could not save: file has been modified since last save.") source_file.save_file(request.POST['content']) except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_save_file', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) return json_response({"modified": time.mktime(source_file.last_modified.utctimetuple())})
def launch_emulator(request): user_id = request.user.id platform = request.POST['platform'] oauth = request.POST['token'] tz_offset = request.POST['tz_offset'] versions = { 'aplite': '2.9', 'basalt': '3.0', } version = versions[platform] redis_key = 'qemu-user-%s-%s' % (user_id, platform) qemu_instance = redis_client.get(redis_key) if qemu_instance is not None: qemu_instance = json.loads(qemu_instance) try: response = requests.post(qemu_instance['ping_url'], timeout=2, verify=settings.COMPLETION_CERTS) response.raise_for_status() response = response.json() except (requests.RequestException, ValueError) as e: print "couldn't fetch old instance: %s" % e pass else: if response.get('alive', False): return json_response(qemu_instance) else: print "old instance is dead." token = _generate_token() servers = set(settings.QEMU_URLS) while len(servers) > 0: server = random.choice(list(servers)) servers.remove(server) try: result = requests.post(server + 'qemu/launch', data={'token': token, 'platform': platform, 'version': version, 'oauth': oauth, 'tz_offset': tz_offset}, headers={'Authorization': settings.QEMU_LAUNCH_AUTH_HEADER}, timeout=15, verify=settings.COMPLETION_CERTS) result.raise_for_status() response = result.json() url = urlparse.urlsplit(server) response['host'] = url.hostname response['secure'] = (url.scheme == 'https') response['api_port'] = url.port or (443 if url.scheme == 'https' else 80) response['ping_url'] = '%sqemu/%s/ping' % (server, response['uuid']) response['kill_url'] = '%sqemu/%s/kill' % (server, response['uuid']) response['token'] = token redis_client.set(redis_key, json.dumps(response)) return json_response(response) except requests.HTTPError as e: print e.response.text except (requests.RequestException, ValueError) as e: print e pass return json_failure("Unable to create emulator instance.")
def save_source_file(request, project_id, file_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) source_file = get_object_or_404(SourceFile, pk=file_id, project=project) try: if source_file.was_modified_since(int(request.POST['modified'])): send_td_event('cloudpebble_save_abort_unsafe', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, request=request, project=project) raise Exception(_("Could not save: file has been modified since last save.")) source_file.save_file(request.POST['content'], folded_lines=request.POST['folded_lines']) except Exception as e: return json_failure(str(e)) else: send_td_event('cloudpebble_save_file', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, request=request, project=project) return json_response({"modified": time.mktime(source_file.last_modified.utctimetuple())})
def create_project(request): name = request.POST['name'] template_id = request.POST.get('template', None) project_type = request.POST.get('type', 'native') try: with transaction.commit_on_success(): project = Project.objects.create( name=name, owner=request.user, sdk_version=2, app_company_name=request.user.username, app_short_name=name, app_long_name=name, app_version_code=1, app_version_label='1.0', app_is_watchface=False, app_capabilities='', project_type=project_type ) if template_id is not None and int(template_id) != 0: template = TemplateProject.objects.get(pk=int(template_id)) template.copy_into_project(project) elif project_type == 'simplyjs': f = SourceFile.objects.create(project=project, file_name="app.js") f.save_file(open('{}/src/html/demo.js'.format(settings.SIMPLYJS_ROOT)).read()) except IntegrityError as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_project', project=project, request=request) return json_response({"id": project.id})
def create_resource(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) kind = request.POST['kind'] resource_ids = json.loads(request.POST['resource_ids']) file_name = request.FILES['file'].name resources = [] try: with transaction.commit_on_success(): rf = ResourceFile.objects.create(project=project, file_name=file_name, kind=kind) for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None resources.append(ResourceIdentifier.objects.create(resource_file=rf, resource_id=r['id'], character_regex=regex, tracking=tracking)) rf.save_file(request.FILES['file'], request.FILES['file'].size) except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_file', data={ 'data': { 'filename': file_name, 'kind': 'resource', 'resource-kind': kind } }, project=project, request=request) return json_response({"file": { "id": rf.id, "kind": rf.kind, "file_name": rf.file_name, "resource_ids": [{'id': x.resource_id, 'regex': x.character_regex} for x in resources], "identifiers": [x.resource_id for x in resources] }})
def update_resource(request, project_id, resource_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) resource_ids = json.loads(request.POST['resource_ids']) try: with transaction.commit_on_success(): # Lazy approach: delete all the resource_ids and recreate them. # We could do better. resources = [] ResourceIdentifier.objects.filter(resource_file=resource).delete() for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None resources.append(ResourceIdentifier.objects.create(resource_file=resource, resource_id=r['id'], character_regex=regex, tracking=tracking)) if 'file' in request.FILES: resource.save_file(request.FILES['file'], request.FILES['file'].size) except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_save_file', data={ 'data': { 'filename': resource.file_name, 'kind': 'source' } }, project=project, request=request) return json_response({"file": { "id": resource.id, "kind": resource.kind, "file_name": resource.file_name, "resource_ids": [{'id': x.resource_id, 'regex': x.character_regex} for x in resources], "identifiers": [x.resource_id for x in resources] }})
def save_project_settings(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) try: with transaction.commit_on_success(): project.name = request.POST['name'] project.app_uuid = request.POST['app_uuid'] project.app_company_name = request.POST['app_company_name'] project.app_short_name = request.POST['app_short_name'] project.app_long_name = request.POST['app_long_name'] project.app_version_code = int(request.POST['app_version_code']) project.app_version_label = request.POST['app_version_label'] project.app_is_watchface = bool(int(request.POST['app_is_watchface'])) project.app_capabilities = request.POST['app_capabilities'] project.app_keys = request.POST['app_keys'] project.app_jshint = bool(int(request.POST['app_jshint'])) menu_icon = request.POST['menu_icon'] if menu_icon != '': menu_icon = int(menu_icon) old_icon = project.menu_icon if old_icon is not None: old_icon.is_menu_icon = False old_icon.save() icon_resource = project.resources.filter(id=menu_icon)[0] icon_resource.is_menu_icon = True icon_resource.save() project.save() except IntegrityError as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_save_project_settings', project=project, request=request) return json_response({})
def rename_source_file(request, project_id, file_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) source_file = get_object_or_404(SourceFile, pk=file_id, project=project) old_filename = source_file.file_name try: if source_file.file_name != request.POST['old_name']: send_keen_event('cloudpebble', 'cloudpebble_rename_abort_unsafe', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) raise Exception(_("Could not rename, file has been renamed already.")) if source_file.was_modified_since(int(request.POST['modified'])): send_keen_event('cloudpebble', 'cloudpebble_rename_abort_unsafe', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) raise Exception(_("Could not rename, file has been modified since last save.")) source_file.file_name = request.POST['new_name'] source_file.save() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_rename_file', data={ 'data': { 'old_filename': old_filename, 'new_filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) return json_response({"modified": time.mktime(source_file.last_modified.utctimetuple())})
def create_resource(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) kind = request.POST['kind'] resource_ids = json.loads(request.POST['resource_ids']) file_name = request.FILES['file'].name resources = [] try: with transaction.commit_on_success(): rf = ResourceFile.objects.create(project=project, file_name=file_name, kind=kind) for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None resources.append( ResourceIdentifier.objects.create(resource_file=rf, resource_id=r['id'], character_regex=regex, tracking=tracking)) rf.save_file(request.FILES['file'], request.FILES['file'].size) except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_file', data={ 'data': { 'filename': file_name, 'kind': 'resource', 'resource-kind': kind } }, project=project, request=request) return json_response({ "file": { "id": rf.id, "kind": rf.kind, "file_name": rf.file_name, "resource_ids": [{ 'id': x.resource_id, 'regex': x.character_regex } for x in resources], "identifiers": [x.resource_id for x in resources], "extra": { y.resource_id: { 'regex': y.character_regex, 'tracking': y.tracking } for y in rf.identifiers.all() } } })
def import_zip(request): zip_file = request.FILES['archive'] name = request.POST['name'] try: project = Project.objects.create(owner=request.user, name=name) except IntegrityError as e: return json_failure(str(e)) task = do_import_archive.delay(project.id, zip_file.read(), delete_project=True) return json_response({'task_id': task.task_id, 'project_id': project.id})
def create_project(request): name = request.POST['name'] template_id = request.POST.get('template', None) if template_id is not None: template_id = int(template_id) project_type = request.POST.get('type', 'native') template_name = None sdk_version = request.POST.get('sdk', 2) try: with transaction.commit_on_success(): project = Project.objects.create( name=name, owner=request.user, app_company_name=request.user.username, app_short_name=name, app_long_name=name, app_version_label='1.0', app_is_watchface=False, app_capabilities='', project_type=project_type, sdk_version=sdk_version, ) if template_id is not None and template_id != 0: template = TemplateProject.objects.get(pk=template_id) template_name = template.name template.copy_into_project(project) elif project_type == 'simplyjs': f = SourceFile.objects.create(project=project, file_name="app.js") f.save_file( open('{}/src/html/demo.js'.format( settings.SIMPLYJS_ROOT)).read()) elif project_type == 'pebblejs': f = SourceFile.objects.create(project=project, file_name="app.js") f.save_file( open('{}/src/js/app.js'.format( settings.PEBBLEJS_ROOT)).read()) except IntegrityError as e: return json_failure(str(e)) else: send_keen_event( 'cloudpebble', 'cloudpebble_create_project', {'data': { 'template': { 'id': template_id, 'name': template_name } }}, project=project, request=request) return json_response({"id": project.id})
def list_phones(request): user_key = request.user.social_auth.get(provider='pebble').extra_data['access_token'] response = requests.get( '{0}/api/v1/me.json'.format(settings.SOCIAL_AUTH_PEBBLE_ROOT_URL), headers={'Authorization': 'Bearer {0}'.format(user_key)}, params={'client_id': settings.SOCIAL_AUTH_PEBBLE_KEY}) if response.status_code != 200: return json_failure(response.reason) else: devices = response.json()['devices'] return json_response({'devices': devices})
def update_resource(request, project_id, resource_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) resource_ids = json.loads(request.POST['resource_ids']) try: with transaction.commit_on_success(): # Lazy approach: delete all the resource_ids and recreate them. # We could do better. resources = [] ResourceIdentifier.objects.filter(resource_file=resource).delete() for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None resources.append( ResourceIdentifier.objects.create(resource_file=resource, resource_id=r['id'], character_regex=regex, tracking=tracking)) if 'file' in request.FILES: resource.save_file(request.FILES['file'], request.FILES['file'].size) except Exception as e: return json_failure(str(e)) else: send_keen_event( 'cloudpebble', 'cloudpebble_save_file', data={'data': { 'filename': resource.file_name, 'kind': 'source' }}, project=project, request=request) return json_response({ "file": { "id": resource.id, "kind": resource.kind, "file_name": resource.file_name, "resource_ids": [{ 'id': x.resource_id, 'regex': x.character_regex } for x in resources], "identifiers": [x.resource_id for x in resources] } })
def list_phones(request): user_key = request.user.social_auth.get( provider='pebble').extra_data['access_token'] response = requests.get( '{0}/api/v1/me.json'.format(settings.SOCIAL_AUTH_PEBBLE_ROOT_URL), headers={'Authorization': 'Bearer {0}'.format(user_key)}, params={'client_id': settings.SOCIAL_AUTH_PEBBLE_KEY}) if response.status_code != 200: return json_failure(response.reason) else: devices = response.json()['devices'] return json_response({'devices': devices})
def list_phones(request): user_key = request.user.social_auth.get(provider="pebble").extra_data["access_token"] response = requests.get( "{0}/api/v1/me.json".format(settings.SOCIAL_AUTH_PEBBLE_ROOT_URL), headers={"Authorization": "Bearer {0}".format(user_key)}, params={"client_id": settings.SOCIAL_AUTH_PEBBLE_KEY}, ) if response.status_code != 200: return json_failure(response.reason) else: devices = response.json()["devices"] return json_response({"devices": devices})
def delete_source_file(request, project_id, file_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) source_file = get_object_or_404(SourceFile, pk=file_id, project=project) try: source_file.delete() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_delete_file', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) return json_response({})
def build_log(request, project_id, build_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) build = get_object_or_404(BuildResult, project=project, pk=build_id) try: log = build.read_build_log() except Exception as e: return json_failure(str(e)) send_keen_event('cloudpebble', 'cloudpebble_view_build_log', data={ 'data': { 'build_state': build.state } }, project=project, request=request) return json_response({"log": log})
def create_source_file(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) try: f = SourceFile.objects.create(project=project, file_name=request.POST['name']) f.save_file('') except IntegrityError as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_file', data={ 'data': { 'filename': request.POST['name'], 'kind': 'source' } }, project=project, request=request) return json_response({"file": {"id": f.id, "name": f.file_name}})
def create_source_file(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) try: f = SourceFile.objects.create(project=project, file_name=request.POST['name']) f.save_file(request.POST.get('content', '')) except IntegrityError as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_file', data={ 'data': { 'filename': request.POST['name'], 'kind': 'source' } }, project=project, request=request) return json_response({"file": {"id": f.id, "name": f.file_name}})
def _spin_up_server(request): servers = set(settings.YCM_URLS) while len(servers) > 0: server = random.choice(list(servers)) servers.remove(server) try: result = requests.post('%sspinup' % server, json.dumps(request), headers={'Content-Type': 'application/json'}, verify=settings.COMPLETION_CERTS) if result.ok: response = result.json() if response['success']: return json_response({'uuid': response['uuid'], 'server': server}) except (requests.RequestException, ValueError): pass print "Server %s failed; trying another." % server # If we get out of here, something went wrong. return json_failure({'success': False, 'error': 'No servers'})
def build_log(request, project_id, build_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) build = get_object_or_404(BuildResult, project=project, pk=build_id) try: log = build.read_build_log() except Exception as e: return json_failure(str(e)) send_keen_event('cloudpebble', 'cloudpebble_view_build_log', data={'data': { 'build_state': build.state }}, project=project, request=request) return json_response({"log": log})
def create_resource(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) kind = request.POST['kind'] resource_ids = json.loads(request.POST['resource_ids']) posted_file = request.FILES.get('file', None) file_name = request.POST['file_name'] new_tags = json.loads(request.POST['new_tags']) resources = [] try: with transaction.atomic(): rf = ResourceFile.objects.create(project=project, file_name=file_name, kind=kind) for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None resources.append(ResourceIdentifier.objects.create(resource_file=rf, resource_id=r['id'], character_regex=regex, tracking=tracking)) if posted_file is not None: variant = ResourceVariant.objects.create(resource_file=rf, tags=",".join(str(int(t)) for t in new_tags)) variant.save_file(posted_file, posted_file.size) target_platforms = json.loads(request.POST.get('target_platforms', None)) rf.target_platforms = None if target_platforms is None else json.dumps(target_platforms) rf.save() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_file', data={ 'data': { 'filename': file_name, 'kind': 'resource', 'resource-kind': kind } }, project=project, request=request) return json_response({"file": { "id": rf.id, "kind": rf.kind, "file_name": rf.file_name, "target_platforms": json.loads(rf.target_platforms) if rf.target_platforms else None, "resource_ids": [{'id': x.resource_id, 'regex': x.character_regex} for x in resources], "identifiers": [x.resource_id for x in resources], "variants": [x.get_tags() for x in rf.variants.all()], "extra": {y.resource_id: {'regex': y.character_regex, 'tracking': y.tracking} for y in rf.identifiers.all()} }})
def delete_resource(request, project_id, resource_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) try: resource.delete() except Exception as e: return json_failure(str(e)) else: send_td_event('cloudpebble_delete_file', data={ 'data': { 'filename': resource.file_name, 'kind': 'resource', 'resource-kind': resource.kind } }, request=request, project=project) return json_response({})
def import_github(request): name = request.POST['name'] repo = request.POST['repo'] branch = request.POST['branch'] match = re.match(r'^(?:https?://|git@|git://)?(?:www\.)?github\.com[/:]([\w.-]+)/([\w.-]+?)(?:\.git|/|$)', repo) if match is None: return HttpResponse(json.dumps({"success": False, 'error': "Invalid GitHub URL."}), content_type="application/json") github_user = match.group(1) github_project = match.group(2) try: project = Project.objects.create(owner=request.user, name=name) except IntegrityError as e: return json_failure(str(e)) task = do_import_github.delay(project.id, github_user, github_project, branch, delete_project=True) return json_response({'task_id': task.task_id, 'project_id': project.id})
def _spin_up_server(request): servers = set(settings.YCM_URLS) print request while len(servers) > 0: server = random.choice(list(servers)) servers.remove(server) try: result = requests.post('%sspinup' % server, json.dumps(request), headers={'Content-Type': 'application/json'}, verify=settings.COMPLETION_CERTS) if result.ok: response = result.json() if response['success']: return json_response({'uuid': response['uuid'], 'server': server}) except (requests.RequestException, ValueError): import traceback traceback.print_exc() print "Server %s failed; trying another." % server # If we get out of here, something went wrong. return json_failure({'success': False, 'error': 'No servers'})
def create_resource(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) kind = request.POST['kind'] resource_ids = json.loads(request.POST['resource_ids']) default_file = request.FILES.get('file', None) colour_file = request.FILES.get('file_colour', None) file_name = default_file.name if default_file is not None else colour_file.name resources = [] try: with transaction.commit_on_success(): rf = ResourceFile.objects.create(project=project, file_name=file_name, kind=kind) for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None resources.append(ResourceIdentifier.objects.create(resource_file=rf, resource_id=r['id'], character_regex=regex, tracking=tracking)) if default_file is not None: default_variant = ResourceVariant.objects.create(resource_file=rf, variant=ResourceVariant.VARIANT_DEFAULT) default_variant.save_file(default_file, default_file.size) if colour_file is not None: colour_variant = ResourceVariant.objects.create(resource_file=rf, variant=ResourceVariant.VARIANT_COLOUR) colour_variant.save_file(colour_file, colour_file.size) except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_file', data={ 'data': { 'filename': file_name, 'kind': 'resource', 'resource-kind': kind } }, project=project, request=request) return json_response({"file": { "id": rf.id, "kind": rf.kind, "file_name": rf.file_name, "resource_ids": [{'id': x.resource_id, 'regex': x.character_regex} for x in resources], "identifiers": [x.resource_id for x in resources], "variants": [x.variant for x in rf.variants.all()], "extra": {y.resource_id: {'regex': y.character_regex, 'tracking': y.tracking} for y in rf.identifiers.all()} }})
def save_project_settings(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) try: with transaction.commit_on_success(): sdk_version = int(request.POST['sdk_version']) project.name = request.POST['name'] project.sdk_version = sdk_version if sdk_version == 1: project.version_def_name = request.POST['version_def_name'] elif sdk_version > 1: project.app_uuid = request.POST['app_uuid'] project.app_company_name = request.POST['app_company_name'] project.app_short_name = request.POST['app_short_name'] project.app_long_name = request.POST['app_long_name'] project.app_version_code = int( request.POST['app_version_code']) project.app_version_label = request.POST['app_version_label'] project.app_is_watchface = bool( int(request.POST['app_is_watchface'])) project.app_capabilities = request.POST['app_capabilities'] project.app_keys = request.POST['app_keys'] project.app_jshint = bool(int(request.POST['app_jshint'])) menu_icon = request.POST['menu_icon'] if menu_icon != '': menu_icon = int(menu_icon) old_icon = project.menu_icon if old_icon is not None: old_icon.is_menu_icon = False old_icon.save() icon_resource = project.resources.filter(id=menu_icon)[0] icon_resource.is_menu_icon = True icon_resource.save() project.save() except IntegrityError as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_save_project_settings', project=project, request=request) return json_response({})
def update_resource(request, project_id, resource_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) resource_ids = json.loads(request.POST['resource_ids']) try: with transaction.atomic(): # Lazy approach: delete all the resource_ids and recreate them. # We could do better. resources = [] ResourceIdentifier.objects.filter(resource_file=resource).delete() for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None compat = r['compatibility'] if 'compatibility' in r else None resources.append(ResourceIdentifier.objects.create(resource_file=resource, resource_id=r['id'], character_regex=regex, tracking=tracking, compatibility=compat)) if 'file' in request.FILES: default_variant = resource.variants.get_or_create(variant=ResourceVariant.VARIANT_DEFAULT)[0] default_variant.save_file(request.FILES['file'], request.FILES['file'].size) if 'file_colour' in request.FILES: colour_variant = resource.variants.get_or_create(variant=ResourceVariant.VARIANT_COLOUR)[0] colour_variant.save_file(request.FILES['file_colour'], request.FILES['file_colour'].size) except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_save_file', data={ 'data': { 'filename': resource.file_name, 'kind': 'source' } }, project=project, request=request) return json_response({"file": { "id": resource.id, "kind": resource.kind, "file_name": resource.file_name, "resource_ids": [{'id': x.resource_id, 'regex': x.character_regex, 'compatibility': x.compatibility} for x in resources], "identifiers": [x.resource_id for x in resources], "variants": [x.variant for x in resource.variants.all()], "extra": {y.resource_id: {'regex': y.character_regex, 'tracking': y.tracking, 'compatibility': y.compatibility} for y in resource.identifiers.all()} }})
def load_source_file(request, project_id, file_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) source_file = get_object_or_404(SourceFile, pk=file_id, project=project) try: content = source_file.get_contents() send_keen_event('cloudpebble', 'cloudpebble_open_file', data={ 'data': { 'filename': source_file.file_name, 'kind': 'source' } }, project=project, request=request) except Exception as e: return json_failure(str(e)) else: return json_response({ "success": True, "source": content, "modified": time.mktime(source_file.last_modified.utctimetuple()) })
def create_project(request): name = request.POST['name'] template_id = request.POST.get('template', None) if template_id is not None: template_id = int(template_id) project_type = request.POST.get('type', 'native') template_name = None sdk_version = request.POST.get('sdk', 2) try: with transaction.atomic(): project = Project.objects.create( name=name, owner=request.user, app_company_name=request.user.username, app_short_name=name, app_long_name=name, app_version_label='1.0', app_is_watchface=False, app_capabilities='', project_type=project_type, sdk_version=sdk_version, ) if template_id is not None and template_id != 0: template = TemplateProject.objects.get(pk=template_id) template_name = template.name template.copy_into_project(project) elif project_type == 'simplyjs': f = SourceFile.objects.create(project=project, file_name="app.js") f.save_file(open('{}/src/html/demo.js'.format(settings.SIMPLYJS_ROOT)).read()) elif project_type == 'pebblejs': f = SourceFile.objects.create(project=project, file_name="app.js") f.save_file(open('{}/src/js/app.js'.format(settings.PEBBLEJS_ROOT)).read()) except IntegrityError as e: return json_failure(str(e)) else: send_td_event('cloudpebble_create_project', {'data': {'template': {'id': template_id, 'name': template_name}}}, request=request, project=project) return json_response({"id": project.id})
def create_resource(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) kind = request.POST['kind'] resource_ids = json.loads(request.POST['resource_ids']) posted_file = request.FILES.get('file', None) file_name = request.POST['file_name'] new_tags = json.loads(request.POST['new_tags']) resources = [] try: with transaction.atomic(): rf = ResourceFile.objects.create(project=project, file_name=file_name, kind=kind) for r in resource_ids: resource_options = decode_resource_id_options(r) resources.append(ResourceIdentifier.objects.create(resource_file=rf, **resource_options)) if posted_file is not None: variant = ResourceVariant.objects.create(resource_file=rf, tags=",".join(str(int(t)) for t in new_tags)) variant.save_file(posted_file, posted_file.size) rf.save() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_create_file', data={ 'data': { 'filename': file_name, 'kind': 'resource', 'resource-kind': kind } }, project=project, request=request) return json_response({"file": { "id": rf.id, "kind": rf.kind, "file_name": rf.file_name, "resource_ids": [x.get_options_dict(with_id=True) for x in resources], "identifiers": [x.resource_id for x in resources], "variants": [x.get_tags() for x in rf.variants.all()], "extra": {y.resource_id: y.get_options_dict(with_id=False) for y in rf.identifiers.all()} }})
def create_project_repo(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) repo = request.POST['repo'] description = request.POST['description'] try: repo = ide.git.create_repo(request.user, repo, description) except Exception as e: return json_failure(str(e)) else: project.github_repo = repo.full_name project.github_branch = "master" project.github_last_sync = None project.github_last_commit = None project.save() send_td_event('cloudpebble_created_github_repo', data={ 'data': { 'repo': project.github_repo } }, request=request, project=project) return json_response({"repo": repo.html_url})
def save_project_settings(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) try: with transaction.commit_on_success(): sdk_version = int(request.POST["sdk_version"]) project.name = request.POST["name"] project.sdk_version = sdk_version if sdk_version == 1: project.version_def_name = request.POST["version_def_name"] elif sdk_version > 1: project.app_uuid = request.POST["app_uuid"] project.app_company_name = request.POST["app_company_name"] project.app_short_name = request.POST["app_short_name"] project.app_long_name = request.POST["app_long_name"] project.app_version_code = int(request.POST["app_version_code"]) project.app_version_label = request.POST["app_version_label"] project.app_is_watchface = bool(int(request.POST["app_is_watchface"])) project.app_capabilities = request.POST["app_capabilities"] project.app_keys = request.POST["app_keys"] project.app_jshint = bool(int(request.POST["app_jshint"])) menu_icon = request.POST["menu_icon"] if menu_icon != "": menu_icon = int(menu_icon) old_icon = project.menu_icon if old_icon is not None: old_icon.is_menu_icon = False old_icon.save() icon_resource = project.resources.filter(id=menu_icon)[0] icon_resource.is_menu_icon = True icon_resource.save() project.save() except IntegrityError as e: return json_failure(str(e)) else: send_keen_event("cloudpebble", "cloudpebble_save_project_settings", project=project, request=request) return json_response({})
def create_project_repo(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) repo = request.POST['repo'] description = request.POST['description'] try: repo = ide.git.create_repo(request.user, repo, description) except Exception as e: return json_failure(str(e)) else: project.github_repo = repo.full_name project.github_branch = "master" project.github_last_sync = None project.github_last_commit = None project.save() send_keen_event('cloudpebble', 'cloudpebble_created_github_repo', project=project, request=request, data={'data': { 'repo': project.github_repo }}) return json_response({"repo": repo.html_url})
def set_project_repo(request, project_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) repo = request.POST['repo'] branch = request.POST['branch'] auto_pull = bool(int(request.POST['auto_pull'])) auto_build = bool(int(request.POST['auto_build'])) repo = ide.git.url_to_repo(repo) if repo is None: return json_failure("Invalid repo URL.") repo = '%s/%s' % repo g = ide.git.get_github(request.user) try: g_repo = g.get_repo(repo) except UnknownObjectException: return json_response({ 'exists': False, 'access': False, 'updated': False, 'branch_exists': False }) # TODO: Validate the branch...give user option to create one? with transaction.commit_on_success(): if repo != project.github_repo: if project.github_hook_uuid: try: remove_hooks(g.get_repo(project.github_repo), project.github_hook_uuid) except: pass # Just clear the repo if none specified. if repo == '': project.github_repo = None project.github_branch = None project.github_last_sync = None project.github_last_commit = None project.github_hook_uuid = None project.save() return json_response({ 'exists': True, 'access': True, 'updated': True, 'branch_exists': True }) if not ide.git.git_verify_tokens(request.user): return json_failure("No GitHub tokens on file.") try: has_access = ide.git.check_repo_access(request.user, repo) except UnknownObjectException: return json_response({ 'exists': False, 'access': False, 'updated': False, 'branch_exists': False }) if has_access: project.github_repo = repo project.github_branch = branch project.github_last_sync = None project.github_last_commit = None project.github_hook_uuid = None else: return json_response({ 'exists': True, 'access': True, 'updated': True, 'branch_exists': True }) if branch != project.github_branch: project.github_branch = branch if auto_pull and project.github_hook_uuid is None: # Generate a new hook UUID project.github_hook_uuid = uuid.uuid4().hex # Set it up try: g_repo.create_hook( 'web', { 'url': settings.GITHUB_HOOK_TEMPLATE % { 'project': project.id, 'key': project.github_hook_uuid }, 'content_type': 'form' }, ['push'], True) except Exception as e: return json_failure(str(e)) elif not auto_pull: if project.github_hook_uuid is not None: try: remove_hooks(g_repo, project.github_hook_uuid) except: pass project.github_hook_uuid = None project.github_hook_build = auto_build project.save() send_keen_event('cloudpebble', 'cloudpebble_project_github_linked', project=project, request=request, data={ 'data': { 'repo': project.github_repo, 'branch': project.github_branch } }) return json_response({ 'exists': True, 'access': True, 'updated': True, 'branch_exists': True })
def update_resource(request, project_id, resource_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) resource_ids = json.loads(request.POST['resource_ids']) file_name = request.POST.get('file_name', None) target_platforms = json.loads(request.POST.get('target_platforms', None)) variant_tags = json.loads(request.POST.get('variants', "[]")) new_tags = json.loads(request.POST.get('new_tags', "[]")) replacement_map = json.loads(request.POST.get('replacements', "[]")) replacement_files = request.FILES.getlist('replacement_files[]') try: with transaction.atomic(): # Lazy approach: delete all the resource_ids and recreate them. # We could do better. resources = [] ResourceIdentifier.objects.filter(resource_file=resource).delete() for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None compat = r['compatibility'] if 'compatibility' in r else None resources.append(ResourceIdentifier.objects.create(resource_file=resource, resource_id=r['id'], character_regex=regex, tracking=tracking, compatibility=compat)) # We get sent a list of (tags_before, tags_after) pairs. updated_variants = [] for tag_update in variant_tags: tags_before, tags_after = tag_update variant = resource.variants.get(tags=tags_before) variant.set_tags(tags_after) updated_variants.append(variant) for variant in updated_variants: variant.save() if 'file' in request.FILES: variant = resource.variants.create(tags=",".join(str(int(t)) for t in new_tags)) variant.save_file(request.FILES['file'], request.FILES['file'].size) # We may get sent a list of pairs telling us which variant gets which replacement file for tags, file_index in replacement_map: variant = resource.variants.get(tags=tags) replacement = replacement_files[int(file_index)] variant.save_file(replacement, replacement.size) resource.target_platforms = None if target_platforms is None else json.dumps(target_platforms) if file_name and resource.file_name != file_name: resource.file_name = file_name resource.save() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_save_file', data={ 'data': { 'filename': resource.file_name, 'kind': 'source' } }, project=project, request=request) return json_response({"file": { "id": resource.id, "kind": resource.kind, "file_name": resource.file_name, "resource_ids": [{'id': x.resource_id, 'regex': x.character_regex, 'compatibility': x.compatibility} for x in resources], "target_platforms": json.loads(resource.target_platforms) if resource.target_platforms else None, "identifiers": [x.resource_id for x in resources], "variants": [x.get_tags() for x in resource.variants.all()], "extra": {y.resource_id: {'regex': y.character_regex, 'tracking': y.tracking, 'compatibility': y.compatibility} for y in resource.identifiers.all()} }})
def launch_emulator(request): user_id = request.user.id platform = request.POST['platform'] oauth = request.POST['token'] tz_offset = request.POST['tz_offset'] versions = { 'aplite': '2.9', 'basalt': '3.0', } version = versions[platform] redis_key = 'qemu-user-%s-%s' % (user_id, platform) qemu_instance = redis_client.get(redis_key) if qemu_instance is not None: qemu_instance = json.loads(qemu_instance) try: response = requests.post(qemu_instance['ping_url'], timeout=2, verify=settings.COMPLETION_CERTS) response.raise_for_status() response = response.json() except (requests.RequestException, ValueError) as e: print "couldn't fetch old instance: %s" % e pass else: if response.get('alive', False): return json_response(qemu_instance) else: print "old instance is dead." token = _generate_token() servers = set(settings.QEMU_URLS) while len(servers) > 0: server = random.choice(list(servers)) servers.remove(server) try: result = requests.post( server + 'qemu/launch', data={ 'token': token, 'platform': platform, 'version': version, 'oauth': oauth, 'tz_offset': tz_offset }, headers={'Authorization': settings.QEMU_LAUNCH_AUTH_HEADER}, timeout=15, verify=settings.COMPLETION_CERTS) result.raise_for_status() response = result.json() url = urlparse.urlsplit(server) response['host'] = url.hostname response['secure'] = (url.scheme == 'https') response['api_port'] = url.port or (443 if url.scheme == 'https' else 80) response['ping_url'] = '%sqemu/%s/ping' % (server, response['uuid']) response['kill_url'] = '%sqemu/%s/kill' % (server, response['uuid']) response['token'] = token redis_client.set(redis_key, json.dumps(response)) return json_response(response) except requests.HTTPError as e: print e.response.text except (requests.RequestException, ValueError) as e: print e pass return json_failure("Unable to create emulator instance.")
def update_resource(request, project_id, resource_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) resource_ids = json.loads(request.POST['resource_ids']) file_name = request.POST.get('file_name', None) variant_tags = json.loads(request.POST.get('variants', "[]")) new_tags = json.loads(request.POST.get('new_tags', "[]")) replacement_map = json.loads(request.POST.get('replacements', "[]")) replacement_files = request.FILES.getlist('replacement_files[]') try: with transaction.atomic(): # Lazy approach: delete all the resource_ids and recreate them. # We could do better. resources = [] ResourceIdentifier.objects.filter(resource_file=resource).delete() for r in resource_ids: resource_options = decode_resource_id_options(r) resources.append(ResourceIdentifier.objects.create(resource_file=resource, **resource_options)) # We get sent a list of (tags_before, tags_after) pairs. updated_variants = [] for tag_update in variant_tags: tags_before, tags_after = tag_update variant = resource.variants.get(tags=tags_before) variant.set_tags(tags_after) updated_variants.append(variant) for variant in updated_variants: variant.save() if 'file' in request.FILES: variant = resource.variants.create(tags=",".join(str(int(t)) for t in new_tags)) variant.save_file(request.FILES['file'], request.FILES['file'].size) # We may get sent a list of pairs telling us which variant gets which replacement file for tags, file_index in replacement_map: variant = resource.variants.get(tags=tags) replacement = replacement_files[int(file_index)] variant.save_file(replacement, replacement.size) if file_name and resource.file_name != file_name: resource.file_name = file_name resource.save() except Exception as e: return json_failure(str(e)) else: send_keen_event('cloudpebble', 'cloudpebble_save_file', data={ 'data': { 'filename': resource.file_name, 'kind': 'source' } }, project=project, request=request) return json_response({"file": { "id": resource.id, "kind": resource.kind, "file_name": resource.file_name, "resource_ids": [x.get_options_dict(with_id=True) for x in resources], "identifiers": [x.resource_id for x in resources], "variants": [x.get_tags() for x in resource.variants.all()], "extra": {y.resource_id: y.get_options_dict(with_id=False) for y in resource.identifiers.all()} }})
def update_resource(request, project_id, resource_id): project = get_object_or_404(Project, pk=project_id, owner=request.user) resource = get_object_or_404(ResourceFile, pk=resource_id, project=project) resource_ids = json.loads(request.POST['resource_ids']) try: with transaction.atomic(): # Lazy approach: delete all the resource_ids and recreate them. # We could do better. resources = [] ResourceIdentifier.objects.filter(resource_file=resource).delete() for r in resource_ids: regex = r['regex'] if 'regex' in r else None tracking = int(r['tracking']) if 'tracking' in r else None compat = r['compatibility'] if 'compatibility' in r else None resources.append( ResourceIdentifier.objects.create(resource_file=resource, resource_id=r['id'], character_regex=regex, tracking=tracking, compatibility=compat)) if 'file' in request.FILES: default_variant = resource.variants.get_or_create( variant=ResourceVariant.VARIANT_DEFAULT)[0] default_variant.save_file(request.FILES['file'], request.FILES['file'].size) if 'file_colour' in request.FILES: colour_variant = resource.variants.get_or_create( variant=ResourceVariant.VARIANT_COLOUR)[0] colour_variant.save_file(request.FILES['file_colour'], request.FILES['file_colour'].size) except Exception as e: return json_failure(str(e)) else: send_keen_event( 'cloudpebble', 'cloudpebble_save_file', data={'data': { 'filename': resource.file_name, 'kind': 'source' }}, project=project, request=request) return json_response({ "file": { "id": resource.id, "kind": resource.kind, "file_name": resource.file_name, "resource_ids": [{ 'id': x.resource_id, 'regex': x.character_regex, 'compatibility': x.compatibility } for x in resources], "identifiers": [x.resource_id for x in resources], "variants": [x.variant for x in resource.variants.all()], "extra": { y.resource_id: { 'regex': y.character_regex, 'tracking': y.tracking, 'compatibility': y.compatibility } for y in resource.identifiers.all() } } })