def _delete_blogs_syndicate(blog_id, consumer_blog_id): consumer = _get_consumer_from_auth() out_service = get_resource_service('syndication_out') consumer_id = str(consumer['_id']) out_syndication = out_service.get_syndication(consumer_id, blog_id, consumer_blog_id) if not out_syndication: logger.warning( 'Syndication already deleted for blog "{}".'.format(blog_id)) return api_response({}, 204) else: out_service.delete({ '$and': [{ 'blog_id': { '$eq': blog_id } }, { 'consumer_id': { '$eq': consumer_id } }, { 'consumer_blog_id': { '$eq': consumer_blog_id } }] }) return api_response({}, 204)
def _delete_producer_blogs_syndicate(producer_id, blog_id, consumer_blog_id): producers = get_resource_service('producers') in_service = get_resource_service('syndication_in') syndication_in = in_service.get_syndication(producer_id, blog_id, consumer_blog_id) if not syndication_in: logger.warning('Syndication not sent for blog "{}".'.format(blog_id)) return api_response({}, 204) else: try: response = producers.unsyndicate(producer_id, blog_id, consumer_blog_id, json_loads=False) except ProducerAPIError as e: return api_response(str(e), 500) else: if response.status_code == 204: syndication_id = syndication_in['_id'] in_service.delete_action(lookup={'_id': syndication_id}) return api_response(response.content, response.status_code, json_dumps=False) else: return api_error('Unable to unsyndicate producer blog.', _response_status(response.status_code))
def consumer_check_connection(consumer_id): consumers = get_resource_service('consumers') consumer = consumers.find_one(_id=consumer_id, req=None) if not consumer: return api_response('invalid consumer id', 404) check_webhook_status(consumer_id) return api_response('OK', 200)
def _update_producer_blogs_syndicate(producer_id, blog_id, consumer_blog_id, auto_retrieve, start_date): producers = get_resource_service('producers') in_service = get_resource_service('syndication_in') in_syndication = in_service.get_syndication(producer_id, blog_id, consumer_blog_id) if not in_syndication: return api_error('Syndication not sent for blog "{}".'.format(blog_id), 409) try: response = producers.syndicate(producer_id, blog_id, consumer_blog_id, start_date, update=True, json_loads=False) except ProducerAPIError as e: return api_response(str(e), 500) else: if response.status_code == 200: syndication_in = in_service.get_syndication(producer_id, blog_id, consumer_blog_id) in_service.update(syndication_in['_id'], { 'auto_retrieve': auto_retrieve, 'start_date': start_date }, syndication_in) del syndication_in['blog_token'] return api_response(syndication_in, 200) elif response.status_code == 404: return api_error('Syndication not sent for blog "{}"'.format(blog_id), 409) else: return api_error('Unable to update blog syndication.', _response_status(response.status_code))
def marketer_blogs(marketer_id): # Use marketplace app url to retrieve marketer by id uri = 'marketers/{}'.format(marketer_id) try: response = _send_marketplace_api_request(MARKETPLACE_APP_URL, uri) except APIConnectionError as e: return api_response(str(e), 500) if response.status_code != 200: return api_error('Unable to get marketer.', response.status_code) marketer = json.loads(response.content.decode('utf-8')) # Use marketer url to call /marketplace/blogs url = marketer['url'] try: response = _send_marketplace_api_request(url, 'marketed/blogs', request.args) except APIConnectionError as e: return api_response(str(e), 500) if response.status_code == 200: # Add marketer name to each blog content = json.loads(response.content.decode('utf-8')) for item in content['_items']: item['marketer_name'] = marketer['name'] response_content = json.dumps(content) return api_response(response_content, response.status_code, json_dumps=False) else: return api_error('Unable to get blogs of marketers.', response.status_code)
def marketers(): # Use marketplace app url to retrieve marketers try: response = _send_marketplace_api_request(MARKETPLACE_APP_URL, 'marketers', request.args) except APIConnectionError as e: return api_response(str(e), 500) if response.status_code == 200: # Update picture_url - bit of a hack until we settle on a storage solution for the marketplace app url = MARKETPLACE_APP_URL if not url.endswith('/'): url = '{}/'.format(url) response_content = '' try: content = json.loads(response.content.decode('utf-8')) for item in content['_items']: picture_url = item['picture_url'] picture_url = picture_url.replace("/api/", "") item['picture_url'] = url + picture_url response_content = json.dumps(content) except Exception as e: logger.warning('Exception on attempt to parse response from marketplace app: {}'.format(str(e))) return api_response(response_content, response.status_code, json_dumps=False) else: return api_error('Unable to get marketers.', response.status_code)
def producer_check_connection(producer_id): producers = get_resource_service('producers') producer = producers.find_one(_id=producer_id, req=None) if not producer: return api_response('invalid_producer_id', 404) check_api_status(producer) return api_response('OK', 200)
def _create_producer_blogs_syndicate(producer_id, blog_id, consumer_blog_id, auto_publish, auto_retrieve, start_date=None): producers = get_resource_service('producers') in_service = get_resource_service('syndication_in') in_syndication = in_service.get_syndication(producer_id, blog_id, consumer_blog_id) if in_syndication: return api_error('Syndication already sent for blog "{}".'.format(blog_id), 409) try: response = producers.syndicate(producer_id, blog_id, consumer_blog_id, auto_retrieve, start_date, json_loads=False) except ProducerAPIError as e: return api_response(str(e), 500) else: if response.status_code == 201: syndication = response.json() in_service.post([{ 'blog_id': syndication['consumer_blog_id'], 'blog_token': syndication['token'], 'producer_id': producer_id, 'producer_blog_id': blog_id, 'producer_blog_title': syndication['producer_blog_title'], 'auto_publish': auto_publish, 'auto_retrieve': auto_retrieve, 'start_date': start_date }]) return api_response(response.content, response.status_code, json_dumps=False) elif response.status_code == 409: return api_error('Syndication already sent for blog "{}"'.format(blog_id), 409) else: return api_error('Unable to syndicate producer blog.', _response_status(response.status_code))
def producer_blog_posts(producer_id, blog_id): producers = get_resource_service('producers') try: response = producers.get_blog_posts(producer_id, blog_id, json_loads=False) except ProducerAPIError as e: return api_response(str(e), 500) else: if response.status_code == 200: return api_response(response.content, response.status_code, json_dumps=False) else: return api_error('Unable to get producer blog posts.', _response_status(response.status_code))
def blogs(): # Use marketplace app to retrieve blogs of all marketers try: response = _send_marketplace_api_request(MARKETPLACE_APP_URL, 'blogs', request.args) except APIConnectionError as e: return api_response(str(e), 500) if response.status_code == 200: return api_response(response.content, 200, json_dumps=False) else: return api_error('Unable to get blogs from marketplace.', response.status_code)
def get_blog_posts(blog_id): blog = Blog(blog_id) kwargs = {} # Get boolean arguments and cast string values to bool. try: kwargs['sticky'] = strtobool(request.args.get('sticky', '0')) kwargs['highlight'] = strtobool(request.args.get('highlight', '0')) except ValueError as e: return api_error(str(e), 403) # Get default ordering. ordering = request.args.get('ordering', Blog.default_ordering) if ordering not in Blog.ordering: return api_error('"{}" is not valid'.format(ordering), 403) kwargs['ordering'] = ordering # Get page & limit. try: kwargs['page'] = int(request.args.get('page', Blog.default_page)) kwargs['limit'] = int(request.args.get('limit', Blog.default_page_limit)) except ValueError as e: return api_error(str(e), 403) # Check page value. if kwargs['page'] < 1: return api_error('"page" value is not valid.', 403) # Check max page limit. if kwargs['limit'] > Blog.max_page_limit: return api_error('"limit" value is not valid.', 403) response_data = blog.posts(wrap=True, **kwargs) result_data = convert_posts(response_data, blog) return api_response(result_data, 200)
def get_advertisements(blog_id, output): """@TODO: add docstrings""" # if the `output` is the `_id` get the data. if output: if isinstance(output, str): output = get_resource_service('outputs').find_one(req=None, _id=output) if not output: return api_error('output not found', 404) else: collection = get_resource_service('collections').find_one( req=None, _id=output.get('collection')) output['collection'] = collection ads = [] if output and output.get('collection', False): ads_ids = output['collection'].get('advertisements', []) ads_ids = list(map(lambda x: x['advertisement_id'], ads_ids)) ads_query = get_resource_service('advertisements').find( {"_id": { "$in": ads_ids }}) ads = list(ads_query) return api_response(ads, 200)
def marketer_languages(): try: response = _send_marketplace_api_request(MARKETPLACE_APP_URL, 'languages', request.args) except APIConnectionError as e: return api_response(str(e), 500) if response.status_code == 200: content = json.loads(response.content.decode('utf-8')) response = [] for language_code in content: if language_code not in SUPPORTED_LANGUAGES['languages'].keys(): logger.warning('Language code {} not in SUPPORTED_LANGUAGES'.format(language_code)) continue response.append({'code': language_code, 'name': SUPPORTED_LANGUAGES['languages'][language_code]}) return api_response(response, 200) else: return api_error('Unable to get languages from marketplace.', response.status_code)
def _update_blogs_syndicate(blog_id, consumer_blog_id, auto_retrieve, start_date): consumer = _get_consumer_from_auth() out_service = get_resource_service('syndication_out') consumer_id = str(consumer['_id']) syndication_out = out_service.get_syndication(consumer_id, blog_id, consumer_blog_id) if not syndication_out: return api_error('Syndication not sent for blog "{}".'.format(blog_id), 404) out_service.update(syndication_out['_id'], { 'start_date': start_date, 'auto_retrieve': auto_retrieve }, syndication_out) return api_response({'_status': 'OK'}, 200)
def _create_blogs_syndicate(blog_id, consumer_blog_id, auto_retrieve, start_date): # Get the blog to be syndicated - must be enabled for syndication blogs_service = get_resource_service('blogs') blog = blogs_service.find_one(req=None, checkUser=False, _id=blog_id) if blog is None: return api_error( 'No blog available for syndication with given id "{}".'.format( blog_id), 409) if not blog.get('syndication_enabled', False): return api_error('blog is not enabled for syndication', 409) consumer = _get_consumer_from_auth() out_service = get_resource_service('syndication_out') consumer_id = str(consumer['_id']) out_syndication = out_service.get_syndication(consumer_id, blog_id, consumer_blog_id) if out_syndication: return api_error( 'Syndication already sent for blog "{}".'.format(blog_id), 409) if not start_date: # TODO: Find a way to force value to None, as it's ignoring schema settings. # we are forced to set a date in the past, as python-eve is saving by default to datetime.datetime.now(). start_date = datetime.datetime(2010, 1, 1, 0, 0, 0) doc = { 'blog_id': blog_id, 'consumer_id': consumer_id, 'consumer_blog_id': consumer_blog_id, 'start_date': start_date, 'auto_retrieve': auto_retrieve } syndication_id = out_service.post([doc])[0] syndication = out_service.find_one(_id=syndication_id, req=None) return api_response( { 'token': syndication['token'], 'producer_blog_title': blog['title'], 'consumer_blog_id': consumer_blog_id, # we return it anyway for consistency. '_status': 'OK' }, 201)
def create_amp_comment(): data = request.values check_comment_length(data['text']) item_data = dict() item_data['text'] = data['text'] item_data['commenter'] = data['commenter'] item_data['client_blog'] = data['client_blog'] item_data['item_type'] = "comment" items = get_resource_service('client_items') item_id = items.post([item_data])[0] comment_data = dict() comment_data["post_status"] = "comment" comment_data["client_blog"] = item_data['client_blog'] comment_data["groups"] = [{ "id": "root", "refs": [{ "idRef": "main" }], "role": "grpRole:NEP" }, { "id": "main", "refs": [{ "residRef": item_id }], "role": "grpRole:Main" }] post_comments = get_resource_service('client_posts') post_comment = post_comments.post([comment_data])[0] comment = post_comments.find_one(req=None, _id=post_comment) resp = api_response(comment, 201) resp.headers['Access-Control-Allow-Credentials'] = 'true' client_domain = data.get('__amp_source_origin') resp.headers['Access-Control-Allow-Origin'] = client_domain resp.headers['AMP-Access-Control-Allow-Source-Origin'] = client_domain resp.headers[ 'Access-Control-Expose-Headers'] = 'AMP-Access-Control-Allow-Source-Origin' return resp
def get_advertisements(blog_id, output): """ Returns the list of advertisements for a given output id Args: :blog_id: string :output: string of the desired output channel """ if output: if isinstance(output, str): output = get_resource_service('outputs').find_one(req=None, _id=output) if not output: return api_error('output not found', 404) else: collection = get_resource_service('collections').find_one( req=None, _id=output.get('collection')) output['collection'] = collection ads = get_advertisements_list(output) return api_response(ads, 200)
def get_token(): global_serv = get_resource_service('global_preferences').get_global_prefs() credentials = global_serv.get(YT_CREDENTIALS) if credentials: url = 'https://www.googleapis.com/oauth2/v4/token' try: params = { 'client_id': credentials['client_id'], 'client_secret': credentials['client_secret'], 'refresh_token': credentials['refresh_token'], 'grant_type': 'refresh_token' } response = requests.post(url, data=params) response = json.loads(response.text) return api_response(response['access_token'], 200) except Exception as err: msg = 'Unexpected error getting youtube access token. {0}'.format( err) logger.warning(msg) return api_error(msg, 501) else: return api_error('Youtube credentials not configured yet', 501)
def get_blog_posts(blog_id): blog = Blog(blog_id) kwargs = {} # Get boolean arguments and cast string values to bool. try: kwargs['sticky'] = strtobool(request.args.get('sticky', '0')) kwargs['highlight'] = strtobool(request.args.get('highlight', '0')) except ValueError as e: return api_error(str(e), 403) # Get default ordering. ordering = request.args.get('ordering', Blog.default_ordering) if ordering not in Blog.ordering: return api_error('"{}" is not valid'.format(ordering), 403) kwargs['ordering'] = ordering # Get page & limit. try: kwargs['page'] = int(request.args.get('page', Blog.default_page)) kwargs['limit'] = int( request.args.get('limit', Blog.default_page_limit)) except ValueError as e: return api_error(str(e), 403) # Check page value. if kwargs['page'] < 1: return api_error('"page" value is not valid.', 403) # Check max page limit. if kwargs['limit'] > Blog.max_page_limit: return api_error('"limit" value is not valid.', 403) response_data = blog.posts(wrap=True, **kwargs) fields = [ '_id', '_etag', '_created', '_updated', 'blog', 'lb_highlight', 'sticky', 'deleted', 'post_status', 'published_date', 'unpublished_date' ] # Convert posts for i, post in enumerate(response_data['_items']): doc = {k: post.get(k) for k in fields} # add items in post doc['items'] = [] for g in post.get('groups', []): if g['id'] != 'main': continue for item in g['refs']: doc['items'].append(_get_converted_item(item['item'])) # add authorship publisher = {} publisher['display_name'] = post['publisher']['display_name'] publisher['picture_url'] = post['publisher'].get('picture_url', '') doc['publisher'] = publisher response_data['_items'][i] = doc # Add additional blog metadata to response _meta. response_data['_meta']['last_updated_post'] = blog._blog.get( 'last_updated_post') response_data['_meta']['last_created_post'] = blog._blog.get( 'last_created_post') return api_response(response_data, 200)
def syndication_webhook(): in_service = get_resource_service('syndication_in') blog_token = request.headers.get('Authorization') # assume if there is no blog token that a get request is just checking for a response from the webhook if not blog_token and request.method == 'GET': return api_response({}, 200) in_syndication = in_service.find_one(blog_token=blog_token, req=None) if in_syndication is None: return api_error('Blog is not being syndicated', 406) blog_service = get_resource_service('client_blogs') blog = blog_service.find_one(req=None, _id=in_syndication['blog_id']) if blog is None: return api_error('Blog not found', 404) if blog['blog_status'] != 'open': return api_error( 'Updates should not be sent for a blog which is not open', 409) data = request.get_json() try: items, producer_post = data['items'], data['post'] except KeyError: return api_error('Bad Request', 400) logger.info('Webhook Request - method: {} items: {} post: {}'.format( request.method, items, producer_post)) posts_service = get_resource_service('posts') producer_post_id = get_producer_post_id(in_syndication, producer_post['_id']) post = posts_service.find_one(req=None, producer_post_id=producer_post_id) post_id = None publisher = None if post: post_id = str(post['_id']) publisher = get_post_creator(post) if publisher: return api_error( 'Post "{}" cannot be updated: already updated by "{}"'.format( post_id, publisher), 409) if request.method == 'GET': return api_response({}, 200) elif request.method in ('POST', 'PUT'): new_post = create_syndicated_blog_post(producer_post, items, in_syndication) if request.method == 'POST': # Create post if post: # Post may have been previously deleted if post.get('deleted'): posts_service.update(post_id, new_post, post) return api_response({'post_id': post_id}, 200) else: return api_error('Post already exist', 409) new_post_id = posts_service.post([new_post])[0] return api_response({'post_id': str(new_post_id)}, 201) else: # Update post if not post: return api_error('Post does not exist', 404) posts_service.patch(post_id, new_post) return api_response({'post_id': post_id}, 200) else: # Delete post posts_service.patch(post_id, {'deleted': True}) return api_response({'post_id': post_id}, 200)