<commit_before>from urllib import urlencode

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib import messages
from django.views.generic import TemplateView
from django.utils.decorators import method_decorator

from go.wizard.forms import Wizard1CreateForm, Wizard1ExistingRouterForm
from go.conversation.forms import NewConversationForm
from go.channel.forms import NewChannelForm
from go.base.utils import (
    get_conversation_view_definition, conversation_or_404,
    get_router_view_definition)
from go.vumitools.account import RoutingTableHelper, GoConnector


import logging
logger = logging.getLogger(__name__)


class BaseWizardView(TemplateView):
    template_base = 'wizard_views'
    view_name = None

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(BaseWizardView, self).dispatch(*args, **kwargs)

    def get_template_names(self):
        return ['%s/%s.html' % (self.template_base, self.view_name)]


class WizardCreateView(BaseWizardView):
    view_name = 'wizard_1_create'

    def _render(self, request, wizard_form=None, conversation_form=None,
                channel_form=None, router_form=None):
        return self.render_to_response({
            'wizard_form': wizard_form or Wizard1CreateForm(),
            'conversation_form': (conversation_form or
                                  NewConversationForm(request.user_api)),
            'channel_form': (channel_form or NewChannelForm(request.user_api)),
            'router_form': (router_form or
                            Wizard1ExistingRouterForm(request.user_api)),
        })

    def get(self, request):
        return self._render(request)

    def post(self, request):
        # TODO: Reuse new conversation/channel view logic here.
        wiz_form = Wizard1CreateForm(request.POST)
        conv_form = NewConversationForm(request.user_api, request.POST)
        chan_form = NewChannelForm(request.user_api, request.POST)
        router_form = Wizard1ExistingRouterForm(request.user_api, request.POST)

        forms_to_validate = [wiz_form, conv_form]
        # We do this on the raw POST data so we can validate in one step.
        if request.POST.get('channel_kind') == 'new':
            forms_to_validate.append(chan_form)
        elif request.POST.get('channel_kind') == 'existing':
            forms_to_validate.append(router_form)

        if not all(form.is_valid() for form in forms_to_validate):
            # TODO: Better validation.
            logger.info("Validation failed: %s" % (
                [frm.errors for frm in forms_to_validate],))
            return self._render(request, wizard_form=wiz_form,
                                conversation_form=conv_form,
                                channel_form=chan_form,
                                router_form=router_form)

        # Create conversation
        view_def, conv = self._create_conversation(
            request, conv_form.cleaned_data)

        wiz_data = wiz_form.cleaned_data
        if wiz_data['channel_kind'] == 'new':
            self._handle_new_channel(
                request, chan_form.cleaned_data, wiz_data['keyword'], conv)
        else:
            self._handle_existing_channel(
                request, router_form.cleaned_data, conv)

        messages.info(request, 'Conversation created successfully.')
        if view_def.is_editable:
            return redirect(view_def.get_view_url(
                'edit', conversation_key=conv.key))
        else:
            return redirect(view_def.get_view_url(
                'show', conversation_key=conv.key))

    def _handle_new_channel(self, request, chan_data, keyword, conv):
        channel = tuple(chan_data['channel'].split(':'))
        if channel[1]:
            tag = request.user_api.acquire_specific_tag(channel)
        else:
            tag = request.user_api.acquire_tag(channel[0])

        # Set up routing
        if keyword:
            # Create router
            endpoint, router = self._create_keyword_router(
                request, keyword, ':'.join(tag))
            self._setup_keyword_routing(
                request, conv, tag, router, endpoint)
        else:
            self._setup_basic_routing(request, conv, tag)

    def _handle_existing_channel(self, request, router_data, conv):
        # TODO: Check that keyword is unused.
        router = request.user_api.get_router(router_data['existing_router'])
        keyword = router_data['new_keyword']
        endpoint = 'keyword_%s' % (keyword.lower(),)
        # TODO: Better way to manage this kind of thing.
        kem = router.config.setdefault('keyword_endpoint_mapping', {})
        kem[keyword] = endpoint
        if endpoint not in router.extra_outbound_endpoints:
            router.extra_outbound_endpoints.append(endpoint)
        router.save()

        self._setup_keyword_routing(request, conv, None, router, endpoint)

    def _create_conversation(self, request, conv_data):
        conversation_type = conv_data['conversation_type']<commit_msg>Safer channel splitting in wizard view.<commit_after>from urllib import urlencode

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib import messages
from django.views.generic import TemplateView
from django.utils.decorators import method_decorator

from go.wizard.forms import Wizard1CreateForm, Wizard1ExistingRouterForm
from go.conversation.forms import NewConversationForm
from go.channel.forms import NewChannelForm
from go.base.utils import (
    get_conversation_view_definition, conversation_or_404,
    get_router_view_definition)
from go.vumitools.account import RoutingTableHelper, GoConnector


import logging
logger = logging.getLogger(__name__)


class BaseWizardView(TemplateView):
    template_base = 'wizard_views'
    view_name = None

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(BaseWizardView, self).dispatch(*args, **kwargs)

    def get_template_names(self):
        return ['%s/%s.html' % (self.template_base, self.view_name)]


class WizardCreateView(BaseWizardView):
    view_name = 'wizard_1_create'

    def _render(self, request, wizard_form=None, conversation_form=None,
                channel_form=None, router_form=None):
        return self.render_to_response({
            'wizard_form': wizard_form or Wizard1CreateForm(),
            'conversation_form': (conversation_form or
                                  NewConversationForm(request.user_api)),
            'channel_form': (channel_form or NewChannelForm(request.user_api)),
            'router_form': (router_form or
                            Wizard1ExistingRouterForm(request.user_api)),
        })

    def get(self, request):
        return self._render(request)

    def post(self, request):
        # TODO: Reuse new conversation/channel view logic here.
        wiz_form = Wizard1CreateForm(request.POST)
        conv_form = NewConversationForm(request.user_api, request.POST)
        chan_form = NewChannelForm(request.user_api, request.POST)
        router_form = Wizard1ExistingRouterForm(request.user_api, request.POST)

        forms_to_validate = [wiz_form, conv_form]
        # We do this on the raw POST data so we can validate in one step.
        if request.POST.get('channel_kind') == 'new':
            forms_to_validate.append(chan_form)
        elif request.POST.get('channel_kind') == 'existing':
            forms_to_validate.append(router_form)

        if not all(form.is_valid() for form in forms_to_validate):
            # TODO: Better validation.
            logger.info("Validation failed: %s" % (
                [frm.errors for frm in forms_to_validate],))
            return self._render(request, wizard_form=wiz_form,
                                conversation_form=conv_form,
                                channel_form=chan_form,
                                router_form=router_form)

        # Create conversation
        view_def, conv = self._create_conversation(
            request, conv_form.cleaned_data)

        wiz_data = wiz_form.cleaned_data
        if wiz_data['channel_kind'] == 'new':
            self._handle_new_channel(
                request, chan_form.cleaned_data, wiz_data['keyword'], conv)
        else:
            self._handle_existing_channel(
                request, router_form.cleaned_data, conv)

        messages.info(request, 'Conversation created successfully.')
        if view_def.is_editable:
            return redirect(view_def.get_view_url(
                'edit', conversation_key=conv.key))
        else:
            return redirect(view_def.get_view_url(
                'show', conversation_key=conv.key))

    def _handle_new_channel(self, request, chan_data, keyword, conv):
        channel = tuple(chan_data['channel'].split(':', 1))
        if channel[1]:
            tag = request.user_api.acquire_specific_tag(channel)
        else:
            tag = request.user_api.acquire_tag(channel[0])

        # Set up routing
        if keyword:
            # Create router
            endpoint, router = self._create_keyword_router(
                request, keyword, ':'.join(tag))
            self._setup_keyword_routing(
                request, conv, tag, router, endpoint)
        else:
            self._setup_basic_routing(request, conv, tag)

    def _handle_existing_channel(self, request, router_data, conv):
        # TODO: Check that keyword is unused.
        router = request.user_api.get_router(router_data['existing_router'])
        keyword = router_data['new_keyword']
        endpoint = 'keyword_%s' % (keyword.lower(),)
        # TODO: Better way to manage this kind of thing.
        kem = router.config.setdefault('keyword_endpoint_mapping', {})
        kem[keyword] = endpoint
        if endpoint not in router.extra_outbound_endpoints:
            router.extra_outbound_endpoints.append(endpoint)
        router.save()

        self._setup_keyword_routing(request, conv, None, router, endpoint)

    def _create_conversation(self, request, conv_data):
        conversation_type = conv_data['conversation_type']
{'fraction_non_alphanumeric': 0.08691471973848669, 'fraction_numerical': 0.0024036150370156718, 'mean_word_length': 2.779796511627907, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2312133', 'n_tokens_mistral': 2941, 'n_tokens_neox': 2852, 'n_words': 623}