Пример #1
0
Файл: feed.py Проект: 0xMF/alpha
    def generate_media_block(self, default_size=100):
        # Make a thumbnail for the first photo or video
        media_block = ''
        link_kwargs = None
        photo_annotations = get_photo_annotations(self.post_a.get('annotations', []))
        video_annotations = get_video_annotations(self.post_a.get('annotations', []))

        if photo_annotations:
            icon_class = 'icon-zoom-in'
            value = photo_annotations[0]['value']

            link_kwargs = {
                'href': value.get('embeddable_url', smart_reverse(self.request, 'photo',
                                                                  args=[self.post_a.user.username, self.post_a.id, 1])),
            }

            # keep the :// here
            photos_domain = '://photos.app.net'
            if photos_domain not in link_kwargs['href']:
                link_kwargs['target'] = '_blank'
                link_kwargs['rel'] = 'nofollow'
            else:
                link_kwargs['data-pjax-url'] = smart_reverse(self.request, 'pau.views.alpha.photo', args=[self.post_a.user.username,
                                                             self.post_a.id, 1], force_qualified=True)
        elif video_annotations:
            icon_class = 'icon-play-circle'
            value = video_annotations[0]['value']
            embeddable_url = value.get('embeddable_url')
            if embeddable_url:
                link_kwargs = {
                    'href': embeddable_url,
                    'target': '_blank',
                    'rel': 'nofollow'
                }

        if link_kwargs:
            thumbnail_width = value['thumbnail_width']
            thumbnail_height = value['thumbnail_height']
            thumbnail_url = value.get('thumbnail_url_secure', value['thumbnail_url'])

            try:
                max_width = int(self.request.GET.get('max_width', default_size))
                max_height = int(self.request.GET.get('max_height', default_size))
            except:
                max_width = max_height = default_size

            include_zoom = bool(self.request.GET.get('include_zoom', True))
            display_width, display_height = map(str, fit_to_box(thumbnail_width, thumbnail_height, max_width, max_height))

            media_block = [
                html.div(class_='post-media', *[
                    html.a(class_="shadow-overlay", data=self.click_data, *[
                        html.i(class_=icon_class) if include_zoom else ''
                    ], **link_kwargs),
                    html.div(class_='inner-shadow-overlay'),
                    html.img(src=thumbnail_url, width=display_width, height=display_height)
                ])
            ]

        return media_block
Пример #2
0
    def populate_context(self, request, username=None, post_id=None, photo_id=None, *args, **kwargs):
        super(PauPhotoView, self).populate_context(request, *args, **kwargs)

        try:
            post_id = int(post_id)
            photo_id = int(photo_id)
        except:
            raise Http404()

        post_api_obj = bridge.get_post(request, post_id)
        if not verify_post(username, post_api_obj):
            raise Http404()

        photo_annotations = get_photo_annotations(post_api_obj.get('annotations', []))
        num_photos = len(photo_annotations)
        # N.B. photo_id is 1-based
        if photo_id < 1 or photo_id > num_photos:
            raise Http404()

        photo_annotation = photo_annotations[photo_id - 1]
        value = photo_annotation['value']
        width = value['width']
        height = value['height']
        url = value.get('url_secure', value['url'])

        next_photo_url = None
        prev_photo_url = None
        if photo_id > 1:
            prev_photo_url = smart_reverse(request, 'photo', args=[username, post_id, photo_id - 1])
        if photo_id < num_photos:
            next_photo_url = smart_reverse(request, 'photo', args=[username, post_id, photo_id + 1])

        post_presenter = PhotoPostPresenter.from_item(request, post_api_obj)
        self.view_ctx['page_title'] = u'App.net | %s photo: %s' % (post_api_obj.user.username, truncate(post_api_obj.get('text', ''), 50))
        self.view_ctx['page_description'] = truncate(post_api_obj.get('text', self.view_ctx['page_title']), 100)

        self.view_ctx.update_ctx({
            'image_url': url,
            'image_width': width,
            'image_height': height,
            'next_photo_url': next_photo_url,
            'prev_photo_url': prev_photo_url,
            'post_presenter': post_presenter,
            'post_url': smart_reverse(request, 'post_detail_view', args=[username, post_id]),
            'post_api_obj': post_api_obj,
            'oembed_url': oembed_url(request.build_absolute_uri()),
            '__js_page_load_hooks': ['photo.init']
        })
Пример #3
0
Файл: feed.py Проект: 0xMF/alpha
 def generate_html(self):
     avatar_size = '30s'
     max_num_faces = 5
     li_fn = lambda user: html.li(class_='yui3-u', title=user.username, *[
         html.a(href=smart_reverse(self.request, 'user_detail_view', args=[user.username]), class_='avatar facepile-size', style={'background-image': 'url(%s)' % user.avatar_image.get(avatar_size, '')})
     ])
     tree = html.ul(
         *[li_fn(user) for user in self.starred_by[:max_num_faces]]
     )
     return tree
Пример #4
0
Файл: feed.py Проект: 0xMF/alpha
 def generate_obj_link(self):
     obj = self.interaction.objects[0] if self.interaction.objects else None
     if self.action == 'follow':
         return 'you'
     elif self.action in ('star', 'reply', 'repost'):
         return html.a(href=smart_reverse(self.request, 'post_detail_view', kwargs={'username': self.request.user.username,
                       'post_id': obj['id']}), *['your post'])
     elif self.action in ('broadcast_create', 'broadcast_subscribe', 'broadcast_unsubscribe'):
         return html.a(href=obj.canonical_url, *[obj.title])
     elif self.action == 'welcome':
         return 'App.net'
     return ''
Пример #5
0
    def from_item(cls,
                  request,
                  post_a,
                  show_deleted=False,
                  single_post=False,
                  show_stream_marker=False,
                  reply_link_format='to_self',
                  in_conversation=False,
                  click_data=None,
                  *args,
                  **kwargs):
        presenter = cls(*args, **kwargs)
        presenter.request = request
        presenter.post_a = post_a

        presenter.repost = None
        if hasattr(post_a, 'repost_of') and post_a.repost_of:
            presenter.repost = post_a
            # Render the original post not the repost
            presenter.post_a = post_a = post_a.repost_of
        if post_a.user:
            presenter.user_detail_url = smart_reverse(
                request, 'user_detail_view', args=[post_a.user.username])
            presenter.post_detail_url = smart_reverse(request,
                                                      'post_detail_view',
                                                      kwargs={
                                                          'username':
                                                          post_a.user.username,
                                                          'post_id':
                                                          str(post_a.id)
                                                      })
        presenter.show_deleted = show_deleted
        presenter.single_post = single_post
        presenter.reply_link_format = reply_link_format
        presenter.in_conversation = in_conversation
        presenter.is_authenticated = request.user.is_authenticated()
        presenter.show_stream_marker = request.user.is_authenticated(
        ) and request.user.preferences.use_stream_markers and show_stream_marker
        presenter.click_data = click_data or {}
        return presenter
Пример #6
0
    def action_redirect_to_signup(self, request, *args, **kwargs):
        user_id = request.POST.get('user_id')
        if not user_id:
            raise Http404()

        extra_params = {
            'action': 'follow',
            'user_id': user_id,
        }

        request.session['next_blob'] = extra_params

        return HttpResponseRedirect(smart_reverse(request, 'login', url_params={'next': request.build_absolute_uri()}))
Пример #7
0
Файл: feed.py Проект: 0xMF/alpha
    def from_item(cls, request, post_a, show_deleted=False, single_post=False, show_stream_marker=False,
                  reply_link_format='to_self', in_conversation=False, click_data=None, *args, **kwargs):
        presenter = cls(*args, **kwargs)
        presenter.request = request
        presenter.post_a = post_a

        presenter.repost = None
        if hasattr(post_a, 'repost_of') and post_a.repost_of:
            presenter.repost = post_a
            # Render the original post not the repost
            presenter.post_a = post_a = post_a.repost_of
        if post_a.user:
            presenter.user_detail_url = smart_reverse(request, 'user_detail_view', args=[post_a.user.username])
            presenter.post_detail_url = smart_reverse(request, 'post_detail_view', kwargs={'username': post_a.user.username, 'post_id': str(post_a.id)})
        presenter.show_deleted = show_deleted
        presenter.single_post = single_post
        presenter.reply_link_format = reply_link_format
        presenter.in_conversation = in_conversation
        presenter.is_authenticated = request.user.is_authenticated()
        presenter.show_stream_marker = request.user.is_authenticated() and request.user.preferences.use_stream_markers and show_stream_marker
        presenter.click_data = click_data or {}
        return presenter
Пример #8
0
    def action_redirect_to_signup(self, request, *args, **kwargs):
        user_id = request.POST.get('user_id')
        if not user_id:
            raise Http404()

        extra_params = {
            'action': 'follow',
            'user_id': user_id,
        }

        request.session['next_blob'] = extra_params

        return HttpResponseRedirect(
            smart_reverse(request,
                          'login',
                          url_params={'next': request.build_absolute_uri()}))
Пример #9
0
def well_known_webfinger(request):
    resource = request.GET.get('resource')
    if not resource:
        raise Http404()

    fake_email = resource.lower().replace('acct:', '')
    username, domain = fake_email.split('@', 1)

    current_domain = 'alpha.%s' % (settings.PARENT_HOST)
    if domain != current_domain:
        raise Http404()

    user = bridge.get_user_by_username(request, username)

    if not user:
        raise Http404()

    def link(rel, href, _type=None):
        link = dict(rel=rel, href=href)
        if _type:
            link['type'] = _type

        return link

    user_profile = smart_reverse(request,
                                 'user_detail_view',
                                 args=[username],
                                 force_qualified=True)
    activitystream = 'https://api.%s/users/@%s/activitystream' % (
        settings.PARENT_HOST, username)
    resp = json.dumps({
        "subject":
        'acct:%s@%s' % (username, current_domain),
        "aliases": [
            user_profile,
        ],
        "links": [
            link(rel='http://webfinger.net/rel/profile-page',
                 href=user_profile,
                 _type='text/html'),
            link(rel='http://activitystrea.ms/specs/json/1.0/',
                 href=activitystream)
        ]
    })

    return HttpResponse(resp, content_type='application/json')
Пример #10
0
    def populate_context(self, request, *args, **kwargs):
        super(PauMMLActionView, self).populate_context(request, *args, **kwargs)
        self.view_ctx.update_ctx({
            '__js_page_load_hooks': ['utils.handle_resize', 'init_pau', 'init_post_delete', 'init_mute_user', 'init_post_report',
                                     'init_star_post', 'init_repost', 'pau.init_fixed_nav'],
            '__js_api_options': {
                'api_base_url': smart_reverse(request, 'omo_api_proxy'),
            },
            '__js_canvas_mode': 'pau',
            '__js_subscribe_url': 'https://account.app.net/upgrade/',
            '__js_upgrade_storage_url': 'https://account.app.net/settings/upgrade/storage/',
            'selected_nav_page': self.selected_nav_page,
            'explore_streams': bridge.list_explore_streams(request),
            'report_post_form': ReportPostForm(),
        })

        self.view_ctx.forms = []
Пример #11
0
    def populate_context(self, request, *args, **kwargs):
        super(PauMMLActionView, self).populate_context(request, *args, **kwargs)
        self.view_ctx.update_ctx({
            '__js_page_load_hooks': ['utils.handle_resize', 'init_pau', 'init_post_delete', 'init_mute_user', 'init_post_report',
                                     'init_star_post', 'init_repost', 'pau.init_fixed_nav'],
            '__js_api_options': {
                'api_base_url': smart_reverse(request, 'omo_api_proxy'),
            },
            '__js_canvas_mode': 'pau',
            '__js_subscribe_url': 'https://account.app.net/upgrade/',
            '__js_upgrade_storage_url': 'https://account.app.net/settings/upgrade/storage/',
            'selected_nav_page': self.selected_nav_page,
            'explore_streams': bridge.list_explore_streams(request),
            'report_post_form': ReportPostForm(),
        })

        self.view_ctx.forms = []
Пример #12
0
 def generate_html(self):
     avatar_size = '30s'
     max_num_faces = 5
     li_fn = lambda user: html.li(
         class_='yui3-u',
         title=user.username,
         *[
             html.a(href=smart_reverse(
                 self.request, 'user_detail_view', args=[user.username]),
                    class_='avatar facepile-size',
                    style={
                        'background-image':
                        'url(%s)' % user.avatar_image.get(avatar_size, '')
                    })
         ])
     tree = html.ul(
         *[li_fn(user) for user in self.starred_by[:max_num_faces]])
     return tree
Пример #13
0
 def generate_obj_link(self):
     obj = self.interaction.objects[0] if self.interaction.objects else None
     if self.action == 'follow':
         return 'you'
     elif self.action in ('star', 'reply', 'repost'):
         return html.a(href=smart_reverse(self.request,
                                          'post_detail_view',
                                          kwargs={
                                              'username':
                                              self.request.user.username,
                                              'post_id': obj['id']
                                          }),
                       *['your post'])
     elif self.action in ('broadcast_create', 'broadcast_subscribe',
                          'broadcast_unsubscribe'):
         return html.a(href=obj.canonical_url, *[obj.title])
     elif self.action == 'welcome':
         return 'App.net'
     return ''
Пример #14
0
    def from_data(cls, request, is_following, target_id, target_username, target_description_dict,
                  target_avatar, button_classes=None, is_onboarding=False, click_data=None, show_follow_buttons=True,
                  *args, **kwargs):
        presenter = cls()
        presenter.request = request
        presenter.is_following = is_following
        presenter.target_id = target_id
        presenter.target_description = target_description_dict
        presenter.target_username = target_username
        presenter.target_avatar = target_avatar
        presenter.button_classes = button_classes
        presenter.is_onboarding = is_onboarding
        presenter.click_data = click_data
        presenter.show_follow_buttons = show_follow_buttons

        presenter.target_user_detail_url = smart_reverse(
            request, 'user_detail_view', args=[presenter.target_username]
        )

        return presenter
Пример #15
0
def well_known_webfinger(request):
    resource = request.GET.get('resource')
    if not resource:
        raise Http404()

    fake_email = resource.lower().replace('acct:', '')
    username, domain = fake_email.split('@', 1)

    current_domain = 'alpha.%s' % (settings.PARENT_HOST)
    if domain != current_domain:
        raise Http404()

    user = bridge.get_user_by_username(request, username)

    if not user:
        raise Http404()

    def link(rel, href, _type=None):
        link = dict(rel=rel, href=href)
        if _type:
            link['type'] = _type

        return link

    user_profile = smart_reverse(request, 'user_detail_view', args=[username], force_qualified=True)
    activitystream = 'https://api.%s/users/@%s/activitystream' % (settings.PARENT_HOST, username)
    resp = json.dumps({
        "subject": 'acct:%s@%s' % (username, current_domain),
        "aliases": [
            user_profile,
        ],
        "links": [
            link(rel='http://webfinger.net/rel/profile-page', href=user_profile, _type='text/html'),
            link(rel='http://activitystrea.ms/specs/json/1.0/', href=activitystream)
        ]
    })

    return HttpResponse(resp, content_type='application/json')
Пример #16
0
    def generate_media_block(self, default_size=100):
        # Make a thumbnail for the first photo or video
        media_block = ''
        link_kwargs = None
        photo_annotations = get_photo_annotations(
            self.post_a.get('annotations', []))
        video_annotations = get_video_annotations(
            self.post_a.get('annotations', []))

        if photo_annotations:
            icon_class = 'icon-zoom-in'
            value = photo_annotations[0]['value']

            link_kwargs = {
                'href':
                value.get(
                    'embeddable_url',
                    smart_reverse(
                        self.request,
                        'photo',
                        args=[self.post_a.user.username, self.post_a.id, 1])),
            }

            # keep the :// here
            photos_domain = '://photos.app.net'
            if photos_domain not in link_kwargs['href']:
                link_kwargs['target'] = '_blank'
                link_kwargs['rel'] = 'nofollow'
            else:
                link_kwargs['data-pjax-url'] = smart_reverse(
                    self.request,
                    'pau.views.alpha.photo',
                    args=[self.post_a.user.username, self.post_a.id, 1],
                    force_qualified=True)
        elif video_annotations:
            icon_class = 'icon-play-circle'
            value = video_annotations[0]['value']
            embeddable_url = value.get('embeddable_url')
            if embeddable_url:
                link_kwargs = {
                    'href': embeddable_url,
                    'target': '_blank',
                    'rel': 'nofollow'
                }

        if link_kwargs:
            thumbnail_width = value['thumbnail_width']
            thumbnail_height = value['thumbnail_height']
            thumbnail_url = value.get('thumbnail_url_secure',
                                      value['thumbnail_url'])

            try:
                max_width = int(self.request.GET.get('max_width',
                                                     default_size))
                max_height = int(
                    self.request.GET.get('max_height', default_size))
            except:
                max_width = max_height = default_size

            include_zoom = bool(self.request.GET.get('include_zoom', True))
            display_width, display_height = map(
                str,
                fit_to_box(thumbnail_width, thumbnail_height, max_width,
                           max_height))

            media_block = [
                html.div(class_='post-media',
                         *[
                             html.a(class_="shadow-overlay",
                                    data=self.click_data,
                                    *[
                                        html.i(class_=icon_class)
                                        if include_zoom else ''
                                    ],
                                    **link_kwargs),
                             html.div(class_='inner-shadow-overlay'),
                             html.img(src=thumbnail_url,
                                      width=display_width,
                                      height=display_height)
                         ])
            ]

        return media_block
Пример #17
0
def build_tree_from_text_entity_pack(
        request,
        text_entity_pack,
        itemscope='https://join.app.net/schemas/Post',
        convert_new_lines=False):
    # adapted from omo models TextEntityPack.html
    def entity_text(e):
        return text_entity_pack['text'][e['pos']:e['pos'] + e['len']]

    mention_builder = lambda m: html.a(itemprop='mention',
                                       data={
                                           'mention-name': m['name'],
                                           'mention-id': m['id']
                                       },
                                       href=smart_reverse(request,
                                                          'user_detail_view',
                                                          args=[m['name']],
                                                          force_qualified=True
                                                          ),
                                       *[entity_text(m)])
    hashtag_builder = lambda h: html.a(
        itemprop='hashtag',
        data={'hashtag-name': h['name']},
        href=smart_reverse(
            request, 'hashtags', args=[h['name']], force_qualified=True),
        *[entity_text(h)])
    link_builder = lambda l: html.a(
        href=l['url'], target="_blank", rel='nofollow', *[entity_text(l)])

    # map starting position, length of entity placeholder to the replacement html
    entity_map = {}
    for entity_key, builder in [('mentions', mention_builder),
                                ('hashtags', hashtag_builder),
                                ('links', link_builder)]:
        for entity in text_entity_pack.get('entities', {}).get(entity_key, []):
            try:
                entity_map[(entity['pos'], entity['len'])] = builder(entity)
            except NoReverseMatch:
                logger.warning(
                    'Could not build link for entity=%s in Pau path %s.',
                    entity.get('name'), request.path)

    # replace strings with html
    html_pieces = []
    text_idx = 0  # our current place in the original text string
    for entity_start, entity_len in sorted(entity_map.keys()):
        if text_idx != entity_start:
            # if our current place isn't the start of an entity, bring in text until the next entity
            html_pieces.append(
                text_entity_pack.get('text', "")[text_idx:entity_start])

        # pull out the entity html
        entity_html = entity_map[(entity_start, entity_len)]
        html_pieces.append(entity_html)

        # move past the entity we just added
        text_idx = entity_start + entity_len

    # clean up any remaining text
    html_pieces.append(text_entity_pack.get('text', "")[text_idx:])
    if convert_new_lines:
        new_html_pieces = []
        for piece in html_pieces:
            if isinstance(piece, basestring) and '\n' in piece:
                new_html_pieces += list(
                    intersperse(html.br(), piece.split('\n')))
            else:
                new_html_pieces.append(piece)

        html_pieces = new_html_pieces

    # TODO: link to schema
    return html.span(itemscope=itemscope, *html_pieces)
Пример #18
0
Файл: feed.py Проект: 0xMF/alpha
    def generate_post_footer(self):
        if self.post_a.get('is_deleted'):
            return ''

        footer_top_row = []
        # repost
        # N.B. if you change this html (reposts), make sure to change the ajax handler for repost,
        # which duplicates this html to provide client-side feedback
        viewer_has_reposted = self.post_a.get('you_reposted')
        if self.repost or viewer_has_reposted:
            # yes, there is a priority order of reposter info - viewer trumps everyone else
            if viewer_has_reposted:
                reposter_username = self.request.user.username
                reposter_display = 'you'
            elif self.repost:
                reposter_username = self.repost.user.username
                reposter_display = '@' + reposter_username
            footer_top_row.append(
                html.div(class_='post-reposted-by yui3-u', *[
                    html.span(class_='reposted-by-text', *[
                        html.i(class_='icon-repost'),
                        html.span(' Reposted by ', *[
                            html.a(href=smart_reverse(self.request, 'user_detail_view', args=[reposter_username]),
                                   data=self.click_data, *[reposter_display]),
                        ])
                    ])
                ])
            )

        # place
        place_annotation = get_place_annotation(self.post_a.get('annotations', []))
        if place_annotation:
            if place_annotation['value'].get('address'):
                place_pretty = u'%s \u2014 %s' % (place_annotation['value']['name'], place_annotation['value']['address'])
            else:
                place_pretty = u'%s' % place_annotation['value']['name']

            tags_html = []
            if place_annotation.get('type') == 'net.app.core.checkin':
                factual_url = urljoin('http://factual.com/', place_annotation['value']['factual_id'])
                tags_html.append(html.meta(name="factual", content=factual_url))
            tags_html.append(html.span(class_='posted-from-text', *[
                html.i(class_='icon-pushpin'),
                html.span(' at %s' % place_pretty),
            ]))
            footer_top_row.append(html.div(class_='post-posted-from-place yui3-u', *tags_html))
        footer_bottom_row = []

        # timestamp
        timezone_str = self.request.user.adn_user.timezone if self.is_authenticated else 'America/Los_Angeles'
        viewers_timezone = pytz.timezone(timezone_str)
        non_relative_timestamp = pytz.utc.localize(self.post_a.created_at).astimezone(viewers_timezone)
        datetime_formatted = non_relative_timestamp.strftime("%I:%M %p - %d %b %Y")
        footer_bottom_row.append(html.li(
            html.a(href=self.post_detail_url, data=self.click_data, class_='timestamp u-url', title=datetime_formatted, *[
                html.time(class_='dt-published', datetime=datetime_formatted, *[
                    html.i(class_='icon-time yui3-u'),
                    " " + naturaldate(self.post_a.created_at),
                ])
            ])),
        )

        is_reply = hasattr(self.post_a, 'reply_to') and self.post_a.reply_to
        reply_to_hash = "#" + str(self.post_a.reply_to) if is_reply else ''
        # conversation active?
        if is_reply or (self.post_a.num_replies > 0 and not self.single_post):
            footer_bottom_row.append(
                html.li(class_='in-reply-to yui3-u', *[
                    html.a(href=self.post_detail_url + reply_to_hash, data=self.click_data, title='In Reply To...', *[
                        html.i(class_='icon-comments', **{'aria-label': 'In Reply To...'})
                        ])
                ])
            )

        # reply
        if self.is_authenticated and self.show_reply_button:
            footer_bottom_row.append(self.reply_button())

        if self.show_stream_marker:
            data = {
                'set-stream-marker': ''
            }

            footer_bottom_row.append(
                html.li(class_='show-on-hover yui3-u stream-marker-button', *[
                    html.a(href='#', data=data, *[
                        html.i(class_='icon-bookmark'),
                        ""
                        ])
                ])
            )

        if self.post_a.source and self.show_via_attribution:
            source_link = getattr(self.post_a.source, 'link', None)
            source_name = getattr(self.post_a.source, 'name', None)
            if source_link and source_name:
                footer_bottom_row.append(
                    html.li(class_='show-on-hover post-source yui3-u', *[
                        html.a(href=self.post_a.source.link, rel='nofollow', target='_blank', *[
                            html.i(class_='icon-share'),
                            ' via ' + source_name
                            ])
                    ])
                )

        # crosspost
        annotations = self.post_a.get('annotations', [])
        cp_url = None
        for a in annotations:
            annotation_type = a.get('type')
            if annotation_type == "net.app.core.crosspost":
                cp_url = a.get('value', {}).get('canonical_url')
                if cp_url and not re.match('^https?://', cp_url, re.IGNORECASE):
                    cp_url = "http://" + cp_url

        if cp_url:
            cp_url_display = urlparse(cp_url).netloc
            if cp_url_display.startswith('www.'):
                cp_url_display = cp_url_display[4:]
            footer_bottom_row.append(
                html.li(class_='show-on-hover crossposted-from yui3-u', *[
                    html.a(href=cp_url, target='_blank', *[
                        html.i(class_='icon-random'),
                        ' from ' + cp_url_display
                        ])
                ])
            )

        # report this post to app.net
        if self.show_report_button:
            if self.is_authenticated and self.request.user.adn_user.id != self.post_a.user.id:
                footer_bottom_row.append(
                    html.li(class_='show-on-hover last pull-right yui3-u', *[
                        html.a(href='#report', data={'post-report': ''}, *[
                            html.i(class_='icon-flag'),
                            html.span(class_='t-yui3-u-none m-yui3-u-none', *[' Report']),
                            ])
                    ])
                )

        # mute this user--it's not really an if/else with the delete case so I'm not combining the conditions
        if self.show_mute_button:
            if self.is_authenticated and self.request.user.adn_user.id != self.post_a.user.id and not self.post_a.user.you_muted:
                footer_bottom_row.append(
                    html.li(class_='show-on-hover pull-right yui3-u', *[
                        html.a(href='#mute-user', data={'post-mute-user': ''}, *[
                            html.i(class_='icon-minus-sign'),
                            html.span(class_='t-yui3-u-none m-yui3-u-none', *[' Mute user']),
                            ])
                    ])
                )

        # delete this post
        if self.show_delete_button:
            if self.is_authenticated and self.request.user.adn_user.id == self.post_a.user.id:
                footer_bottom_row.append(
                    html.li(class_='show-on-hover last pull-right yui3-u', *[
                        html.a(href='#delete', data={'post-delete': ''}, *[
                            html.i(class_='icon-remove'),
                            html.span(class_='t-yui3-u-none m-yui3-u-none', *[' Delete']),
                            ])
                    ])
                )

        tree = html.div(class_='post-footer', *[
            html.ul(class_='ul-horizontal unstyled footer-top', *footer_top_row),
            html.ul(class_='ul-horizontal unstyled footer-bottom', *footer_bottom_row)
        ])

        return tree
Пример #19
0
 def handle_not_authorized(self, request, *args, **kwargs):
     return HttpResponseRedirect(smart_reverse(request, 'login', url_params={'next': self.next_url(request)}))
Пример #20
0
 def adjust_url(stream):
     stream['url'] = smart_reverse(request, 'explore', args=[stream['slug']])
     return stream
Пример #21
0
 def adjust_url(stream):
     stream["url"] = smart_reverse(request, "explore", args=[stream["slug"]])
     return stream
Пример #22
0
    def populate_context(self,
                         request,
                         username=None,
                         post_id=None,
                         photo_id=None,
                         *args,
                         **kwargs):
        super(PauPhotoView, self).populate_context(request, *args, **kwargs)

        try:
            post_id = int(post_id)
            photo_id = int(photo_id)
        except:
            raise Http404()

        post_api_obj = bridge.get_post(request, post_id)
        if not verify_post(username, post_api_obj):
            raise Http404()

        photo_annotations = get_photo_annotations(
            post_api_obj.get('annotations', []))
        num_photos = len(photo_annotations)
        # N.B. photo_id is 1-based
        if photo_id < 1 or photo_id > num_photos:
            raise Http404()

        photo_annotation = photo_annotations[photo_id - 1]
        value = photo_annotation['value']
        width = value['width']
        height = value['height']
        url = value.get('url_secure', value['url'])

        next_photo_url = None
        prev_photo_url = None
        if photo_id > 1:
            prev_photo_url = smart_reverse(
                request, 'photo', args=[username, post_id, photo_id - 1])
        if photo_id < num_photos:
            next_photo_url = smart_reverse(
                request, 'photo', args=[username, post_id, photo_id + 1])

        post_presenter = PhotoPostPresenter.from_item(request, post_api_obj)
        self.view_ctx['page_title'] = u'App.net | %s photo: %s' % (
            post_api_obj.user.username,
            truncate(post_api_obj.get('text', ''), 50))
        self.view_ctx['page_description'] = truncate(
            post_api_obj.get('text', self.view_ctx['page_title']), 100)

        self.view_ctx.update_ctx({
            'image_url':
            url,
            'image_width':
            width,
            'image_height':
            height,
            'next_photo_url':
            next_photo_url,
            'prev_photo_url':
            prev_photo_url,
            'post_presenter':
            post_presenter,
            'post_url':
            smart_reverse(request,
                          'post_detail_view',
                          args=[username, post_id]),
            'post_api_obj':
            post_api_obj,
            'oembed_url':
            oembed_url(request.build_absolute_uri()),
            '__js_page_load_hooks': ['photo.init']
        })
Пример #23
0
    def populate_context(self, request, *args, **kwargs):
        super(PauPostDetailView,
              self).populate_context(request, *args, **kwargs)
        post_id = kwargs.get('post_id')
        before_post_objs, target_post_api_obj, after_post_objs = bridge.get_conversation(
            request, post_id)

        if target_post_api_obj.user and kwargs.get(
                'username') != target_post_api_obj.user.username:
            new_url = smart_reverse(request,
                                    'post_detail_view',
                                    kwargs={
                                        'username':
                                        target_post_api_obj.user.username,
                                        'post_id': str(target_post_api_obj.id)
                                    })
            self.view_ctx.response = HttpResponsePermanentRedirect(new_url)
            return

        if target_post_api_obj.get('is_deleted') and target_post_api_obj.get(
                'repost_of'):
            # Deleted reposts should actually go away, so this can 404. If a user got deleted, their reposts may be ghosts
            # instead of being deleted correctly
            raise Http404()

        if all((target_post_api_obj.get('is_deleted'),
                (target_post_api_obj.get('reply_to') is None),
                (target_post_api_obj.get('num_replies') == 0))):
            # render normally but 404 status code
            self.view_ctx.status_code = 404

        original_post = target_post_api_obj.get('repost_of')
        if original_post:
            # This is the post detail of a repost post, all activity should be redirected to the
            # original post.
            new_url = smart_reverse(request,
                                    'post_detail_view',
                                    kwargs={
                                        'username':
                                        original_post.user.username,
                                        'post_id': str(original_post.id)
                                    })
            self.view_ctx.response = HttpResponsePermanentRedirect(new_url)
            return

        owner = target_post_api_obj.user
        owner_id = owner['id'] if owner else None
        viewer_is_author = request.user.is_authenticated(
        ) and owner_id == request.user.adn_user.id

        if owner:
            name = target_post_api_obj.user.get(
                'name') or target_post_api_obj.user.username
            self.view_ctx['page_title'] = u'%s: %s on App.net' % (
                name, truncate(target_post_api_obj.get('text', ''), 50))
            self.view_ctx['post_create_pre_text'] = u'@%s ' % (
                target_post_api_obj['user']['username']
            ) if not viewer_is_author else ''
            self.view_ctx['page_description'] = u'%s' % (truncate(
                target_post_api_obj.get('text', ''), 100))
        else:
            # user of root post was deleted
            self.view_ctx['page_title'] = u'App.net'
            self.view_ctx['post_create_pre_text'] = ''
            self.view_ctx[
                'page_description'] = u'This App.net post has been deleted'

        self.view_ctx['oembed_url'] = oembed_url(request.build_absolute_uri())
        self.view_ctx['post_a'] = target_post_api_obj
        self.view_ctx['main_post_inner'] = ChooseFeedPostPresenter.from_item(
            request,
            target_post_api_obj,
            show_deleted=True,
            single_post=True,
            in_conversation=True)
        self.view_ctx['before_post_presenters'] = [
            ChooseFeedPostPresenter.from_item(request,
                                              post_api_obj,
                                              show_deleted=True,
                                              in_conversation=True)
            for post_api_obj in before_post_objs
        ]
        self.view_ctx['after_post_presenters'] = [
            ChooseFeedPostPresenter.from_item(request,
                                              post_api_obj,
                                              show_deleted=True,
                                              in_conversation=True)
            for post_api_obj in after_post_objs
        ]
        self.view_ctx['num_stars'] = target_post_api_obj.num_stars
        self.view_ctx['num_reposts'] = target_post_api_obj.num_reposts
        self.view_ctx[
            'star_facepile_presenter'] = StarFacepilePresenter.from_data(
                request, target_post_api_obj)
        self.view_ctx['owner'] = owner
        self.view_ctx['num_replies'] = target_post_api_obj['num_replies']
        self.view_ctx['__js_refresh_on_post_create'] = '1'
        self.view_ctx['__js_permit_attachments'] = True
        if before_post_objs:
            self.view_ctx['__js_post_id'] = post_id
        self.view_ctx['__js_page_load_hooks'] += [
            'init_follow', 'zoom_to_post',
            'post_create.init_post_file_uploader'
        ]
        if request.user.is_authenticated():
            self.view_ctx['__js_page_load_hooks'] += [
                'post_create.init',
            ]
            self.view_ctx['__js_viewer_username'] = request.user.username

        self.view_ctx['post_box_presenter'] = PostCreatePresenter.from_data(
            request, btn_action='Reply', reply_to=target_post_api_obj)
Пример #24
0
 def action_logout(self, request, *args, **kwargs):
     auth_logout(request)
     return HttpResponseRedirect(smart_reverse(request, 'home'))
Пример #25
0
    def generate_post_footer(self):
        if self.post_a.get('is_deleted'):
            return ''

        footer_top_row = []
        # repost
        # N.B. if you change this html (reposts), make sure to change the ajax handler for repost,
        # which duplicates this html to provide client-side feedback
        viewer_has_reposted = self.post_a.get('you_reposted')
        if self.repost or viewer_has_reposted:
            # yes, there is a priority order of reposter info - viewer trumps everyone else
            if viewer_has_reposted:
                reposter_username = self.request.user.username
                reposter_display = 'you'
            elif self.repost:
                reposter_username = self.repost.user.username
                reposter_display = '@' + reposter_username
            footer_top_row.append(
                html.div(class_='post-reposted-by yui3-u',
                         *[
                             html.span(
                                 class_='reposted-by-text',
                                 *[
                                     html.i(class_='icon-repost'),
                                     html.span(
                                         ' Reposted by ', *[
                                             html.a(href=smart_reverse(
                                                 self.request,
                                                 'user_detail_view',
                                                 args=[reposter_username]),
                                                    data=self.click_data,
                                                    *[reposter_display]),
                                         ])
                                 ])
                         ]))

        # place
        place_annotation = get_place_annotation(
            self.post_a.get('annotations', []))
        if place_annotation:
            if place_annotation['value'].get('address'):
                place_pretty = u'%s \u2014 %s' % (
                    place_annotation['value']['name'],
                    place_annotation['value']['address'])
            else:
                place_pretty = u'%s' % place_annotation['value']['name']

            tags_html = []
            if place_annotation.get('type') == 'net.app.core.checkin':
                factual_url = urljoin('http://factual.com/',
                                      place_annotation['value']['factual_id'])
                tags_html.append(html.meta(name="factual",
                                           content=factual_url))
            tags_html.append(
                html.span(class_='posted-from-text',
                          *[
                              html.i(class_='icon-pushpin'),
                              html.span(' at %s' % place_pretty),
                          ]))
            footer_top_row.append(
                html.div(class_='post-posted-from-place yui3-u', *tags_html))
        footer_bottom_row = []

        # timestamp
        timezone_str = self.request.user.adn_user.timezone if self.is_authenticated else 'America/Los_Angeles'
        viewers_timezone = pytz.timezone(timezone_str)
        non_relative_timestamp = pytz.utc.localize(
            self.post_a.created_at).astimezone(viewers_timezone)
        datetime_formatted = non_relative_timestamp.strftime(
            "%I:%M %p - %d %b %Y")
        footer_bottom_row.append(
            html.li(
                html.a(href=self.post_detail_url,
                       data=self.click_data,
                       class_='timestamp u-url',
                       title=datetime_formatted,
                       *[
                           html.time(class_='dt-published',
                                     datetime=datetime_formatted,
                                     *[
                                         html.i(class_='icon-time yui3-u'),
                                         " " +
                                         naturaldate(self.post_a.created_at),
                                     ])
                       ])), )

        is_reply = hasattr(self.post_a, 'reply_to') and self.post_a.reply_to
        reply_to_hash = "#" + str(self.post_a.reply_to) if is_reply else ''
        # conversation active?
        if is_reply or (self.post_a.num_replies > 0 and not self.single_post):
            footer_bottom_row.append(
                html.li(class_='in-reply-to yui3-u',
                        *[
                            html.a(href=self.post_detail_url + reply_to_hash,
                                   data=self.click_data,
                                   title='In Reply To...',
                                   *[
                                       html.i(
                                           class_='icon-comments',
                                           **{'aria-label': 'In Reply To...'})
                                   ])
                        ]))

        # reply
        if self.is_authenticated and self.show_reply_button:
            footer_bottom_row.append(self.reply_button())

        if self.show_stream_marker:
            data = {'set-stream-marker': ''}

            footer_bottom_row.append(
                html.li(class_='show-on-hover yui3-u stream-marker-button',
                        *[
                            html.a(href='#',
                                   data=data,
                                   *[html.i(class_='icon-bookmark'), ""])
                        ]))

        if self.post_a.source and self.show_via_attribution:
            source_link = getattr(self.post_a.source, 'link', None)
            source_name = getattr(self.post_a.source, 'name', None)
            if source_link and source_name:
                footer_bottom_row.append(
                    html.li(class_='show-on-hover post-source yui3-u',
                            *[
                                html.a(href=self.post_a.source.link,
                                       rel='nofollow',
                                       target='_blank',
                                       *[
                                           html.i(class_='icon-share'),
                                           ' via ' + source_name
                                       ])
                            ]))

        # crosspost
        annotations = self.post_a.get('annotations', [])
        cp_url = None
        for a in annotations:
            annotation_type = a.get('type')
            if annotation_type == "net.app.core.crosspost":
                cp_url = a.get('value', {}).get('canonical_url')
                if cp_url and not re.match('^https?://', cp_url,
                                           re.IGNORECASE):
                    cp_url = "http://" + cp_url

        if cp_url:
            cp_url_display = urlparse(cp_url).netloc
            if cp_url_display.startswith('www.'):
                cp_url_display = cp_url_display[4:]
            footer_bottom_row.append(
                html.li(class_='show-on-hover crossposted-from yui3-u',
                        *[
                            html.a(href=cp_url,
                                   target='_blank',
                                   *[
                                       html.i(class_='icon-random'),
                                       ' from ' + cp_url_display
                                   ])
                        ]))

        # report this post to app.net
        if self.show_report_button:
            if self.is_authenticated and self.request.user.adn_user.id != self.post_a.user.id:
                footer_bottom_row.append(
                    html.li(
                        class_='show-on-hover last pull-right yui3-u',
                        *[
                            html.a(
                                href='#report',
                                data={'post-report': ''},
                                *[
                                    html.i(class_='icon-flag'),
                                    html.span(
                                        class_='t-yui3-u-none m-yui3-u-none',
                                        *[' Report']),
                                ])
                        ]))

        # mute this user--it's not really an if/else with the delete case so I'm not combining the conditions
        if self.show_mute_button:
            if self.is_authenticated and self.request.user.adn_user.id != self.post_a.user.id and not self.post_a.user.you_muted:
                footer_bottom_row.append(
                    html.li(
                        class_='show-on-hover pull-right yui3-u',
                        *[
                            html.a(
                                href='#mute-user',
                                data={'post-mute-user': ''},
                                *[
                                    html.i(class_='icon-minus-sign'),
                                    html.span(
                                        class_='t-yui3-u-none m-yui3-u-none',
                                        *[' Mute user']),
                                ])
                        ]))

        # delete this post
        if self.show_delete_button:
            if self.is_authenticated and self.request.user.adn_user.id == self.post_a.user.id:
                footer_bottom_row.append(
                    html.li(
                        class_='show-on-hover last pull-right yui3-u',
                        *[
                            html.a(
                                href='#delete',
                                data={'post-delete': ''},
                                *[
                                    html.i(class_='icon-remove'),
                                    html.span(
                                        class_='t-yui3-u-none m-yui3-u-none',
                                        *[' Delete']),
                                ])
                        ]))

        tree = html.div(class_='post-footer',
                        *[
                            html.ul(class_='ul-horizontal unstyled footer-top',
                                    *footer_top_row),
                            html.ul(
                                class_='ul-horizontal unstyled footer-bottom',
                                *footer_bottom_row)
                        ])

        return tree
Пример #26
0
 def action_logout(self, request, *args, **kwargs):
     auth_logout(request)
     return HttpResponseRedirect(smart_reverse(request, "home"))
Пример #27
0
    def populate_context(self, request, *args, **kwargs):
        super(PauPostDetailView, self).populate_context(request, *args, **kwargs)
        post_id = kwargs.get('post_id')
        before_post_objs, target_post_api_obj, after_post_objs = bridge.get_conversation(request, post_id)

        if target_post_api_obj.user and kwargs.get('username') != target_post_api_obj.user.username:
            new_url = smart_reverse(request, 'post_detail_view', kwargs={'username': target_post_api_obj.user.username,
                                    'post_id': str(target_post_api_obj.id)})
            self.view_ctx.response = HttpResponsePermanentRedirect(new_url)
            return

        if target_post_api_obj.get('is_deleted') and target_post_api_obj.get('repost_of'):
            # Deleted reposts should actually go away, so this can 404. If a user got deleted, their reposts may be ghosts
            # instead of being deleted correctly
            raise Http404()

        if all((target_post_api_obj.get('is_deleted'), (target_post_api_obj.get('reply_to') is None),
                (target_post_api_obj.get('num_replies') == 0))):
            # render normally but 404 status code
            self.view_ctx.status_code = 404

        original_post = target_post_api_obj.get('repost_of')
        if original_post:
            # This is the post detail of a repost post, all activity should be redirected to the
            # original post.
            new_url = smart_reverse(request, 'post_detail_view', kwargs={'username': original_post.user.username,
                                    'post_id': str(original_post.id)})
            self.view_ctx.response = HttpResponsePermanentRedirect(new_url)
            return

        owner = target_post_api_obj.user
        owner_id = owner['id'] if owner else None
        viewer_is_author = request.user.is_authenticated() and owner_id == request.user.adn_user.id

        if owner:
            name = target_post_api_obj.user.get('name') or target_post_api_obj.user.username
            self.view_ctx['page_title'] = u'%s: %s on App.net' % (name, truncate(target_post_api_obj.get('text', ''), 50))
            self.view_ctx['post_create_pre_text'] = u'@%s ' % (target_post_api_obj['user']['username']) if not viewer_is_author else ''
            self.view_ctx['page_description'] = u'%s' % (truncate(target_post_api_obj.get('text', ''), 100))
        else:
            # user of root post was deleted
            self.view_ctx['page_title'] = u'App.net'
            self.view_ctx['post_create_pre_text'] = ''
            self.view_ctx['page_description'] = u'This App.net post has been deleted'

        self.view_ctx['oembed_url'] = oembed_url(request.build_absolute_uri())
        self.view_ctx['post_a'] = target_post_api_obj
        self.view_ctx['main_post_inner'] = ChooseFeedPostPresenter.from_item(request, target_post_api_obj, show_deleted=True, single_post=True, in_conversation=True)
        self.view_ctx['before_post_presenters'] = [
            ChooseFeedPostPresenter.from_item(request, post_api_obj, show_deleted=True, in_conversation=True) for post_api_obj in before_post_objs
        ]
        self.view_ctx['after_post_presenters'] = [
            ChooseFeedPostPresenter.from_item(request, post_api_obj, show_deleted=True, in_conversation=True) for post_api_obj in after_post_objs
        ]
        self.view_ctx['num_stars'] = target_post_api_obj.num_stars
        self.view_ctx['num_reposts'] = target_post_api_obj.num_reposts
        self.view_ctx['star_facepile_presenter'] = StarFacepilePresenter.from_data(request, target_post_api_obj)
        self.view_ctx['owner'] = owner
        self.view_ctx['num_replies'] = target_post_api_obj['num_replies']
        self.view_ctx['__js_refresh_on_post_create'] = '1'
        self.view_ctx['__js_permit_attachments'] = True
        if before_post_objs:
            self.view_ctx['__js_post_id'] = post_id
        self.view_ctx['__js_page_load_hooks'] += ['init_follow', 'zoom_to_post', 'post_create.init_post_file_uploader']
        if request.user.is_authenticated():
            self.view_ctx['__js_page_load_hooks'] += ['post_create.init', ]
            self.view_ctx['__js_viewer_username'] = request.user.username

        self.view_ctx['post_box_presenter'] = PostCreatePresenter.from_data(request, btn_action='Reply', reply_to=target_post_api_obj)
Пример #28
0
 def _user_link(self, user):
     return smart_reverse(self.request,
                          'user_detail_view',
                          args=[user['username']],
                          force_qualified=True)
Пример #29
0
Файл: feed.py Проект: 0xMF/alpha
 def _user_link(self, user):
     return smart_reverse(self.request, 'user_detail_view', args=[user['username']], force_qualified=True)
Пример #30
0
Файл: feed.py Проект: 0xMF/alpha
def build_tree_from_text_entity_pack(request, text_entity_pack, itemscope='https://join.app.net/schemas/Post', convert_new_lines=False):
    # adapted from omo models TextEntityPack.html
    def entity_text(e):
        return text_entity_pack['text'][e['pos']:e['pos'] + e['len']]

    mention_builder = lambda m: html.a(
        itemprop='mention',
        data={
            'mention-name': m['name'], 'mention-id': m['id']
        },
        href=smart_reverse(request, 'user_detail_view', args=[m['name']], force_qualified=True),
        *[entity_text(m)]
    )
    hashtag_builder = lambda h: html.a(
        itemprop='hashtag',
        data={
            'hashtag-name': h['name']
        },
        href=smart_reverse(request, 'hashtags', args=[h['name']], force_qualified=True),
        *[entity_text(h)]
    )
    link_builder = lambda l: html.a(href=l['url'], target="_blank", rel='nofollow', *[entity_text(l)])

    # map starting position, length of entity placeholder to the replacement html
    entity_map = {}
    for entity_key, builder in [('mentions', mention_builder), ('hashtags', hashtag_builder), ('links', link_builder)]:
        for entity in text_entity_pack.get('entities', {}).get(entity_key, []):
            try:
                entity_map[(entity['pos'], entity['len'])] = builder(entity)
            except NoReverseMatch:
                logger.warning('Could not build link for entity=%s in Pau path %s.', entity.get('name'), request.path)

    # replace strings with html
    html_pieces = []
    text_idx = 0  # our current place in the original text string
    for entity_start, entity_len in sorted(entity_map.keys()):
        if text_idx != entity_start:
            # if our current place isn't the start of an entity, bring in text until the next entity
            html_pieces.append(text_entity_pack.get('text', "")[text_idx:entity_start])

        # pull out the entity html
        entity_html = entity_map[(entity_start, entity_len)]
        html_pieces.append(entity_html)

        # move past the entity we just added
        text_idx = entity_start + entity_len

    # clean up any remaining text
    html_pieces.append(text_entity_pack.get('text', "")[text_idx:])
    if convert_new_lines:
        new_html_pieces = []
        for piece in html_pieces:
            if isinstance(piece, basestring) and '\n' in piece:
                new_html_pieces += list(intersperse(html.br(), piece.split('\n')))
            else:
                new_html_pieces.append(piece)

        html_pieces = new_html_pieces

    # TODO: link to schema
    return html.span(itemscope=itemscope, *html_pieces)
Пример #31
0
 def adjust_url(stream):
     stream['url'] = smart_reverse(request, 'explore', args=[stream['slug']])
     return stream