示例#1
0
def get_language():
    if askbot.is_multilingual():
        return translation.get_language()
    elif HAS_ASKBOT_LOCALE_MIDDLEWARE:
        return askbot_settings.ASKBOT_LANGUAGE
    else:
        return django_settings.LANGUAGE_CODE
def test_haystack():
    if 'haystack' in django_settings.INSTALLED_APPS:
        try_import('haystack', 'django-haystack', short_message = True)
        if getattr(django_settings, 'ENABLE_HAYSTACK_SEARCH', False):
            errors = list()
            if not hasattr(django_settings, 'HAYSTACK_CONNECTIONS'):
                message = "Please HAYSTACK_CONNECTIONS to an appropriate value, value 'simple' can be used for basic testing sample:\n"
                message += """HAYSTACK_CONNECTIONS = {
                    'default': {
                    'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
                        }
                    }"""
                errors.append(message)

            if askbot.is_multilingual():
                if not hasattr(django_settings, "HAYSTACK_ROUTERS"):
                    message = "Please add HAYSTACK_ROUTERS = ['askbot.search.haystack.routers.LanguageRouter',] to settings.py"
                    errors.append(message)
                elif 'askbot.search.haystack.routers.LanguageRouter' not in \
                        getattr(django_settings, 'HAYSTACK_ROUTERS'):
                    message = "'askbot.search.haystack.routers.LanguageRouter' to HAYSTACK_ROUTERS as first element in settings.py"
                    errors.append(message)

            if getattr(django_settings, 'HAYSTACK_SIGNAL_PROCESSOR',
                       '').endswith('AskbotCelerySignalProcessor'):
                try_import('celery_haystack', 'celery-haystack', short_message = True)

            footer = 'Please refer to haystack documentation at https://django-haystack.readthedocs.org/en/latest/settings.html'
            print_errors(errors, footer=footer)
示例#3
0
def get_language():
    if askbot.is_multilingual():
        return translation.get_language()
    elif HAS_ASKBOT_LOCALE_MIDDLEWARE:
        return askbot_settings.ASKBOT_LANGUAGE
    else:
        return django_settings.LANGUAGE_CODE
def test_haystack():
    if 'haystack' in django_settings.INSTALLED_APPS:
        try_import('haystack',
                   'django-haystack',
                   show_requirements_message=False)
        if getattr(django_settings, 'ENABLE_HAYSTACK_SEARCH', False):
            errors = list()
            if not hasattr(django_settings, 'HAYSTACK_CONNECTIONS'):
                message = "Please HAYSTACK_CONNECTIONS to an appropriate value, value 'simple' can be used for basic testing sample:\n"
                message += """HAYSTACK_CONNECTIONS = {
                    'default': {
                    'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
                     
                    }"""
                errors.append(message)

            if askbot.is_multilingual():
                if not hasattr(django_settings, "HAYSTACK_ROUTERS"):
                    message = "Please add HAYSTACK_ROUTERS = ['askbot.search.haystack.routers.LanguageRouter',] to settings.py"
                    errors.append(message)
                elif 'askbot.search.haystack.routers.LanguageRouter' not in \
                        getattr(django_settings, 'HAYSTACK_ROUTERS'):
                    message = "'askbot.search.haystack.routers.LanguageRouter' to HAYSTACK_ROUTERS as first element in settings.py"
                    errors.append(message)

            if getattr(django_settings, 'HAYSTACK_SIGNAL_PROCESSOR',
                       '').endswith('AskbotCelerySignalProcessor'):
                try_import('celery_haystack',
                           'celery-haystack',
                           show_requirements_message=False)

            footer = 'Please refer to haystack documentation at https://django-haystack.readthedocs.org/en/latest/settings.html'
            print_errors(errors, footer=footer)
def cached_value_update_handler(setting=None, new_value=None, language_code=None, *args, **kwargs):
    key=setting.key
    if setting.localized == False and askbot.is_multilingual():
        languages = dict(django_settings.LANGUAGES).keys()
        for lang in languages:
            update_cached_value(key, new_value, lang)
    else:
        update_cached_value(key, new_value, language_code)
示例#6
0
def cached_value_update_handler(setting=None, new_value=None, language_code=None, *args, **kwargs):
    key=setting.key
    if setting.localized == False and askbot.is_multilingual():
        languages = dict(django_settings.LANGUAGES).keys()
        for lang in languages:
            update_cached_value(key, new_value, lang)
    else:
        update_cached_value(key, new_value, language_code)
示例#7
0
class BaseIndex(indexes.SearchIndex):

    i18n_enabled = askbot.is_multilingual()

    text = indexes.CharField(document=True, use_template=True)

    def _get_backend(self, using):
        """
        We set the backend alias to be able to determine language in multilanguage setup.
        """
        self._backend_alias = using
        return super(BaseIndex, self)._get_backend(using)

    def get_language(self, obj):
        return None

    def get_default_language(self, using):
        """
        When using multiple languages, this allows us to specify a fallback based on the
        backend being used.
        """
        return language_from_alias(using) or settings.LANGUAGE_CODE

    def get_current_language(self, using=None, obj=None):
        """
        Helper method bound to ALWAYS return a language.
        When obj is not None, this calls self.get_language to try and get a language from obj,
        this is useful when the object itself defines it's language in a "language" field.
        If no language was found or obj is None, then we call self.get_default_language to try and get a fallback language.
        """
        language = self.get_language(obj) if obj else None
        return language or self.get_default_language(using)

    def get_index_kwargs(self, language):
        """
        This is called to filter the indexed queryset.
        """
        return {}

    def index_queryset(self, using=None):
        self._get_backend(using)
        language = self.get_current_language(using)
        filter_kwargs = self.get_index_kwargs(language)
        return self.get_model().objects.filter(**filter_kwargs)

    def prepare(self, obj):
        current_language = self.get_current_language(using=self._backend_alias,
                                                     obj=obj)

        with override(current_language):
            self.prepared_data = super(BaseIndex, self).prepare(obj)
            self.prepared_data['text'] = ' '.join(
                self.prepared_data['text'].split())
            return self.prepared_data
示例#8
0
 def process_context(self, context):
     user = context['user']
     context.update({
         'name': user.username,
         'question_count': len(context['questions']),
         'recipient_user': user,
         'admin_email': askbot_settings.ADMIN_EMAIL,
         'site_name': askbot_settings.APP_SHORT_NAME,
         'is_multilingual': askbot.is_multilingual()
     })
     return context
示例#9
0
 def process_context(self, context):
     user = context['user']
     context.update({
         'name': user.username,
         'question_count': len(context['questions']),
         'recipient_user': user,
         'admin_email': askbot_settings.ADMIN_EMAIL,
         'site_name': askbot_settings.APP_SHORT_NAME,
         'is_multilingual': askbot.is_multilingual()
     })
     return context
示例#10
0
def run_full_text_search(query_set, query_text, text_search_vector_name):
    """runs full text search against the query set and
    the search text. All words in the query text are
    added to the search with the & operator - i.e.
    the more terms in search, the narrower it is.

    It is also assumed that we ar searching in the same
    table as the query set was built against, also
    it is assumed that the table has text search vector
    stored in the column called with value of`text_search_vector_name`.
    """
    original_qs = query_set
    table_name = query_set.model._meta.db_table

    rank_clause = 'ts_rank(' + table_name + \
                    '.' + text_search_vector_name + \
                    ', plainto_tsquery(%s, %s))'

    where_clause = table_name + '.' + \
                    text_search_vector_name + \
                    ' @@ plainto_tsquery(%s, %s)'

    language_code = get_language()

    #a hack with japanese search for the short queries
    if language_code in ['ja', 'zh-cn'] and len(query_text) in (1, 2):
        mul = 4/len(query_text) #4 for 1 and 2 for 2
        query_text = (query_text + ' ')*mul

    #the table name is a hack, because user does not have the language code
    if askbot.is_multilingual() and table_name == 'askbot_thread':
        where_clause += " AND " + table_name + \
                        '.' + "language_code='" + language_code + "'"

    search_query = '|'.join(query_text.split())#apply "OR" operator
    language_name = LANGUAGE_NAMES.get(language_code, 'english')
    extra_params = (language_name, search_query,)
    extra_kwargs = {
        'select': {'relevance': rank_clause},
        'where': [where_clause,],
        'params': extra_params,
        'select_params': extra_params,
    }

    result_qs = query_set.extra(**extra_kwargs)
    #added to allow search that can be ignored by postgres FTS.
    if not result_qs and len(query_text) < 5:
        return original_qs.filter(
                    models.Q(title__icontains=search_query) |
                    models.Q(tagnames__icontains=search_query) |
                    models.Q(posts__text__icontains = search_query)
                    ).extra(select={'relevance': rank_clause}, select_params=extra_params)
    return result_qs
def test_locale_middlewares():
    django_locale_middleware = 'django.middleware.locale.LocaleMiddleware'
    askbot_locale_middleware = 'askbot.middleware.locale.LocaleMiddleware'
    errors = list()

    if askbot.is_multilingual():
        if askbot_locale_middleware in django_settings.MIDDLEWARE_CLASSES:
            errors.append("Please remove '%s' from your MIDDLEWARE_CLASSES" % askbot_locale_middleware)
        if django_locale_middleware not in django_settings.MIDDLEWARE_CLASSES:
            errors.append("Please add '%s' to your MIDDLEWARE_CLASSES" % django_locale_middleware)

    print_errors(errors)
示例#12
0
def test_locale_middlewares():
    django_locale_middleware = 'django.middleware.locale.LocaleMiddleware'
    askbot_locale_middleware = 'askbot.middleware.locale.LocaleMiddleware'
    errors = list()

    if askbot.is_multilingual():
        if askbot_locale_middleware in django_settings.MIDDLEWARE_CLASSES:
            errors.append("Please remove '%s' from your MIDDLEWARE_CLASSES" % askbot_locale_middleware)
        if django_locale_middleware not in django_settings.MIDDLEWARE_CLASSES:
            errors.append("Please add '%s' to your MIDDLEWARE_CLASSES" % django_locale_middleware)

    print_errors(errors)
示例#13
0
def user_select_languages(request, id=None, slug=None):
    if request.user.is_anonymous():
        raise django_exceptions.PermissionDenied

    user = get_object_or_404(models.User, id=id)


    if not askbot.is_multilingual() or \
        not(request.user.id == user.id or request.user.is_administrator()):
        raise django_exceptions.PermissionDenied

    if request.method == 'POST':
        #todo: add form to clean languages
        form = forms.LanguagePrefsForm(request.POST)
        if form.is_valid():
            user.set_languages(form.cleaned_data['languages'])
            user.save()
            profile = user.askbot_profile
            profile.primary_language = form.cleaned_data['primary_language']
            profile.save()

            redirect_url = reverse(
                'user_select_languages',
                kwargs={
                    'id': user.id,
                    'slug': slugify(user.username)
                }
            )
        return HttpResponseRedirect(redirect_url)
    else:
        languages = user.languages.split()
        initial={
            'languages': languages,
            'primary_language': languages[0]
        }
        form = forms.LanguagePrefsForm(initial=initial)
        data = {
            'view_user': user,
            'languages_form': form,
            'tab_name': 'langs',
            'page_class': 'user-profile-page',
        }
        return render(request, 'user_profile/user_languages.html', data)
示例#14
0
def factory(**options):
    # JINJA2_EXTENSIONS was a thing in Coffin. We keep it around because it
    # may be used in Askbot. Should think about deprecating its use.
    options["extensions"] = DEFAULT_EXTENSIONS \
                          + list(django_settings.JINJA2_EXTENSIONS)
    askbot_globals = {
        'settings': askbot_settings,
        'hasattr': hasattr,
        'encode_jwt': encode_jwt
    }

    mother_of_all_loaders = options.pop('loader')

    skins = utils.get_available_skins()
    if askbot.is_multilingual() or HAS_ASKBOT_LOCALE_MIDDLEWARE:
        languages = list(dict(django_settings.LANGUAGES).keys())
    else:
        languages = [django_settings.LANGUAGE_CODE]

    # create an environment for each skin and language we might serve
    # Jinja2 Environments know a concept called "overlays" which cries for
    # consideration here. It may greatly simplify loading templatetags ...
    all_combinations = [(name, lang) for name in skins for lang in languages]
    for name, lang in all_combinations:
        skin_basedir = utils.get_path_to_skin(name)
        options["skin"] = name
        options["language_code"] = lang
        options['loader'] = deepcopy(mother_of_all_loaders)
        options['loader'].searchpath = [f'{skin_basedir}/jinja2'
                                        ] + options['loader'].searchpath
        env = SkinEnvironment(**options)
        env.globals.update(askbot_globals)
        env.set_language(lang)

    load_templatetags()

    # give Django what it asked for
    default_sibling = SkinEnvironment.build_sibling_key(
        [askbot_settings.ASKBOT_DEFAULT_SKIN,
         get_language()])

    return SkinEnvironment.siblings[default_sibling]
示例#15
0
def user_select_languages(request, id=None, slug=None):
    if request.user.is_anonymous():
        raise django_exceptions.PermissionDenied

    user = get_object_or_404(models.User, id=id)


    if not askbot.is_multilingual() or \
        not(request.user.id == user.id or request.user.is_administrator()):
        raise django_exceptions.PermissionDenied

    if request.method == 'POST':
        #todo: add form to clean languages
        form = forms.LanguagePrefsForm(request.POST)
        if form.is_valid():
            user.set_languages(form.cleaned_data['languages'])
            user.set_primary_language(form.cleaned_data['primary_language'])
            user.save()

            redirect_url = reverse(
                'user_select_languages',
                kwargs={
                    'id': user.id,
                    'slug': slugify(user.username)
                }
            )
        return HttpResponseRedirect(redirect_url)
    else:
        languages = user.languages.split()
        initial={
            'languages': languages,
            'primary_language': languages[0]
        }
        form = forms.LanguagePrefsForm(initial=initial)
        data = {
            'view_user': user,
            'languages_form': form,
            'tab_name': 'langs',
            'page_class': 'user-profile-page',
        }
        return render(request, 'user_profile/user_languages.html', data)
示例#16
0
    def process_context(self, context):
        to_user = context.get('to_user')
        from_user = context.get('from_user')
        post = context.get('post')
        update_activity = context.get('update_activity')
        update_type = self.get_update_type(update_activity)

        #unhandled update_type 'post_shared'
        #user_action = _('%(user)s shared a %(post_link)s.')

        origin_post = post.get_origin_post()
        post_url = site_url(post.get_absolute_url())

        can_reply = to_user.can_post_by_email()
        from askbot.models import get_reply_to_addresses
        reply_address, alt_reply_address = get_reply_to_addresses(
            to_user, post)
        alt_reply_subject = urllib.quote(
            ('Re: ' + post.thread.title).encode('utf-8'))

        return {
            'admin_email': askbot_settings.ADMIN_EMAIL,
            'recipient_user': to_user,
            'update_author_name': from_user.username,
            'receiving_user_name': to_user.username,
            'receiving_user_karma': to_user.reputation,
            'reply_by_email_karma_threshold':
            askbot_settings.MIN_REP_TO_POST_BY_EMAIL,
            'can_reply': can_reply,
            'update_type': update_type,
            'update_activity': update_activity,
            'post': post,
            'post_url': post_url,
            'origin_post': origin_post,
            'thread_title': origin_post.thread.title,
            'reply_address': reply_address,
            'alt_reply_address': alt_reply_address,
            'alt_reply_subject': alt_reply_subject,
            'is_multilingual': askbot.is_multilingual(),
            'reply_sep_tpl': const.SIMPLE_REPLY_SEPARATOR_TEMPLATE
        }
示例#17
0
    def process_context(self, context):
        to_user = context.get("to_user")
        from_user = context.get("from_user")
        post = context.get("post")
        update_activity = context.get("update_activity")
        update_type = self.get_update_type(update_activity)

        # unhandled update_type 'post_shared'
        # user_action = _('%(user)s shared a %(post_link)s.')

        origin_post = post.get_origin_post()
        post_url = site_url(post.get_absolute_url())

        can_reply = to_user.can_post_by_email()
        from askbot.models import get_reply_to_addresses

        reply_address, alt_reply_address = get_reply_to_addresses(to_user, post)
        alt_reply_subject = urllib.quote(("Re: " + post.thread.title).encode("utf-8"))

        return {
            "admin_email": askbot_settings.ADMIN_EMAIL,
            "recipient_user": to_user,
            "update_author_name": from_user.username,
            "receiving_user_name": to_user.username,
            "receiving_user_karma": to_user.reputation,
            "reply_by_email_karma_threshold": askbot_settings.MIN_REP_TO_POST_BY_EMAIL,
            "can_reply": can_reply,
            "update_type": update_type,
            "update_activity": update_activity,
            "post": post,
            "post_url": post_url,
            "origin_post": origin_post,
            "thread_title": origin_post.thread.title,
            "reply_address": reply_address,
            "alt_reply_address": alt_reply_address,
            "alt_reply_subject": alt_reply_subject,
            "is_multilingual": askbot.is_multilingual(),
            "reply_sep_tpl": const.SIMPLE_REPLY_SEPARATOR_TEMPLATE,
        }
示例#18
0
    def process_context(self, context):
        to_user = context.get('to_user')
        from_user = context.get('from_user')
        post = context.get('post')
        update_activity = context.get('update_activity')
        update_type = self.get_update_type(update_activity)

        #unhandled update_type 'post_shared' 
        #user_action = _('%(user)s shared a %(post_link)s.')

        origin_post = post.get_origin_post()
        post_url = site_url(post.get_absolute_url())

        can_reply = to_user.can_post_by_email()
        from askbot.models import get_reply_to_addresses
        reply_address, alt_reply_address = get_reply_to_addresses(to_user, post)
        alt_reply_subject = urllib.quote(('Re: ' + post.thread.title).encode('utf-8'))

        return {
           'admin_email': askbot_settings.ADMIN_EMAIL,
           'recipient_user': to_user,
           'update_author_name': from_user.username,
           'receiving_user_name': to_user.username,
           'receiving_user_karma': to_user.reputation,
           'reply_by_email_karma_threshold': askbot_settings.MIN_REP_TO_POST_BY_EMAIL,
           'can_reply': can_reply,
           'update_type': update_type,
           'update_activity': update_activity,
           'post': post,
           'post_url': post_url,
           'origin_post': origin_post,
           'thread_title': origin_post.thread.title,
           'reply_address': reply_address,
           'alt_reply_address': alt_reply_address,
           'alt_reply_subject': alt_reply_subject,
           'is_multilingual': askbot.is_multilingual(),
           'reply_sep_tpl': const.SIMPLE_REPLY_SEPARATOR_TEMPLATE
        }
示例#19
0
def get_alias():
    if askbot.is_multilingual():
        language = get_language()
        return alias_from_language(language)
    return DEFAULT_ALIAS
    def get_updated_questions_for_user(self, user):
        """
        retreive relevant question updates for the user
        according to their subscriptions and recorded question
        views
        """

        user_feeds = EmailFeedSetting.objects.filter(
            subscriber=user
        ).exclude(frequency__in=('n', 'i'))

        should_proceed = False
        for feed in user_feeds:
            if feed.should_send_now() == True:
                should_proceed = True
                break

        #shortcircuit - if there is no ripe feed to work on for this user
        if should_proceed == False:
            return {}

        #these are placeholders for separate query sets per question group
        #there are four groups - one for each EmailFeedSetting.feed_type
        #and each group has subtypes A and B
        #that's because of the strange thing commented below
        #see note on Q and F objects marked with todo tag
        q_sel_A = None
        q_sel_B = None

        q_ask_A = None
        q_ask_B = None

        q_ans_A = None
        q_ans_B = None

        q_all_A = None
        q_all_B = None

        #base question query set for this user
        #basic things - not deleted, not closed, not too old
        #not last edited by the same user
        base_qs = Post.objects.get_questions().exclude(
            thread__last_activity_by=user
        ).exclude(
            thread__last_activity_at__lt=user.date_joined#exclude old stuff
        ).exclude(
            deleted=True
        ).exclude(
            thread__closed=True
        ).order_by('-thread__last_activity_at')

        if askbot_settings.CONTENT_MODERATION_MODE == 'premoderation':
            base_qs = base_qs.filter(approved = True)
        #todo: for some reason filter on did not work as expected ~Q(viewed__who=user) |
        #      Q(viewed__who=user,viewed__when__lt=F('thread__last_activity_at'))
        #returns way more questions than you might think it should
        #so because of that I've created separate query sets Q_set2 and Q_set3
        #plus two separate queries run faster!

        #build two two queries based

        #questions that are not seen by the user at all
        not_seen_qs = base_qs.filter(~Q(viewed__who=user))
        #questions that were seen, but before last modification
        seen_before_last_mod_qs = base_qs.filter(
            Q(viewed__who=user, viewed__when__lt=F('thread__last_activity_at'))
        )

        #shorten variables for convenience
        Q_set_A = not_seen_qs
        Q_set_B = seen_before_last_mod_qs

        if askbot.is_multilingual():
            languages = user.languages.split()
        else:
            languages = None

        for feed in user_feeds:
            if feed.feed_type == 'm_and_c':
                #alerts on mentions and comments are processed separately
                #because comments to questions do not trigger change of last_updated
                #this may be changed in the future though, see
                #http://askbot.org/en/question/96/
                continue

            #each group of updates represented by the corresponding
            #query set has it's own cutoff time
            #that cutoff time is computed for each user individually
            #and stored as a parameter "cutoff_time"

            #we won't send email for a given question if an email has been
            #sent after that cutoff_time
            if feed.should_send_now():
                if DEBUG_THIS_COMMAND == False:
                    feed.mark_reported_now()
                cutoff_time = feed.get_previous_report_cutoff_time()

                if feed.feed_type == 'q_sel':
                    q_sel_A = Q_set_A.filter(thread__followed_by=user)
                    q_sel_A.cutoff_time = cutoff_time #store cutoff time per query set
                    q_sel_B = Q_set_B.filter(thread__followed_by=user)
                    q_sel_B.cutoff_time = cutoff_time #store cutoff time per query set

                elif feed.feed_type == 'q_ask':
                    q_ask_A = Q_set_A.filter(author=user)
                    q_ask_A.cutoff_time = cutoff_time
                    q_ask_B = Q_set_B.filter(author=user)
                    q_ask_B.cutoff_time = cutoff_time

                elif feed.feed_type == 'q_ans':
                    q_ans_A = Q_set_A.filter(thread__posts__author=user, thread__posts__post_type='answer')
                    q_ans_A = q_ans_A[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_ans_A.cutoff_time = cutoff_time

                    q_ans_B = Q_set_B.filter(thread__posts__author=user, thread__posts__post_type='answer')
                    q_ans_B = q_ans_B[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_ans_B.cutoff_time = cutoff_time

                elif feed.feed_type == 'q_all':
                    q_all_A = user.get_tag_filtered_questions(Q_set_A)
                    q_all_B = user.get_tag_filtered_questions(Q_set_B)

                    q_all_A = q_all_A[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_all_B = q_all_B[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_all_A.cutoff_time = cutoff_time
                    q_all_B.cutoff_time = cutoff_time

        #build ordered list questions for the email report
        q_list = SortedDict()

        #todo: refactor q_list into a separate class?
        extend_question_list(q_sel_A, q_list, languages=languages)
        extend_question_list(q_sel_B, q_list, languages=languages)

        #build list of comment and mention responses here
        #it is separate because posts are not marked as changed
        #when people add comments
        #mention responses could be collected in the loop above, but
        #it is inconvenient, because feed_type m_and_c bundles the two
        #also we collect metadata for these here
        try:
            feed = user_feeds.get(feed_type='m_and_c')
            if feed.should_send_now():
                cutoff_time = feed.get_previous_report_cutoff_time()
                comments = Post.objects.get_comments().filter(
                    added_at__lt=cutoff_time
                ).exclude(author=user).select_related('parent')
                q_commented = list()

                for c in comments:
                    post = c.parent

                    if post.author_id != user.pk:
                        continue

                    #skip is post was seen by the user after
                    #the comment posting time
                    q_commented.append(post.get_origin_post())

                extend_question_list(
                    q_commented,
                    q_list,
                    cutoff_time=cutoff_time,
                    add_comment=True,
                    languages=languages
                )

                mentions = Activity.objects.get_mentions(
                    mentioned_at__lt=cutoff_time,
                    mentioned_whom=user
                )

                #print 'have %d mentions' % len(mentions)
                #MM = Activity.objects.filter(activity_type = const.TYPE_ACTIVITY_MENTION)
                #print 'have %d total mentions' % len(MM)
                #for m in MM:
                #    print m

                mention_posts = get_all_origin_posts(mentions)
                q_mentions_id = [q.id for q in mention_posts]

                q_mentions_A = Q_set_A.filter(id__in = q_mentions_id)
                q_mentions_A.cutoff_time = cutoff_time
                extend_question_list(
                    q_mentions_A,
                    q_list,
                    add_mention=True,
                    languages=languages
                )

                q_mentions_B = Q_set_B.filter(id__in = q_mentions_id)
                q_mentions_B.cutoff_time = cutoff_time
                extend_question_list(
                    q_mentions_B,
                    q_list,
                    add_mention=True,
                    languages=languages
                )
        except EmailFeedSetting.DoesNotExist:
            pass

        if user.email_tag_filter_strategy == const.INCLUDE_INTERESTING:
            extend_question_list(q_all_A, q_list, languages=languages)
            extend_question_list(q_all_B, q_list, languages=languages)

        extend_question_list(q_ask_A, q_list, limit=True, languages=languages)
        extend_question_list(q_ask_B, q_list, limit=True, languages=languages)

        extend_question_list(q_ans_A, q_list, limit=True, languages=languages)
        extend_question_list(q_ans_B, q_list, limit=True, languages=languages)

        if user.email_tag_filter_strategy == const.EXCLUDE_IGNORED:
            extend_question_list(q_all_A, q_list, limit=True, languages=languages)
            extend_question_list(q_all_B, q_list, limit=True, languages=languages)

        ctype = ContentType.objects.get_for_model(Post)
        EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT

        #up to this point we still don't know if emails about
        #collected questions were sent recently
        #the next loop examines activity record and decides
        #for each question, whether it needs to be included or not
        #into the report

        for q, meta_data in q_list.items():
            #this loop edits meta_data for each question
            #so that user will receive counts on new edits new answers, etc
            #and marks questions that need to be skipped
            #because an email about them was sent recently enough

            #also it keeps a record of latest email activity per question per user
            try:
                #todo: is it possible to use content_object here, instead of
                #content type and object_id pair?
                update_info = Activity.objects.get(
                    user=user,
                    content_type=ctype,
                    object_id=q.id,
                    activity_type=EMAIL_UPDATE_ACTIVITY
                )
                emailed_at = update_info.active_at
            except Activity.DoesNotExist:
                update_info = Activity(
                                    user=user, 
                                    content_object=q, 
                                    activity_type=EMAIL_UPDATE_ACTIVITY
                                )
                emailed_at = datetime.datetime(1970, 1, 1)  #long time ago
                if django_settings.USE_TZ:
                    emailed_at = timezone.make_aware(emailed_at, timezone.utc)
            except Activity.MultipleObjectsReturned:
                raise Exception(
                                'server error - multiple question email activities '
                                'found per user-question pair'
                                )

            cutoff_time = meta_data['cutoff_time']#cutoff time for the question

            #skip question if we need to wait longer because
            #the delay before the next email has not yet elapsed
            #or if last email was sent after the most recent modification
            if emailed_at > cutoff_time or emailed_at > q.thread.last_activity_at:
                meta_data['skip'] = True
                continue

            #collect info on all sorts of news that happened after
            #the most recent emailing to the user about this question
            q_rev = q.revisions.filter(revised_at__gt=emailed_at)
            q_rev = q_rev.exclude(author=user)

            #now update all sorts of metadata per question
            meta_data['q_rev'] = len(q_rev)
            if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at:
                meta_data['q_rev'] = 0
                meta_data['new_q'] = True
            else:
                meta_data['new_q'] = False

            new_ans = Post.objects.get_answers(user).filter(
                thread=q.thread,
                added_at__gt=emailed_at,
                deleted=False,
            )
            new_ans = new_ans.exclude(author=user)
            meta_data['new_ans'] = len(new_ans)

            ans_ids = Post.objects.get_answers(user).filter(
                thread=q.thread,
                added_at__gt=emailed_at,
                deleted=False,
            ).values_list('id', flat=True)

            ans_rev = PostRevision.objects.filter(post__id__in = ans_ids)
            ans_rev = ans_rev.exclude(author=user).distinct()

            meta_data['ans_rev'] = len(ans_rev)

            comments = meta_data.get('comments', 0)
            mentions = meta_data.get('mentions', 0)

            #print meta_data
            #finally skip question if there are no news indeed
            if len(q_rev) + len(new_ans) + len(ans_rev) + comments + mentions == 0:
                meta_data['skip'] = True
                #print 'skipping'
            else:
                meta_data['skip'] = False
                #print 'not skipping'
                update_info.active_at = timezone.now() 
                if DEBUG_THIS_COMMAND == False:
                    update_info.save() #save question email update activity
        #q_list is actually an ordered dictionary
        #print 'user %s gets %d' % (user.username, len(q_list.keys()))
        #todo: sort question list by update time
        return q_list
示例#21
0
from django.conf import settings
try:
    from django.conf.urls import handler404
    from django.conf.urls import include, patterns, url
except ImportError:
    from django.conf.urls.defaults import handler404
    from django.conf.urls.defaults import include, patterns, url

import askbot
from askbot.views.error import internal_error as handler500
from django.conf import settings
from django.contrib import admin

admin.autodiscover()

if askbot.is_multilingual():
    from django.conf.urls.i18n import i18n_patterns
    urlpatterns = i18n_patterns('',
        (r'%s' % settings.ASKBOT_URL, include('askbot.urls'))
    )
else:
    urlpatterns = patterns('',
        (r'%s' % settings.ASKBOT_URL, include('askbot.urls'))
    )

urlpatterns += patterns('',
    (r'^admin/', include(admin.site.urls)),
    #(r'^cache/', include('keyedcache.urls')), - broken views disable for now
    #(r'^settings/', include('askbot.deps.livesettings.urls')),
    (r'^followit/', include('followit.urls')),
    (r'^tinymce/', include('tinymce.urls')),
settings.register(
    values.ImageValue(
        GENERAL_SKIN_SETTINGS,
        'SITE_LOGO_URL',
        description = _('Q&amp;A site logo'),
        help_text = _(
                        'To change the logo, select new file, '
                        'then submit this whole form.'
                    ),
        default = '/images/logo.gif',
        url_resolver = skin_utils.get_media_url
    )
)

#cannot use HAS_ASKBOT_LOCALE_MIDDLEWARE due to circular import error
if not askbot.is_multilingual() and \
        'askbot.middleware.locale.LocaleMiddleware' in django_settings.MIDDLEWARE_CLASSES:
    settings.register(
        values.StringValue(
            GENERAL_SKIN_SETTINGS,
            'ASKBOT_LANGUAGE',
            default = django_settings.LANGUAGE_CODE,
            choices =  django_settings.LANGUAGES,
            description = _('Select Language'),
        )
    )

settings.register(
    values.BooleanValue(
        GENERAL_SKIN_SETTINGS,
        'SHOW_LOGO',
示例#23
0
try:
    from django.conf.urls import handler404
    from django.conf.urls import include, url
except ImportError:
    from django.conf.urls.defaults import handler404
    from django.conf.urls.defaults import include, url

from askbot import is_multilingual
from askbot.views.error import internal_error as handler500
from django.conf import settings
from django.contrib import admin
from django.views import static as StaticViews

admin.autodiscover()

if is_multilingual():
    from django.conf.urls.i18n import i18n_patterns
    urlpatterns = i18n_patterns(
        url(r'%s' % settings.ASKBOT_URL, include('askbot.urls'))
    )
else:
    urlpatterns = [
        url(r'%s' % settings.ASKBOT_URL, include('askbot.urls'))
    ]

urlpatterns += [
    url(r'^admin/', admin.site.urls),
    #(r'^cache/', include('keyedcache.urls')), - broken views disable for now
    #(r'^settings/', include('askbot.deps.livesettings.urls')),
    url(r'^followit/', include('followit.urls')),
    url(r'^tinymce/', include('tinymce.urls')),
示例#24
0
def application_settings(request):
    """The context processor function"""
    #if not request.path.startswith('/' + settings.ASKBOT_URL):
    #    #todo: this is a really ugly hack, will only work
    #    #when askbot is installed not at the home page.
    #    #this will not work for the
    #    #heavy modders of askbot, because their custom pages
    #    #will not receive the askbot settings in the context
    #    #to solve this properly we should probably explicitly
    #    #add settings to the context per page
    #    return {}
    my_settings = askbot_settings.as_dict()
    my_settings['LANGUAGE_CODE'] = getattr(request, 'LANGUAGE_CODE',
                                           settings.LANGUAGE_CODE)
    my_settings['LANGUAGE_MODE'] = askbot.get_lang_mode()
    my_settings['MULTILINGUAL'] = askbot.is_multilingual()
    my_settings['LANGUAGES_DICT'] = dict(getattr(settings, 'LANGUAGES', []))
    my_settings['ALLOWED_UPLOAD_FILE_TYPES'] = \
            settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES
    my_settings['ASKBOT_URL'] = settings.ASKBOT_URL
    my_settings['STATIC_URL'] = settings.STATIC_URL
    my_settings['IP_MODERATION_ENABLED'] = getattr(
        settings, 'ASKBOT_IP_MODERATION_ENABLED', False)
    my_settings['USE_LOCAL_FONTS'] = getattr(settings,
                                             'ASKBOT_USE_LOCAL_FONTS', False)
    my_settings['CSRF_COOKIE_NAME'] = settings.CSRF_COOKIE_NAME
    my_settings['DEBUG'] = settings.DEBUG
    my_settings['USING_RUNSERVER'] = 'runserver' in sys.argv
    my_settings['ASKBOT_VERSION'] = askbot.get_version()
    my_settings['LOGIN_URL'] = url_utils.get_login_url()
    my_settings['LOGOUT_URL'] = url_utils.get_logout_url()

    if my_settings['EDITOR_TYPE'] == 'tinymce':
        tinymce_plugins = settings.TINYMCE_DEFAULT_CONFIG.get('plugins',
                                                              '').split(',')
        my_settings['TINYMCE_PLUGINS'] = map(lambda v: v.strip(),
                                             tinymce_plugins)
    else:
        my_settings['TINYMCE_PLUGINS'] = []

    my_settings['LOGOUT_REDIRECT_URL'] = url_utils.get_logout_redirect_url()

    current_language = get_language()

    #for some languages we will start searching for shorter words
    if current_language == 'ja':
        #we need to open the search box and show info message about
        #the japanese lang search
        min_search_word_length = 1
    else:
        min_search_word_length = my_settings['MIN_SEARCH_WORD_LENGTH']

    need_scope_links = askbot_settings.ALL_SCOPE_ENABLED or \
                    askbot_settings.UNANSWERED_SCOPE_ENABLED or \
                    (request.user.is_authenticated() and askbot_settings.FOLLOWED_SCOPE_ENABLED)

    context = {
        'base_url': site_url(''),
        'csrf_token': get_or_create_csrf_token(request),
        'empty_search_state': SearchState.get_empty(),
        'min_search_word_length': min_search_word_length,
        'current_language_code': current_language,
        'settings': my_settings,
        'moderation_items': api.get_info_on_moderation_items(request.user),
        'need_scope_links': need_scope_links,
        'noscript_url': const.DEPENDENCY_URLS['noscript'],
    }

    use_askbot_login = '******' in settings.INSTALLED_APPS
    my_settings['USE_ASKBOT_LOGIN_SYSTEM'] = use_askbot_login
    if use_askbot_login and request.user.is_anonymous():
        from askbot.deps.django_authopenid import context as login_context
        context.update(login_context.login_context(request))

    if askbot_settings.GROUPS_ENABLED:
        #calculate context needed to list all the groups
        def _get_group_url(group):
            """calculates url to the group based on its id and name"""
            group_slug = slugify(group['name'])
            return reverse('users_by_group',
                           kwargs={
                               'group_id': group['id'],
                               'group_slug': group_slug
                           })

        #load id's and names of all groups
        global_group = models.Group.objects.get_global_group()
        groups = models.Group.objects.exclude_personal()
        groups = groups.exclude(id=global_group.id)
        groups_data = list(groups.values('id', 'name'))

        #sort groups_data alphanumerically, but case-insensitive
        groups_data = sorted(
            groups_data,
            lambda x, y: cmp(x['name'].lower(), y['name'].lower()))

        #insert data for the global group at the first position
        groups_data.insert(0, {
            'id': global_group.id,
            'name': global_group.name
        })

        #build group_list for the context
        group_list = list()
        for group in groups_data:
            link = _get_group_url(group)
            group_list.append({'name': group['name'], 'link': link})
        context['group_list'] = simplejson.dumps(group_list)

    return context
示例#25
0
def application_settings(request):
    """The context processor function"""
    #if not request.path.startswith('/' + settings.ASKBOT_URL):
    #    #todo: this is a really ugly hack, will only work
    #    #when askbot is installed not at the home page.
    #    #this will not work for the
    #    #heavy modders of askbot, because their custom pages
    #    #will not receive the askbot settings in the context
    #    #to solve this properly we should probably explicitly
    #    #add settings to the context per page
    #    return {}
    my_settings = askbot_settings.as_dict()
    my_settings['LANGUAGE_CODE'] = getattr(request, 'LANGUAGE_CODE', settings.LANGUAGE_CODE)
    my_settings['LANGUAGE_MODE'] = askbot.get_lang_mode()
    my_settings['MULTILINGUAL'] = askbot.is_multilingual()
    my_settings['LANGUAGES_DICT'] = dict(getattr(settings, 'LANGUAGES', []))
    my_settings['ALLOWED_UPLOAD_FILE_TYPES'] = \
            settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES
    my_settings['ASKBOT_URL'] = settings.ASKBOT_URL
    my_settings['STATIC_URL'] = settings.STATIC_URL
    my_settings['IP_MODERATION_ENABLED'] = getattr(settings, 'ASKBOT_IP_MODERATION_ENABLED', False)
    my_settings['USE_LOCAL_FONTS'] = getattr(
                                        settings,
                                        'ASKBOT_USE_LOCAL_FONTS',
                                        False
                                    )
    my_settings['CSRF_COOKIE_NAME'] = settings.CSRF_COOKIE_NAME
    my_settings['DEBUG'] = settings.DEBUG
    my_settings['USING_RUNSERVER'] = 'runserver' in sys.argv
    my_settings['ASKBOT_VERSION'] = askbot.get_version()
    my_settings['LOGIN_URL'] = url_utils.get_login_url()
    my_settings['LOGOUT_URL'] = url_utils.get_logout_url()

    if my_settings['EDITOR_TYPE'] == 'tinymce':
        tinymce_plugins = settings.TINYMCE_DEFAULT_CONFIG.get('plugins', '').split(',')
        my_settings['TINYMCE_PLUGINS'] = map(lambda v: v.strip(), tinymce_plugins)
        my_settings['TINYMCE_EDITOR_DESELECTOR'] = settings.TINYMCE_DEFAULT_CONFIG['editor_deselector']
        my_settings['TINYMCE_CONFIG_JSON'] = json.dumps(settings.TINYMCE_DEFAULT_CONFIG)
    else:
        my_settings['TINYMCE_PLUGINS'] = []
        my_settings['TINYMCE_EDITOR_DESELECTOR'] = ''

    my_settings['LOGOUT_REDIRECT_URL'] = url_utils.get_logout_redirect_url()

    current_language = get_language()

    #for some languages we will start searching for shorter words
    if current_language == 'ja':
        #we need to open the search box and show info message about
        #the japanese lang search
        min_search_word_length = 1
    else:
        min_search_word_length = my_settings['MIN_SEARCH_WORD_LENGTH']

    need_scope_links = askbot_settings.ALL_SCOPE_ENABLED or \
                    askbot_settings.UNANSWERED_SCOPE_ENABLED or \
                    (request.user.is_authenticated() and askbot_settings.FOLLOWED_SCOPE_ENABLED)

    context = {
        'base_url': site_url(''),
        'csrf_token': get_or_create_csrf_token(request),
        'empty_search_state': SearchState.get_empty(),
        'min_search_word_length': min_search_word_length,
        'current_language_code': current_language,
        'settings': my_settings,
        'moderation_items': api.get_info_on_moderation_items(request.user),
        'need_scope_links': need_scope_links,
        'noscript_url': const.DEPENDENCY_URLS['noscript'],
    }

    use_askbot_login = '******' in settings.INSTALLED_APPS
    my_settings['USE_ASKBOT_LOGIN_SYSTEM'] = use_askbot_login
    if use_askbot_login and request.user.is_anonymous():
        from askbot.deps.django_authopenid import context as login_context
        context.update(login_context.login_context(request))

    if askbot_settings.GROUPS_ENABLED:
        #calculate context needed to list all the groups
        def _get_group_url(group):
            """calculates url to the group based on its id and name"""
            group_slug = slugify(group['name'])
            return reverse(
                'users_by_group',
                kwargs={'group_id': group['id'], 'group_slug': group_slug}
            )

        #load id's and names of all groups
        global_group = models.Group.objects.get_global_group()
        groups = models.Group.objects.exclude_personal()
        groups = groups.exclude(id=global_group.id)
        groups_data = list(groups.values('id', 'name'))

        #sort groups_data alphanumerically, but case-insensitive
        groups_data = sorted(
                        groups_data,
                        lambda x, y: cmp(x['name'].lower(), y['name'].lower())
                    )

        #insert data for the global group at the first position
        groups_data.insert(0, {'id': global_group.id, 'name': global_group.name})

        #build group_list for the context
        group_list = list()
        for group in groups_data:
            link = _get_group_url(group)
            group_list.append({'name': group['name'], 'link': link})
        context['group_list'] = simplejson.dumps(group_list)

    if askbot_settings.EDITOR_TYPE == 'tinymce':
        from tinymce.widgets import TinyMCE
        context['tinymce'] = TinyMCE()

    return context
示例#26
0
def show_users(request, by_group=False, group_id=None, group_slug=None):
    """Users view, including listing of users by group"""
    if askbot_settings.GROUPS_ENABLED and not by_group:
        default_group = models.Group.objects.get_global_group()
        group_slug = slugify(default_group.name)
        new_url = reverse('users_by_group',
                          kwargs={
                              'group_id': default_group.id,
                              'group_slug': group_slug
                          })
        return HttpResponseRedirect(new_url)

    users = models.User.objects.exclude(askbot_profile__status='b').exclude(
        is_active=False).select_related('askbot_profile')

    if askbot.is_multilingual():
        users = users.filter(
            localized_askbot_profiles__language_code=get_language(),
            localized_askbot_profiles__is_claimed=True)

    group = None
    group_email_moderation_enabled = False
    user_acceptance_level = 'closed'
    user_membership_level = 'none'
    if by_group == True:
        if askbot_settings.GROUPS_ENABLED == False:
            raise Http404
        if group_id:
            if all((group_id, group_slug)) == False:
                return HttpResponseRedirect('groups')
            else:
                try:
                    group = models.Group.objects.get(id=group_id)
                    group_email_moderation_enabled = (
                        askbot_settings.GROUP_EMAIL_ADDRESSES_ENABLED \
                        and askbot_settings.CONTENT_MODERATION_MODE == 'premoderation'
                    )
                    user_acceptance_level = group.get_openness_level_for_user(
                        request.user)
                except models.Group.DoesNotExist:
                    raise Http404
                if group_slug == slugify(group.name):
                    #filter users by full group memberships
                    #todo: refactor as Group.get_full_members()
                    full_level = models.GroupMembership.FULL
                    memberships = models.GroupMembership.objects.filter(
                        group=group, level=full_level)
                    user_ids = memberships.values_list('user__id', flat=True)
                    users = users.filter(id__in=user_ids)
                    if request.user.is_authenticated():
                        membership = request.user.get_group_membership(group)
                        if membership:
                            user_membership_level = membership.get_level_display(
                            )

                else:
                    group_page_url = reverse('users_by_group',
                                             kwargs={
                                                 'group_id': group.id,
                                                 'group_slug':
                                                 slugify(group.name)
                                             })
                    return HttpResponseRedirect(group_page_url)

    is_paginated = True

    form = forms.ShowUsersForm(request.REQUEST)
    form.full_clean()  #always valid
    sort_method = form.cleaned_data['sort']
    page = form.cleaned_data['page']
    search_query = form.cleaned_data['query']

    if search_query == '':
        if sort_method == 'newest':
            order_by_parameter = '-date_joined'
        elif sort_method == 'last':
            order_by_parameter = 'date_joined'
        elif sort_method == 'name':
            order_by_parameter = 'username'
        else:
            # default
            if askbot.is_multilingual():
                order_by_parameter = '-localized_askbot_profiles__reputation'
            else:
                order_by_parameter = '-askbot_profile__reputation'

        objects_list = Paginator(users.order_by(order_by_parameter),
                                 askbot_settings.USERS_PAGE_SIZE)
        base_url = request.path + '?sort=%s&' % sort_method
    else:
        sort_method = 'reputation'
        matching_users = models.get_users_by_text_query(search_query, users)
        objects_list = Paginator(
            matching_users.order_by('-askbot_profile__reputation'),
            askbot_settings.USERS_PAGE_SIZE)
        base_url = request.path + '?name=%s&sort=%s&' % (search_query,
                                                         sort_method)

    try:
        users_page = objects_list.page(page)
    except (EmptyPage, InvalidPage):
        users_page = objects_list.page(objects_list.num_pages)

    paginator_data = {
        'is_paginated': is_paginated,
        'pages': objects_list.num_pages,
        'current_page_number': page,
        'page_object': users_page,
        'base_url': base_url
    }
    paginator_context = functions.setup_paginator(paginator_data)  #

    #todo: move to contexts
    #extra context for the groups
    if askbot_settings.GROUPS_ENABLED:
        #todo: cleanup this branched code after groups are migrated to auth_group
        user_groups = models.Group.objects.exclude_personal()
        if len(user_groups) <= 1:
            assert (user_groups[0].name == askbot_settings.GLOBAL_GROUP_NAME)
            user_groups = None
        group_openness_choices = models.Group().get_openness_choices()
    else:
        user_groups = None
        group_openness_choices = None

    data = {
        'active_tab': 'users',
        'group': group,
        'group_email_moderation_enabled': group_email_moderation_enabled,
        'group_openness_choices': group_openness_choices,
        'page_class': 'users-page',
        'paginator_context': paginator_context,
        'search_query': search_query,
        'tab_id': sort_method,
        'user_acceptance_level': user_acceptance_level,
        'user_count': objects_list.count,
        'user_groups': user_groups,
        'user_membership_level': user_membership_level,
        'users': users_page,
    }

    return render(request, 'users.html', data)
示例#27
0
def application_settings(request):
    """The context processor function"""
    # if not request.path.startswith('/' + settings.ASKBOT_URL):
    #     #todo: this is a really ugly hack, will only work
    #     #when askbot is installed not at the home page.
    #     #this will not work for the
    #     #heavy modders of askbot, because their custom pages
    #     #will not receive the askbot settings in the context
    #     #to solve this properly we should probably explicitly
    #     #add settings to the context per page
    #     return {}
    my_settings = askbot_settings.as_dict()
    my_settings['LANGUAGE_CODE'] = getattr(request, 'LANGUAGE_CODE',
                                           settings.LANGUAGE_CODE)
    my_settings['LANGUAGE_MODE'] = askbot.get_lang_mode()
    my_settings['MULTILINGUAL'] = askbot.is_multilingual()
    my_settings['LANGUAGES_DICT'] = dict(getattr(settings, 'LANGUAGES', []))
    my_settings[
        'ALLOWED_UPLOAD_FILE_TYPES'] = settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES
    my_settings['ASKBOT_URL'] = settings.ASKBOT_URL
    my_settings['STATIC_URL'] = settings.STATIC_URL
    my_settings['IP_MODERATION_ENABLED'] = getattr(
        settings, 'ASKBOT_IP_MODERATION_ENABLED', False)
    my_settings['USE_LOCAL_FONTS'] = getattr(settings,
                                             'ASKBOT_USE_LOCAL_FONTS', False)
    my_settings['CSRF_COOKIE_NAME'] = settings.CSRF_COOKIE_NAME
    my_settings['DEBUG'] = settings.DEBUG
    my_settings['USING_RUNSERVER'] = 'runserver' in sys.argv
    my_settings['ASKBOT_VERSION'] = askbot.get_version()
    my_settings['LOGIN_URL'] = url_utils.get_login_url()
    my_settings['LOGOUT_URL'] = url_utils.get_logout_url()

    if my_settings['EDITOR_TYPE'] == 'tinymce':
        tinymce_plugins = settings.TINYMCE_DEFAULT_CONFIG.get('plugins',
                                                              '').split(',')
        my_settings['TINYMCE_PLUGINS'] = [v.strip() for v in tinymce_plugins]
        my_settings[
            'TINYMCE_EDITOR_DESELECTOR'] = settings.TINYMCE_DEFAULT_CONFIG[
                'editor_deselector']
        my_settings['TINYMCE_CONFIG_JSON'] = json.dumps(
            settings.TINYMCE_DEFAULT_CONFIG)
    else:
        my_settings['TINYMCE_PLUGINS'] = []
        my_settings['TINYMCE_EDITOR_DESELECTOR'] = ''

    my_settings['LOGOUT_REDIRECT_URL'] = url_utils.get_logout_redirect_url()

    current_language = get_language()

    # for some languages we will start searching for shorter words
    if current_language == 'ja':
        # we need to open the search box and show info message about
        # the japanese lang search
        min_search_word_length = 1
    else:
        min_search_word_length = my_settings['MIN_SEARCH_WORD_LENGTH']

    need_scope_links = askbot_settings.ALL_SCOPE_ENABLED or \
        askbot_settings.UNANSWERED_SCOPE_ENABLED or \
        (request.user.is_authenticated and askbot_settings.FOLLOWED_SCOPE_ENABLED)

    context = {
        'base_url': site_url(''),
        'csrf_token': csrf.get_token(request),
        'empty_search_state': SearchState.get_empty(),
        'min_search_word_length': min_search_word_length,
        'current_language_code': current_language,
        'settings': my_settings,
        'moderation_items': api.get_info_on_moderation_items(request.user),
        'need_scope_links': need_scope_links,
        'noscript_url': const.DEPENDENCY_URLS['noscript'],
    }

    use_askbot_login = '******' in settings.INSTALLED_APPS
    my_settings['USE_ASKBOT_LOGIN_SYSTEM'] = use_askbot_login
    if use_askbot_login and request.user.is_anonymous:
        from askbot.deps.django_authopenid import context as login_context
        context.update(login_context.login_context(request))

    context['group_list'] = json.dumps(make_group_list())

    if askbot_settings.EDITOR_TYPE == 'tinymce':
        from tinymce.widgets import TinyMCE
        context['tinymce'] = TinyMCE()

    return context
示例#28
0
def get_alias():
    if askbot.is_multilingual():
        language = get_language()
        return alias_from_language(language)
    return DEFAULT_ALIAS
示例#29
0
from django.conf import settings
try:
    from django.conf.urls import handler404
    from django.conf.urls import include, patterns, url
except ImportError:
    from django.conf.urls.defaults import handler404
    from django.conf.urls.defaults import include, patterns, url

import askbot
from askbot.views.error import internal_error as handler500
from django.conf import settings
from django.contrib import admin

admin.autodiscover()

if askbot.is_multilingual():
    from django.conf.urls.i18n import i18n_patterns
    urlpatterns = i18n_patterns(
        '', (r'%s' % settings.ASKBOT_URL, include('askbot.urls')))
else:
    urlpatterns = patterns(
        '', (r'%s' % settings.ASKBOT_URL, include('askbot.urls')))

urlpatterns += patterns(
    '',
    (r'^admin/', include(admin.site.urls)),
    #(r'^cache/', include('keyedcache.urls')), - broken views disable for now
    #(r'^settings/', include('askbot.deps.livesettings.urls')),
    (r'^followit/', include('followit.urls')),
    (r'^tinymce/', include('tinymce.urls')),
    (r'^robots.txt$', include('robots.urls')),
示例#30
0
        skins[skin_code].set_language(language_code)
        #from askbot.templatetags import extra_filters_jinja as filters
        #skins[skin_name].filters['media'] = filters.media
    return skins

def get_app_dir_env(language_code):
    env = AppDirectoryEnvironment(
                            extensions=['jinja2.ext.i18n',],
                            globals={'settings': askbot_settings}
                        )
    env.set_language(language_code)
    return env

LOADERS = django_settings.TEMPLATES
SKINS = dict()
if askbot.is_multilingual() or HAS_ASKBOT_LOCALE_MIDDLEWARE:
    for lang in dict(django_settings.LANGUAGES).keys():
        SKINS.update(load_skins(lang))
else:
    SKINS = load_skins(django_settings.LANGUAGE_CODE)

APP_DIR_ENVS = dict()
if 'askbot.skins.loaders.JinjaAppDirectoryLoader' in LOADERS:
    if askbot.is_multilingual() or HAS_ASKBOT_LOCALE_MIDDLEWARE:
        for lang in dict(django_settings.LANGUAGES).keys():
            APP_DIR_ENVS[lang] = get_app_dir_env(lang)
    else:
        lang = django_settings.LANGUAGE_CODE
        APP_DIR_ENVS[lang] = get_app_dir_env(lang)

def get_skin():
示例#31
0
                       default='',
                       description=_('Custom destination URL for the logo'),
                       update_callback=logo_destination_callback))

settings.register(
    values.ImageValue(GENERAL_SKIN_SETTINGS,
                      'SITE_LOGO_URL',
                      description=_('Q&amp;A site logo'),
                      help_text=_(
                          'To change the logo, select new file, then submit'
                          'this whole form.'),
                      default='/images/logo.gif',
                      url_resolver=skin_utils.get_media_url))

# Cannot use HAS_ASKBOT_LOCALE_MIDDLEWARE due to circular import error
if not askbot.is_multilingual() and \
        'askbot.middleware.locale.LocaleMiddleware' in django_settings.MIDDLEWARE_CLASSES:
    settings.register(
        values.StringValue(
            GENERAL_SKIN_SETTINGS,
            'ASKBOT_LANGUAGE',
            default=django_settings.LANGUAGE_CODE,
            choices=django_settings.LANGUAGES,
            description=_('Select Language'),
        ))

settings.register(
    values.BooleanValue(
        GENERAL_SKIN_SETTINGS,
        'SHOW_LOGO',
        description=_('Show logo'),
示例#32
0
    def get_updated_questions_for_user(self, user):
        """
        retreive relevant question updates for the user
        according to their subscriptions and recorded question
        views
        """

        user_feeds = EmailFeedSetting.objects.filter(subscriber=user).exclude(
            frequency__in=('n', 'i'))

        should_proceed = False
        for feed in user_feeds:
            if feed.should_send_now() == True:
                should_proceed = True
                break

        #shortcircuit - if there is no ripe feed to work on for this user
        if should_proceed == False:
            return {}

        #these are placeholders for separate query sets per question group
        #there are four groups - one for each EmailFeedSetting.feed_type
        #and each group has subtypes A and B
        #that's because of the strange thing commented below
        #see note on Q and F objects marked with todo tag
        q_sel_A = None
        q_sel_B = None

        q_ask_A = None
        q_ask_B = None

        q_ans_A = None
        q_ans_B = None

        q_all_A = None
        q_all_B = None

        #base question query set for this user
        #basic things - not deleted, not closed, not too old
        #not last edited by the same user
        base_qs = Post.objects.get_questions(
        ).exclude(thread__last_activity_by=user).exclude(
            thread__last_activity_at__lt=user.date_joined  #exclude old stuff
        ).exclude(deleted=True).exclude(
            thread__closed=True).order_by('-thread__last_activity_at')

        if askbot_settings.CONTENT_MODERATION_MODE == 'premoderation':
            base_qs = base_qs.filter(approved=True)
        #todo: for some reason filter on did not work as expected ~Q(viewed__who=user) |
        #      Q(viewed__who=user,viewed__when__lt=F('thread__last_activity_at'))
        #returns way more questions than you might think it should
        #so because of that I've created separate query sets Q_set2 and Q_set3
        #plus two separate queries run faster!

        #build two two queries based

        #questions that are not seen by the user at all
        not_seen_qs = base_qs.filter(~Q(viewed__who=user))
        #questions that were seen, but before last modification
        seen_before_last_mod_qs = base_qs.filter(
            Q(viewed__who=user,
              viewed__when__lt=F('thread__last_activity_at')))

        #shorten variables for convenience
        Q_set_A = not_seen_qs
        Q_set_B = seen_before_last_mod_qs

        if askbot.is_multilingual():
            languages = user.languages.split()
        else:
            languages = None

        for feed in user_feeds:
            if feed.feed_type == 'm_and_c':
                #alerts on mentions and comments are processed separately
                #because comments to questions do not trigger change of last_updated
                #this may be changed in the future though, see
                #http://askbot.org/en/question/96/
                continue

            #each group of updates represented by the corresponding
            #query set has it's own cutoff time
            #that cutoff time is computed for each user individually
            #and stored as a parameter "cutoff_time"

            #we won't send email for a given question if an email has been
            #sent after that cutoff_time
            if feed.should_send_now():
                if DEBUG_THIS_COMMAND == False:
                    feed.mark_reported_now()
                cutoff_time = feed.get_previous_report_cutoff_time()

                if feed.feed_type == 'q_sel':
                    q_sel_A = Q_set_A.filter(thread__followed_by=user)
                    q_sel_A.cutoff_time = cutoff_time  #store cutoff time per query set
                    q_sel_B = Q_set_B.filter(thread__followed_by=user)
                    q_sel_B.cutoff_time = cutoff_time  #store cutoff time per query set

                elif feed.feed_type == 'q_ask':
                    q_ask_A = Q_set_A.filter(author=user)
                    q_ask_A.cutoff_time = cutoff_time
                    q_ask_B = Q_set_B.filter(author=user)
                    q_ask_B.cutoff_time = cutoff_time

                elif feed.feed_type == 'q_ans':
                    q_ans_A = Q_set_A.filter(thread__posts__author=user,
                                             thread__posts__post_type='answer')
                    q_ans_A = q_ans_A[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_ans_A.cutoff_time = cutoff_time

                    q_ans_B = Q_set_B.filter(thread__posts__author=user,
                                             thread__posts__post_type='answer')
                    q_ans_B = q_ans_B[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_ans_B.cutoff_time = cutoff_time

                elif feed.feed_type == 'q_all':
                    q_all_A = user.get_tag_filtered_questions(Q_set_A)
                    q_all_B = user.get_tag_filtered_questions(Q_set_B)

                    q_all_A = q_all_A[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_all_B = q_all_B[:askbot_settings.MAX_ALERTS_PER_EMAIL]
                    q_all_A.cutoff_time = cutoff_time
                    q_all_B.cutoff_time = cutoff_time

        #build ordered list questions for the email report
        q_list = SortedDict()

        #todo: refactor q_list into a separate class?
        extend_question_list(q_sel_A, q_list, languages=languages)
        extend_question_list(q_sel_B, q_list, languages=languages)

        #build list of comment and mention responses here
        #it is separate because posts are not marked as changed
        #when people add comments
        #mention responses could be collected in the loop above, but
        #it is inconvenient, because feed_type m_and_c bundles the two
        #also we collect metadata for these here
        try:
            feed = user_feeds.get(feed_type='m_and_c')
            if feed.should_send_now():
                cutoff_time = feed.get_previous_report_cutoff_time()
                comments = Post.objects.get_comments().filter(
                    added_at__lt=cutoff_time).exclude(
                        author=user).select_related('parent')
                q_commented = list()

                for c in comments:
                    post = c.parent

                    if post.author_id != user.pk:
                        continue

                    #skip is post was seen by the user after
                    #the comment posting time
                    q_commented.append(post.get_origin_post())

                extend_question_list(q_commented,
                                     q_list,
                                     cutoff_time=cutoff_time,
                                     add_comment=True,
                                     languages=languages)

                mentions = Activity.objects.get_mentions(
                    mentioned_at__lt=cutoff_time, mentioned_whom=user)

                #print 'have %d mentions' % len(mentions)
                #MM = Activity.objects.filter(activity_type = const.TYPE_ACTIVITY_MENTION)
                #print 'have %d total mentions' % len(MM)
                #for m in MM:
                #    print m

                mention_posts = get_all_origin_posts(mentions)
                q_mentions_id = [q.id for q in mention_posts]

                q_mentions_A = Q_set_A.filter(id__in=q_mentions_id)
                q_mentions_A.cutoff_time = cutoff_time
                extend_question_list(q_mentions_A,
                                     q_list,
                                     add_mention=True,
                                     languages=languages)

                q_mentions_B = Q_set_B.filter(id__in=q_mentions_id)
                q_mentions_B.cutoff_time = cutoff_time
                extend_question_list(q_mentions_B,
                                     q_list,
                                     add_mention=True,
                                     languages=languages)
        except EmailFeedSetting.DoesNotExist:
            pass

        if user.email_tag_filter_strategy == const.INCLUDE_INTERESTING:
            extend_question_list(q_all_A, q_list, languages=languages)
            extend_question_list(q_all_B, q_list, languages=languages)

        extend_question_list(q_ask_A, q_list, limit=True, languages=languages)
        extend_question_list(q_ask_B, q_list, limit=True, languages=languages)

        extend_question_list(q_ans_A, q_list, limit=True, languages=languages)
        extend_question_list(q_ans_B, q_list, limit=True, languages=languages)

        if user.email_tag_filter_strategy == const.EXCLUDE_IGNORED:
            extend_question_list(q_all_A,
                                 q_list,
                                 limit=True,
                                 languages=languages)
            extend_question_list(q_all_B,
                                 q_list,
                                 limit=True,
                                 languages=languages)

        ctype = ContentType.objects.get_for_model(Post)
        EMAIL_UPDATE_ACTIVITY = const.TYPE_ACTIVITY_EMAIL_UPDATE_SENT

        #up to this point we still don't know if emails about
        #collected questions were sent recently
        #the next loop examines activity record and decides
        #for each question, whether it needs to be included or not
        #into the report

        for q, meta_data in q_list.items():
            #this loop edits meta_data for each question
            #so that user will receive counts on new edits new answers, etc
            #and marks questions that need to be skipped
            #because an email about them was sent recently enough

            #also it keeps a record of latest email activity per question per user
            try:
                #todo: is it possible to use content_object here, instead of
                #content type and object_id pair?
                update_info = Activity.objects.get(
                    user=user,
                    content_type=ctype,
                    object_id=q.id,
                    activity_type=EMAIL_UPDATE_ACTIVITY)
                emailed_at = update_info.active_at
            except Activity.DoesNotExist:
                update_info = Activity(user=user,
                                       content_object=q,
                                       activity_type=EMAIL_UPDATE_ACTIVITY)
                emailed_at = datetime.datetime(1970, 1, 1)  #long time ago
                if django_settings.USE_TZ:
                    emailed_at = timezone.make_aware(emailed_at, timezone.utc)
            except Activity.MultipleObjectsReturned:
                raise Exception(
                    'server error - multiple question email activities '
                    'found per user-question pair')

            cutoff_time = meta_data[
                'cutoff_time']  #cutoff time for the question

            #skip question if we need to wait longer because
            #the delay before the next email has not yet elapsed
            #or if last email was sent after the most recent modification
            if emailed_at > cutoff_time or emailed_at > q.thread.last_activity_at:
                meta_data['skip'] = True
                continue

            #collect info on all sorts of news that happened after
            #the most recent emailing to the user about this question
            q_rev = q.revisions.filter(revised_at__gt=emailed_at)
            q_rev = q_rev.exclude(author=user)

            #now update all sorts of metadata per question
            meta_data['q_rev'] = len(q_rev)
            if len(q_rev) > 0 and q.added_at == q_rev[0].revised_at:
                meta_data['q_rev'] = 0
                meta_data['new_q'] = True
            else:
                meta_data['new_q'] = False

            new_ans = Post.objects.get_answers(user).filter(
                thread=q.thread,
                added_at__gt=emailed_at,
                deleted=False,
            )
            new_ans = new_ans.exclude(author=user)
            meta_data['new_ans'] = len(new_ans)

            ans_ids = Post.objects.get_answers(user).filter(
                thread=q.thread,
                added_at__gt=emailed_at,
                deleted=False,
            ).values_list('id', flat=True)

            ans_rev = PostRevision.objects.filter(post__id__in=ans_ids)
            ans_rev = ans_rev.exclude(author=user).distinct()

            meta_data['ans_rev'] = len(ans_rev)

            comments = meta_data.get('comments', 0)
            mentions = meta_data.get('mentions', 0)

            #print meta_data
            #finally skip question if there are no news indeed
            if len(q_rev) + len(new_ans) + len(
                    ans_rev) + comments + mentions == 0:
                meta_data['skip'] = True
                #print 'skipping'
            else:
                meta_data['skip'] = False
                #print 'not skipping'
                update_info.active_at = timezone.now()
                if DEBUG_THIS_COMMAND == False:
                    update_info.save()  #save question email update activity
        #q_list is actually an ordered dictionary
        #print 'user %s gets %d' % (user.username, len(q_list.keys()))
        #todo: sort question list by update time
        return q_list
示例#33
0
def show_users(request, by_group=False, group_id=None, group_slug=None):
    """Users view, including listing of users by group"""
    if askbot_settings.GROUPS_ENABLED and not by_group:
        default_group = models.Group.objects.get_global_group()
        group_slug = slugify(default_group.name)
        new_url = reverse('users_by_group',
                kwargs={'group_id': default_group.id,
                        'group_slug': group_slug})
        return HttpResponseRedirect(new_url)

    users = models.User.objects.exclude(
                                    askbot_profile__status='b'
                                ).exclude(
                                    is_active=False
                                ).select_related('askbot_profile')

    if askbot.is_multilingual():
        users = users.filter(
                    localized_askbot_profiles__language_code=get_language(),
                    localized_askbot_profiles__is_claimed=True
                )

    group = None
    group_email_moderation_enabled = False
    user_acceptance_level = 'closed'
    user_membership_level = 'none'
    if by_group == True:
        if askbot_settings.GROUPS_ENABLED == False:
            raise Http404
        if group_id:
            if all((group_id, group_slug)) == False:
                return HttpResponseRedirect('groups')
            else:
                try:
                    group = models.Group.objects.get(id = group_id)
                    group_email_moderation_enabled = (
                        askbot_settings.GROUP_EMAIL_ADDRESSES_ENABLED \
                        and askbot_settings.CONTENT_MODERATION_MODE == 'premoderation'
                    )
                    user_acceptance_level = group.get_openness_level_for_user(
                                                                    request.user
                                                                )
                except models.Group.DoesNotExist:
                    raise Http404
                if group_slug == slugify(group.name):
                    #filter users by full group memberships
                    #todo: refactor as Group.get_full_members()
                    full_level = models.GroupMembership.FULL
                    memberships = models.GroupMembership.objects.filter(
                                                    group=group, level=full_level
                                                )
                    user_ids = memberships.values_list('user__id', flat=True)
                    users = users.filter(id__in=user_ids)
                    if request.user.is_authenticated():
                        membership = request.user.get_group_membership(group)
                        if membership:
                            user_membership_level = membership.get_level_display()

                else:
                    group_page_url = reverse(
                                        'users_by_group',
                                        kwargs = {
                                            'group_id': group.id,
                                            'group_slug': slugify(group.name)
                                        }
                                    )
                    return HttpResponseRedirect(group_page_url)

    is_paginated = True

    form = forms.ShowUsersForm(request.REQUEST)
    form.full_clean()#always valid
    sort_method = form.cleaned_data['sort']
    page = form.cleaned_data['page']
    search_query = form.cleaned_data['query']

    if search_query == '':
        if sort_method == 'newest':
            order_by_parameter = '-date_joined'
        elif sort_method == 'last':
            order_by_parameter = 'date_joined'
        elif sort_method == 'name':
            order_by_parameter = 'username'
        else:
            # default
            if askbot.is_multilingual():
                order_by_parameter = '-localized_askbot_profiles__reputation'
            else:
                order_by_parameter = '-askbot_profile__reputation'


        objects_list = Paginator(
                            users.order_by(order_by_parameter),
                            askbot_settings.USERS_PAGE_SIZE
                        )
        base_url = request.path + '?sort=%s&' % sort_method
    else:
        sort_method = 'reputation'
        matching_users = models.get_users_by_text_query(search_query, users)
        objects_list = Paginator(
                            matching_users.order_by('-askbot_profile__reputation'),
                            askbot_settings.USERS_PAGE_SIZE
                        )
        base_url = request.path + '?name=%s&sort=%s&' % (search_query, sort_method)

    try:
        users_page = objects_list.page(page)
    except (EmptyPage, InvalidPage):
        users_page = objects_list.page(objects_list.num_pages)

    paginator_data = {
        'is_paginated' : is_paginated,
        'pages': objects_list.num_pages,
        'current_page_number': page,
        'page_object': users_page,
        'base_url' : base_url
    }
    paginator_context = functions.setup_paginator(paginator_data) #

    #todo: move to contexts
    #extra context for the groups
    if askbot_settings.GROUPS_ENABLED:
        #todo: cleanup this branched code after groups are migrated to auth_group
        user_groups = models.Group.objects.exclude_personal()
        if len(user_groups) <= 1:
            assert(user_groups[0].name == askbot_settings.GLOBAL_GROUP_NAME)
            user_groups = None
        group_openness_choices = models.Group().get_openness_choices()
    else:
        user_groups = None
        group_openness_choices = None

    data = {
        'active_tab': 'users',
        'group': group,
        'group_email_moderation_enabled': group_email_moderation_enabled,
        'group_openness_choices': group_openness_choices,
        'page_class': 'users-page',
        'paginator_context' : paginator_context,
        'search_query' : search_query,
        'tab_id' : sort_method,
        'user_acceptance_level': user_acceptance_level,
        'user_count': objects_list.count,
        'user_groups': user_groups,
        'user_membership_level': user_membership_level,
        'users' : users_page,
    }

    return render(request, 'users.html', data)
示例#34
0
        skins[skin_code].set_language(language_code)
        #from askbot.templatetags import extra_filters_jinja as filters
        #skins[skin_name].filters['media'] = filters.media
    return skins

def get_app_dir_env(language_code):
    env = AppDirectoryEnvironment(
                            extensions=['jinja2.ext.i18n',],
                            globals={'settings': askbot_settings}
                        )
    env.set_language(language_code)
    return env

LOADERS = django_settings.TEMPLATES
SKINS = dict()
if askbot.is_multilingual() or HAS_ASKBOT_LOCALE_MIDDLEWARE:
    for lang in dict(django_settings.LANGUAGES).keys():
        SKINS.update(load_skins(lang))
else:
    SKINS = load_skins(django_settings.LANGUAGE_CODE)

APP_DIR_ENVS = dict()
if 'askbot.skins.loaders.JinjaAppDirectoryLoader' in LOADERS:
    if askbot.is_multilingual() or HAS_ASKBOT_LOCALE_MIDDLEWARE:
        for lang in dict(django_settings.LANGUAGES).keys():
            APP_DIR_ENVS[lang] = get_app_dir_env(lang)
    else:
        lang = django_settings.LANGUAGE_CODE
        APP_DIR_ENVS[lang] = get_app_dir_env(lang)

def get_skin():