Exemplo n.º 1
0
def micropub(event, mpData):
    if event == 'POST':
        properties = mpData['properties']
        if 'h' in properties and properties['h'] is not None:
            if properties['h'].lower() not in ('entry',):
                return ('Micropub CREATE requires a valid action parameter', 400, {})
            elif properties['content'] is None:
                return ('Micropub CREATE requires a content property', 400, {})
            else:
                try:
                    utcdate   = datetime.datetime.utcnow()
                    tzLocal   = pytz.timezone('America/New_York')
                    timestamp = tzLocal.localize(utcdate, is_dst=None)
                    title     = determineTitle(properties, timestamp)
                    slug      = createSlug(title)
                    location  = generateLocation(timestamp, slug)
                    if os.path.exists(os.path.join(current_app.config['SITE_CONTENT'], '%s.md' % location)):
                        return ('Micropub CREATE failed, location already exists', 406)
                    else:
                        data = { 'slug':      slug,
                                 'title':     title,
                                 'location':  location,
                                 'timestamp': timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                                 'micropub':  properties,
                               }
                        current_app.logger.info('micropub create event for [%s]' % slug)
                        kakuEvent('post', 'create', data)
                        return ('Micropub CREATE successful for %s' % location, 202, {'Location': location})
                except:
                    current_app.logger.exception('Exception during micropub handling')
                    return ('Unable to process Micropub request', 400, {})
        elif 'mp-action' in properties and properties['mp-action'] is not None:
            action = properties['mp-action'].lower()
            if action in ('delete', 'undelete'):
                if 'url' in properties and properties['url'] is not None:
                    url = properties['url']
                    try:
                        data = { 'url': url }
                        kakuEvent('post', action, data)
                        return ('Micropub %s successful for %s' % (action, url), 202, {'Location': url})
                    except:
                        current_app.logger.exception('Exception during micropub handling')
                        return ('Unable to process Micropub request', 400, {})
                else:
                    return ('Micropub %s request requires a URL' % action, 400, {})
        else:
            return ('Invalid Micropub CREATE request', 400, {})
    else:
        return ('Unable to process Micropub %s' % data['event'], 400, {})
Exemplo n.º 2
0
def micropub(event, mpData):
    if event == 'POST':
        properties = mpData['properties']
        if 'action' in properties:
            action = properties['action'].lower()
        elif 'mp-action' in properties and properties['mp-action'] is not None:
            action = properties['mp-action'].lower()
        else:
            action = None
        if action == 'create':
            # https://www.w3.org/TR/2016/CR-micropub-20160816/#create
            if 'content' not in properties and 'summary' in properties:
                properties['content'] = ['\n'.join(properties['summary'])]
                properties['summary'] = []
            if 'content' in properties or 'html' in properties:
                try:
                    utcdate = datetime.datetime.utcnow()
                    tzLocal = pytz.timezone('America/New_York')
                    timestamp = tzLocal.localize(utcdate, is_dst=None)
                    title = determineSummary(properties, timestamp)
                    slug = createSlug(title)
                    location = generateLocation(timestamp, slug)
                    targetFile = os.path.join(
                        current_app.config['SITE_CONTENT'], '%s.md' % location)
                    if os.path.exists(targetFile):
                        return (
                            'Micropub CREATE failed, location already exists',
                            406)
                    else:
                        data = {
                            'slug': slug,
                            'title': title,
                            'location': location,
                            'timestamp':
                            timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                            'micropub': properties,
                        }
                        for key in data:
                            current_app.logger.info('    %s = %s' %
                                                    (key, data[key]))
                        current_app.logger.info(
                            'micropub create event for [%s]' % slug)
                        kakuEvent('post', 'create', data)
                        return ('Micropub CREATE successful for %s' % location,
                                202, {
                                    'Location': location
                                })
                except:
                    current_app.logger.exception(
                        'Exception during micropub handling')
                    return ('Unable to process Micropub request', 400, {})
            else:
                return ('Micropub CREATE requires a content or html property',
                        400, {})

        elif action == 'update':
            # https://www.w3.org/TR/2016/CR-micropub-20160816/#update
            if 'url' not in properties:
                return ('Micropub UPDATE requires a url property', 400, {})
            location = properties['url'].strip()
            targetPath = urlparse(location).path
            pathItems = targetPath.split('.')
            current_app.logger.info('[%s] %s' % (targetPath, pathItems))
            if pathItems[-1].lower() == 'html':
                targetPath = '.'.join(pathItems[:-1])
            slug = targetPath.replace(current_app.config['BASEROUTE'], '')
            targetFile = '%s.json' % os.path.join(
                current_app.config['SITE_CONTENT'], slug)
            data = {
                'slug': slug,
                'url': location,
            }
            if not os.path.exists(targetFile):
                return (
                    'Micropub UPDATE failed for %s - location does not exist' %
                    location, 404, {})
            else:
                for key in ('add', 'delete', 'replace'):
                    if key in properties:
                        # "The values of each property inside the replace, add or delete keys must be an array,
                        #  even if there is only a single value."
                        if type(properties[key]) is dict:
                            data['micropub'] = properties[key]
                            data['actionkey'] = key
                            current_app.logger.info(
                                'micropub UPDATE (%s) event for [%s]' %
                                (key, slug))
                            try:
                                kakuEvent('post', 'update', data)
                                return ('Micropub UPDATE successful for %s' %
                                        location, 200, {
                                            'Location': location
                                        })
                            except:
                                current_app.logger.exception(
                                    'Exception during micropub handling')
                                return ('Unable to process Micropub request',
                                        400, {})
                        else:
                            return ('Unable to process Micropub request', 400,
                                    {})
                else:
                    return (
                        'Micropub UPDATE failed for %s - currently only REPLACE is supported'
                        % location, 406, {})

        elif action in ('delete', 'undelete'):
            # https://www.w3.org/TR/2016/CR-micropub-20160816/#delete
            if 'url' in properties and properties['url'] is not None:
                url = properties['url']
                data = {'url': url}
                try:
                    kakuEvent('post', action, data)
                    return ('Micropub %s of %s successful' % (action, url),
                            200, {
                                'Location': url
                            })
                except:
                    current_app.logger.exception(
                        'Exception during micropub handling')
                    return ('Unable to process Micropub request', 400, {})
            else:
                return ('Micropub %s request requires a URL' % action, 400, {})
        else:
            return ('Invalid Micropub CREATE request', 400, {})
    else:
        return ('Unable to process Micropub %s' % data['event'], 400, {})
Exemplo n.º 3
0
def micropub(event, mpData):
    if event == 'POST':
        properties = mpData['properties']
        if 'action' in properties:
            action = properties['action'].lower()
        elif 'mp-action' in properties and properties['mp-action'] is not None:
            action = properties['mp-action'].lower()
        else:
            action = None
        if action == 'create':
            # https://www.w3.org/TR/2016/CR-micropub-20160816/#create
            if 'content' not in properties and 'summary' in properties:
                properties['content'] = [ '\n'.join(properties['summary']) ]
                properties['summary'] = []
            if 'content' in properties or 'html' in properties:
                try:
                    utcdate    = datetime.datetime.utcnow()
                    tzLocal    = pytz.timezone('America/New_York')
                    timestamp  = tzLocal.localize(utcdate, is_dst=None)
                    title      = determineSummary(properties, timestamp)
                    slug       = createSlug(title)
                    location   = generateLocation(timestamp, slug)
                    targetFile = os.path.join(current_app.config['SITE_CONTENT'], '%s.md' % location)
                    if os.path.exists(targetFile):
                        return ('Micropub CREATE failed, location already exists', 406)
                    else:
                        data = { 'slug':      slug,
                                 'title':     title,
                                 'location':  location,
                                 'timestamp': timestamp.strftime('%Y-%m-%d %H:%M:%S'),
                                 'micropub':  properties,
                               }
                        for key in data:
                            current_app.logger.info('    %s = %s' % (key, data[key]))
                        current_app.logger.info('micropub create event for [%s]' % slug)
                        kakuEvent('post', 'create', data)
                        return ('Micropub CREATE successful for %s' % location, 202, {'Location': location})
                except:
                    current_app.logger.exception('Exception during micropub handling')
                    return ('Unable to process Micropub request', 400, {})
            else:
                return ('Micropub CREATE requires a content or html property', 400, {})

        elif action == 'update':
            # https://www.w3.org/TR/2016/CR-micropub-20160816/#update
            if 'url' not in properties:
                return ('Micropub UPDATE requires a url property', 400, {})
            location   = properties['url'].strip()
            targetPath = urlparse(location).path
            pathItems  = targetPath.split('.')
            current_app.logger.info('[%s] %s' % (targetPath, pathItems))
            if pathItems[-1].lower() == 'html':
                targetPath = '.'.join(pathItems[:-1])
            slug       = targetPath.replace(current_app.config['BASEROUTE'], '')
            targetFile = '%s.json' % os.path.join(current_app.config['SITE_CONTENT'], slug)
            data = { 'slug': slug,
                     'url':  location,
                   }
            if not os.path.exists(targetFile):
                return ('Micropub UPDATE failed for %s - location does not exist' % location, 404, {})
            else:
                for key in ('add', 'delete', 'replace'):
                    if key in properties:
                        # "The values of each property inside the replace, add or delete keys must be an array,
                        #  even if there is only a single value."
                        if type(properties[key]) is dict:
                            data['micropub'] = properties[key]
                            data['actionkey'] = key
                            current_app.logger.info('micropub UPDATE (%s) event for [%s]' % (key, slug))
                            try:
                                kakuEvent('post', 'update', data)
                                return ('Micropub UPDATE successful for %s' % location, 200, {'Location': location})
                            except:
                                current_app.logger.exception('Exception during micropub handling')
                                return ('Unable to process Micropub request', 400, {})
                        else:
                            return ('Unable to process Micropub request', 400, {})
                else:
                    return ('Micropub UPDATE failed for %s - currently only REPLACE is supported' % location, 406, {})

        elif action in ('delete', 'undelete'):
            # https://www.w3.org/TR/2016/CR-micropub-20160816/#delete
            if 'url' in properties and properties['url'] is not None:
                url = properties['url']
                data = { 'url': url }
                try:
                    kakuEvent('post', action, data)
                    return ('Micropub %s of %s successful' % (action, url), 200, {'Location': url})
                except:
                    current_app.logger.exception('Exception during micropub handling')
                    return ('Unable to process Micropub request', 400, {})
            else:
                return ('Micropub %s request requires a URL' % action, 400, {})
        else:
            return ('Invalid Micropub CREATE request', 400, {})
    else:
        return ('Unable to process Micropub %s' % data['event'], 400, {})
Exemplo n.º 4
0
def mention(sourceURL, targetURL, vouchDomain=None):
    """Process the incoming Webmention from the sourceURL.

    To verify that the targetURL being referenced by the sourceURL
    is a valid reference we run findMentions() at it and scan the
    resulting href list.

    This does the following checks:
      1. The sourceURL exists
      2. The sourceURL indeed does reference our targetURL
      3. The sourceURL is a valid Vouch (if configured to check)
      4. The sourceURL is active and not deleted, if deleted then remove
         it from our list of mentions for targetURL
    """
    current_app.logger.info('handling Webmention from %s' % sourceURL)

    try:
        result   = False
        vouched  = False
        mentions = ronkyuu.findMentions(sourceURL)
        current_app.logger.info('mentions %s' % mentions)

        if mentions['status'] == 410:
            data = { 'targetURL': targetURL,
                     'sourceURL': sourceURL
                   }
            current_app.logger.info('mention removal event from [%s] of [%s]' % (targetURL, sourceURL))
            kakuEvent('mention', 'deleted', data)
        else:
            for href in mentions['refs']:
                if href != sourceURL and href == targetURL:
                    current_app.logger.info('post at %s was referenced by %s' % (targetURL, sourceURL))
                    if current_app.config['VOUCH_REQUIRED']:
                        if vouchDomain is None:
                            vouched = False
                            result  = False
                        else:
                            vouched = processVouch(sourceURL, targetURL, vouchDomain)
                            result  = vouched
                    else:
                        vouched = False
                        result  = True

                    if result:
                        utcdate   = datetime.datetime.utcnow()
                        tzLocal   = pytz.timezone('America/New_York')
                        timestamp = tzLocal.localize(utcdate, is_dst=None)
                        mf2Data   = Parser(doc=mentions['content']).to_dict()
                        hcard     = extractHCard(mf2Data)
                        data      = { 'sourceURL':   sourceURL,
                                      'targetURL':   targetURL,
                                      'vouchDomain': vouchDomain,
                                      'vouched':     vouched,
                                      'postDate':    timestamp.strftime('%Y-%m-%dT%H:%M:%S'),
                                      'hcard':       hcard,
                                      'mf2data':     mf2Data,
                                    }
                        current_app.logger.info('mention created for [%s] from [%s]' % (targetURL, sourceURL))
                        current_app.logger.info(json.dumps(data, indent=2))
                        kakuEvent('mention', 'create', data)

        current_app.logger.info('mention() returning %s' % result)
    except ValueError:
        current_app.logger.exception('Exception raised during webmention processing')
        result = False
    return result, vouched