Example #1
0
class MessageSerializer(serializers.ModelSerializer):
    """
    Message serializer.
    """
    next_handler = injections.depends(ProgressHandler)

    input = serializers.SerializerMethodField()
    # errors = serializers.CharField(source='get_errors', read_only=True)
    addMessages = serializers.SerializerMethodField()
    nextMessagesUrl = serializers.CharField(source='get_next_url',
                                            read_only=True)

    class Meta:
        model = Message
        fields = (
            'id',
            'input',
            'addMessages',
            'nextMessagesUrl',
            # 'errors',
        )

    def set_group(self, obj):
        try:
            getattr(self, 'qs')
        except AttributeError:
            self.qs = [obj]
            if obj.timestamp:
                current = obj
                for message in obj.chat.message_set.filter(
                        timestamp__gt=obj.timestamp):
                    if self.next_handler.group_filter(current, message):
                        current = message
                        self.qs.append(message)

    def get_input(self, obj):
        """
        Getting description for next message.
        """
        self.set_group(obj)
        input_data = {
            'type':
            obj.get_next_input_type(),
            'url':
            obj.get_next_url(),
            'options':
            obj.get_options(),
            'includeSelectedValuesFromMessages':
            [i.id for i in self.qs if i.contenttype == 'uniterror']
        }
        if not obj.chat.next_point:
            input_data['html'] = ' '
        return InputSerializer().to_representation(input_data)

    def get_addMessages(self, obj):
        self.set_group(obj)
        return InternalMessageSerializer(many=True).to_representation(self.qs)
Example #2
0
class TwilioGateway:
    executor = injections.depends(ThreadPoolExecutor)

    def __init__(self, loop, account_id, auth_token):
        self.loop = loop
        self.account_id = account_id
        self.auth_token = auth_token
        self.client = Client(self.account_id, self.auth_token)

    @run_in_executor()
    def _send_sms(self, message, callback=None):
        self.client.messages.create(
            body=message,
            from_="+13392007215",
            status_callback=callback,
            to="+380974219029",
        )

    async def send_sms(self, message, callback=None):
        return await self._send_sms(message, callback)
Example #3
0
class UsersHandler:
    elastic = injections.depends(aioelasticsearch.Elasticsearch)

    index = "users"
    doc_type = "document"

    async def search(self, request):
        q = request.query.get("query")

        query = {"query": {"match_all": {}}}

        if q is not None:
            query = {"query": {"match": {"name": q}}}

        resp = await self.elastic.search(
            index=self.index, doc_type=self.doc_type, body=query
        )

        if not resp:
            raise web.HTTPNotFound

        users = [doc["_source"] for doc in resp["hits"]["hits"]]

        return web.json_response({"users": UsersOutputTrafaret(users)})
Example #4
0
 class B(object):
     c = di.depends(object, 'c')
Example #5
0
 class A(object):
     b = di.depends(object, 'b')
     y = di.depends(Y, 'y')
Example #6
0
 class Cache(Base):
     processor = di.depends(Base, 'processor')
Example #7
0
 class Processor(Base):
     cache = di.depends(Base, 'cache')
Example #8
0
        class Source:
            value = di.depends(self.Consumer, 'consumer')

            def __injected__(self):
                assert self.value.value is 'John'
Example #9
0
class MessagesView(ValidateMixin, generics.RetrieveUpdateAPIView,
                   viewsets.GenericViewSet):
    """
    GET or UPDATE one message.
    """
    parser_classes = (JSONParser, )
    next_handler = injections.depends(ProgressHandler)

    serializer_class = MessageSerializer
    queryset = Message.objects.all()
    authentication_classes = (SessionAuthentication, )
    permission_classes = (IsAuthenticated, IsOwner)

    def roll_fsm_forward(self, chat, message):
        """ This method should be used when we want to roll fsm forward to the next serialized message and return it.

        :param chat: Chat instance
        :param message: Message
        :return: Response with serialized message
        """
        chat.next_point = self.next_handler.next_point(current=message.content,
                                                       chat=chat,
                                                       message=message,
                                                       request=self.request)
        chat.save()
        message.chat = chat
        serializer = self.get_serializer(message)
        return Response(serializer.data)

    def retrieve(self, request, *args, **kwargs):
        message = self.get_object()
        chat_id = self.request.GET.get('chat_id')
        try:
            chat = self.validate_and_get_chat(chat_id)
        except ValidationError as e:
            return Response({'errors': str(e)})
        self.check_object_permissions(self.request, chat)
        next_point = chat.next_point
        if (message.contenttype in ['response', 'uniterror']
                and message.content_id and next_point == message):
            return self.roll_fsm_forward(chat, message)
        if not message.chat or message.chat != chat or message.timestamp:
            serializer = self.get_serializer(message)
            return Response(serializer.data)

        if message and message.kind == 'add_faq' and message.sub_kind == 'add_faq':
            return self.roll_fsm_forward(chat, message)

        # Important for resolving additional messages
        if message and message.kind not in ('button', 'faqs'):
            if not ('additional' not in chat.state.fsmNode.funcName
                    and message.kind == 'response'):
                # Set next message for user
                if not message.timestamp:
                    message.timestamp = timezone.now()
                    message.save()
                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request)
                chat.save()
                message.chat = chat

        if message and message.kind == 'faqs':
            message.timestamp = timezone.now()
            message.save()

        serializer = self.get_serializer(message)
        return Response(serializer.data)

    def update(self, request, *args, **kwargs):
        chat_id = self.request.data.get('chat_id')
        try:
            chat = self.validate_and_get_chat(chat_id)
        except ValidationError as e:
            return Response({'errors': str(e)})
        self.check_object_permissions(self.request, chat)

        message = self.get_object()
        if (message.input_type == 'text'
                and not self.request.data.get('text', '').strip() and
                not message.lesson_to_answer.lesson.sub_kind == Lesson.CANVAS):
            return Response({'error': 'Empty response. Enter something!'})

        # run validation for numbers
        if message.lesson_to_answer and message.lesson_to_answer.lesson.sub_kind == 'numbers':
            try:
                float(self.request.data.get('text'))
            except ValueError:
                return Response({'error': 'Not correct value!'})
        # Consider to move it to a backgrount task
        update_activity(chat_id)
        return super(MessagesView, self).update(request, *args, **kwargs)

    def perform_update(self, serializer):
        chat_id = self.request.data.get('chat_id')
        message = self.get_object()
        node = message.chat.state.fsmNode
        chat = Chat.objects.get(id=chat_id, user=self.request.user)
        activity = chat.state and chat.state.activity

        def is_in_node(node: str) -> bool:
            return message.chat.state.fsmNode.name == node

        # Check if message is not in current chat
        if not message.chat or message.chat != chat:
            return

        # Do procced the user response in the FSMNode
        if hasattr(node._plugin, 'handler'):
            node._plugin.handler(message, chat, self.request,
                                 self.next_handler)
            return

        if is_chat_add_faq(message) and is_in_node('GET_NEW_FAQ'):
            message.text = self.request.data.get('option', 'no')
            message.save()
            chat.last_modify_timestamp = timezone.now()
            chat.save()

        if message.input_type == 'text' and not message.sub_kind == 'add_faq':
            message.chat = chat
            text = self.request.data.get('text')

            if message.lesson_to_answer.sub_kind == Lesson.EQUATION:
                text = text.strip("$")
                text = '.. math:: ' + text
            resp = StudentResponse(text=text)

            # convert base64 attachment string to django File
            data_attachment = self.request.data.get('attachment')
            if data_attachment and data_attachment.startswith('data:image'):
                format, image_string = data_attachment.split(';base64,')
                extension = format.split('/')[-1].split('+')[0]
                name = '{}-{}.{}'.format('canvas', key_secret_generator(),
                                         extension)
                resp.attachment = ContentFile(base64.b64decode(image_string),
                                              name=name)

            if not message.content_id:
                resp.lesson = message.lesson_to_answer.lesson
                resp.unitLesson = message.lesson_to_answer
                resp.course = message.chat.enroll_code.courseUnit.course
                resp.author = self.request.user
                resp.activity = activity
                resp.is_test = chat.is_test
                resp.is_preview = chat.enroll_code.isPreview
                resp.sub_kind = resp.lesson.sub_kind
            else:
                resp = message.content
                resp.text = text
            resp.is_trial = chat.is_trial
            resp.save()
            if not message.timestamp:
                message.content_id = resp.id
                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(content_id=resp.id,
                                timestamp=timezone.now(),
                                chat=chat)
            else:
                serializer.save()

        message_is_response = message.contenttype == 'response'
        lesson_has_sub_kind = message.lesson_to_answer and message.lesson_to_answer.sub_kind
        content_is_not_additional = not message.content and not message.is_additional
        mc_selfeval = None

        if (message_is_response and lesson_has_sub_kind
                and content_is_not_additional) or (
                    message_is_response and message.lesson_to_answer
                    and message.lesson_to_answer.sub_kind == 'choices'
                    and not content_is_not_additional):
            resp_text = ''
            if message.lesson_to_answer.sub_kind == Lesson.MULTIPLE_CHOICES:
                selected_items = self.request.data.get('selected')
                try:
                    selected = selected_items[str(message.id)]['choices']
                except KeyError:
                    # here request.data is like {"option":1,"chat_id":9,"selected":{"116":{"choices":[0]}}}
                    selected_msg_ids = list(
                        self.request.data.get('selected').keys())
                    # selected_messages == tuple with keys of this dict {"116":{"choices":[0]}} - it will be ("116",)
                    msg_ids = Message.objects.filter(id__in=selected_msg_ids,
                                                     chat=chat).values_list(
                                                         'id', flat=True)
                    correct_ids = set(msg_ids).intersection(
                        set(int(i) for i in list(selected_items.keys())))
                    selected_choices = []
                    for i in correct_ids:
                        selected_choices.append(
                            selected_items[str(i)]['choices'])
                    selected = chain(*selected_choices)

                resp_text = '[selected_choices] ' + ' '.join(
                    str(i) for i in selected)

                correct_choices = set([
                    _[0] for _ in
                    message.lesson_to_answer.lesson.get_correct_choices()
                ])
                selected_choices = set([_ for _ in chain(*selected_choices)])

                if not (correct_choices - selected_choices
                        or correct_choices ^ selected_choices):
                    mc_selfeval = StudentResponse.CORRECT
                elif selected_choices & correct_choices:
                    mc_selfeval = StudentResponse.CLOSE
                else:
                    mc_selfeval = StudentResponse.DIFFERENT

            resp = StudentResponse(text=resp_text)
            # tes, preview flags
            resp.is_test = chat.is_test
            resp.selfeval = mc_selfeval or None
            resp.is_preview = chat.enroll_code.isPreview
            resp.is_trial = chat.is_trial

            resp.kind = message.lesson_to_answer.kind
            resp.sub_kind = message.lesson_to_answer.sub_kind
            resp.lesson = message.lesson_to_answer.lesson
            resp.unitLesson = message.lesson_to_answer
            resp.course = message.chat.enroll_code.courseUnit.course
            resp.author = self.request.user
            resp.activity = activity
            resp.save()

            if not message.timestamp:
                serializer.save(content_id=resp.id,
                                timestamp=timezone.now(),
                                chat=chat,
                                response_to_check=resp)
            else:
                serializer.save()
            return
        if (is_in_node('GET_NEW_FAQ_TITLE') or is_in_node('GET_NEW_FAQ_DESCRIPTION')) \
                and message_is_response and message.sub_kind == 'add_faq':
            text = self.request.data.get('text')
            faq_request = message.content
            if is_in_node('GET_NEW_FAQ_TITLE'):
                faq_request.title = text
            else:
                faq_request.text = text
            faq_request.save()
            faq_request.notify_instructors()
            message.text = text
            message.save()
        if is_in_node('GET_FOR_FAQ_ANSWER'):
            message.text = self.request.data.get('option', 'help')
            message.save()
        if is_in_node('GET_UNDERSTANDING'):
            message.text = self.request.data.get('option', 'no')
            message.save()
        if message.input_type == 'options' and message.kind != 'button':
            if (message.contenttype == 'uniterror'
                    and 'selected' in self.request.data):
                # user selected error model
                message.chat = chat
                try:
                    selected = self.request.data.get('selected')[str(
                        message.id)]['errorModel']
                except KeyError:
                    selected = []
                uniterror = message.content
                uniterror.save_response(user=self.request.user,
                                        response_list=selected)

                message.text = message.get_html()
                message.save()
                if not message.chat.is_live:
                    get_additional_messages(uniterror.response, chat, selected)
                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request)
                chat.last_modify_timestamp = timezone.now()
                chat.save()

                serializer = self.get_serializer(message,
                                                 data=self.request.data)
                serializer.is_valid()
                serializer.save(chat=chat)

            elif (message.kind == 'add_faq' and message.sub_kind == 'add_faq') or \
                 (message.kind == 'get_faq_answer' and message.sub_kind == 'get_faq_answer') or \
                 (message.kind == 'ask_faq_understanding'):
                pass
            elif (message.contenttype == 'unitlesson'
                  and message.kind == 'faqs'
                  and 'selected' in self.request.data):
                message.chat = chat
                try:
                    selected = self.request.data.get('selected')[str(
                        message.id)]['faqModel']
                except KeyError:
                    selected = []

                if selected:
                    c_faq_data().update_one(
                        {
                            "chat_id": chat.id,
                            "ul_id": message.content.id
                        }, {
                            "$set": {
                                "faqs": {
                                    str(faq_id): {
                                        'status': {
                                            "done": False
                                        }
                                    }
                                    for faq_id in selected
                                }
                            }
                        })
                # Save presented in message FAQs to avoid futher bugs in wrong dadta selection
                message.text = message.get_html()
                message.save()

                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request)
                chat.last_modify_timestamp = timezone.now()
                chat.save()

                serializer = self.get_serializer(message,
                                                 data=self.request.data)
                serializer.is_valid()
                serializer.save(chat=chat)
            elif message.contenttype == 'NoneType' and message.kind == 'abort':
                # user selected abort model
                message.chat = chat
                try:
                    selected = self.request.data.get('selected')[str(
                        message.id)]['errorModel']
                except KeyError:
                    selected = []
                if not message.chat.is_live and selected:
                    get_help_messages(chat)
                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request)
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(chat=chat)
            elif message.content_id and not message.student_error:
                # confidence and selfeval
                message.chat = chat
                opt_data = self.request.data.get('option')
                resp = message.content
                if chat.state and chat.state.fsmNode.node_name_is_one_of(
                        'GET_CONFIDENCE', 'ADDITIONAL_GET_CONFIDENCE'):
                    resp.confidence = opt_data
                    text = resp.get_confidence_display()
                else:
                    resp.selfeval = opt_data
                    text = resp.get_selfeval_display()
                    # FIX if response was correct - user will not go to `else` section and response status should be set
                    if not resp.is_locked:
                        resp.status = EVAL_TO_STATUS_MAP.get(opt_data)

                message.text = text
                resp.save()
                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(content_id=resp.id, chat=chat, text=text)
            else:
                #
                message.chat = chat
                selfeval = self.request.data.get('option')
                resp = message.student_error
                resp.status = selfeval
                resp.save()

                # CRITICAL note - do not override response status
                # pass status to main response ONLY in case of absence the status at all
                # is_locked status is setted in TRANSITION node in chat FSM
                if not resp.response.is_locked:
                    resp.response.status = selfeval
                    resp.response.save()

                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                message.text = selfeval
                message.save()
                serializer.save(text=selfeval, chat=chat)
        if message.kind == 'button' and not (message.content_id
                                             and message.content
                                             and message.content.sub_kind):
            chat.last_modify_timestamp = timezone.now()
            chat.next_point = self.next_handler.next_point(
                current=message.content,
                chat=chat,
                message=message,
                request=self.request,
            )
            chat.save()
Example #10
0
 class Z(object):
     x = di.depends(object, 'x')
Example #11
0
 class User:
     value = di.depends(self.Consumer, 'consumer')
Example #12
0
class SmsHandler:
    twilio_gateway = injections.depends(TwilioGateway)

    async def send_sms(self, request):
        await self.twilio_gateway.send_sms("test message")
        return web.json_response({"status": "ok"})
Example #13
0
class ChatInitialView(LoginRequiredMixin, View):
    """
    Entry point for Chat UI.
    """
    next_handler = injections.depends(ProgressHandler)
    template_name = 'chat/main_view.html'
    tester_mode = False

    @staticmethod
    def get_back_url(*args, **kwargs):
        """
        Return link to back page - by default - lms course page.
        """
        return "Course", reverse('lms:course_view', kwargs=dict(course_id=kwargs['courseUnit'].course.id))

    @staticmethod
    def get_enroll_code_object(enroll_key):
        """
        Return EnrollUnitCode object.

        :param enroll_key: enroll code
        :return: EnrollUnitCode instance
        """
        return get_object_or_404(EnrollUnitCode, enrollCode=enroll_key, isPreview=False)

    @staticmethod
    def get_will_learn_need_know(unit, courseUnit):
        """
        Steps to define Concepts for Will learn and Need to know:

            `/ct/teach/courses/:id/units/:id/`
            `/ct/teach/courses/:id/units/:id/lessons/`
            `/ct/teach/courses/:id/units/:id/lessons/:id/`
            `/ct/teach/courses/:id/units/:id/lessons/:id/concepts/`

        `Will learn`

            * We want all Concepts that Defines or Tests Understanding of Lesson
            * Choose Defines or Test for Concept

        `Need to know`

            * We want all Concepts that Assumes a Lesson
            * Choose Assumes for Concept
        """
        will_learn = set()
        need_to_know = set()
        for unit_lesson in unit.get_exercises():
            # QuerySet for "You will learn" and "Need to know" section
            containers_with_querysets = (
                (will_learn, ConceptLink.objects.filter(
                    Q(lesson=unit_lesson.lesson),
                    (Q(relationship=ConceptLink.DEFINES) | Q(relationship=ConceptLink.TESTS)))
                 if unit_lesson.unit.is_show_will_learn else ()),
                (need_to_know, ConceptLink.objects.filter(
                    lesson=unit_lesson.lesson, relationship=ConceptLink.ASSUMES))
            )
            for contaner, qs in containers_with_querysets:
                for concept_link in qs:
                    title = concept_link.concept.title
                    if concept_link.lesson.url:
                        url = concept_link.lesson.url
                    else:
                        ul = UnitLesson.objects.filter(
                            lesson__concept=concept_link.concept
                        ).values('id').first()
                        if ul:
                            url = reverse(
                                'ct:study_concept', args=(courseUnit.course.id, unit.id, ul['id'])
                            )
                    if url:
                        contaner.add((title, url))
        return will_learn, need_to_know

    def get_or_init_chat(self, enroll_code, chat_id):
        """Get chat by id.

        Logic of this method is:
         * try to cast recieved ID to int
         * if gets an error while casting:
           * set i_chat_id = 0 if ValueError
           * set i_chat_id = None if TypeError
         * if i_chat_id:
           * try to get chat by id
         * if i_chat_id is None:
           * restore last session
         * if i_chat_id == 0:
           * create new chat
        :return i_chat_id and chat
        """
        chat = None
        courseUnit = enroll_code.courseUnit
        try:
            # try to convert chat_id to int
            i_chat_id = int(chat_id)
        except ValueError:
            # if error - set i_chat_id to zero - it means create new chat
            i_chat_id = 0
        except TypeError:
            i_chat_id = None

        if i_chat_id:  # chat_id is passed - restore chat by id
            chat = self.get_chat(self.request, enroll_code, user=self.request.user, id=i_chat_id)
        elif i_chat_id is None:  # chat_id not passed - restore last session
            chat = self.get_chat(self.request, enroll_code, user=self.request.user)
        elif i_chat_id == 0 and enroll_code:  # create new session
            chat = self.create_new_chat(self.request, enroll_code, courseUnit)

        if chat and not chat.state:
            chat.next_point = None
            chat.save()

        return chat, i_chat_id

    @staticmethod
    def check_course_not_published_and_user_is_not_instructor(request, courseUnit):
        """
        This method checks that course is not published and user is not instructor.

        :param request: request
        :param courseUnit: course unit
        :return: True | False
        """
        return (
            not courseUnit.is_published() and
            not User.objects.filter(
                id=request.user.id,
                role__role=Role.INSTRUCTOR,
                role__course=courseUnit.course
            ).exists()
        )

    @staticmethod
    def user_enrolled(request, courseUnit):
        return Role.objects.filter(
            user=request.user.id, course=courseUnit.course, role=Role.ENROLLED
        )

    def create_new_chat(self, request, enroll_code, courseUnit, **kwargs):
        # TODO user_trial_mode = self.define_user_trial_mode(request, courseUnit)
        defaults = dict(
            user=request.user,
            enroll_code=enroll_code,
            instructor=courseUnit.course.addedBy,
            is_preview=False,
            is_trial=False
        )
        defaults.update(kwargs)
        chat = Chat(**defaults)
        chat.save()
        return chat

    def define_user_trial_mode(self, request, course_unit):
        """
        Define trial mode for enrolled user depending on course's trial mode settings
        If mode still is undefined get percent of user's trial mode
         and if count of them is less than 50% set trial mode randomly,
        Arguments:
            request (obj): Django Request
            course_unit (obj): Model object
        Return (bool): Existing or newly added trial mode
        """
        user = request.user
        user_enrolled = self.user_enrolled(request, course_unit).first()
        trial_mode = False
        if user_enrolled:  # if user's role exists
            # course is trial and role.trial_mode has been set
            if course_unit.course.trial and user_enrolled.trial_mode is None:
                # get users enrolled to this course
                enrolled_users = Role.objects.filter(
                    course_id=course_unit.course.id,
                    role=Role.ENROLLED
                )
                # count the percent of users in trial mode
                trial_mode_prsnt = float(enrolled_users.filter(trial_mode=True).count()) / enrolled_users.count() * 100
                roles_to_update = Role.objects.filter(
                      user=user.id, role__in=[Role.ENROLLED, Role.SELFSTUDY], course_id=course_unit.course.id)
                # if the percent is not exceeded get random value for trial mode
                if trial_mode_prsnt < 50:  # hardcoded but can be implemented for adjusting from admin
                    trial_mode = random.choice([True, False])
                roles_to_update.update(trial_mode=trial_mode)
            else:
                trial_mode = bool(user_enrolled.trial_mode)  # course is not trial or role has already been set
        return trial_mode

    @staticmethod
    def check_unitlessons_with_order_null_exists(unit):
        return unit.unitlesson_set.filter(order__isnull=False).exists()

    @staticmethod
    def get_chat(request, enroll_code, **kwargs):
        kw = dict(
            enroll_code=enroll_code, user=request.user,
        )
        kw.update(kwargs)
        return Chat.objects.filter(**kw).first()

    def get_chat_sessions(self, request, enroll_code, courseUnit):
        return Chat.objects.filter(
            enroll_code=enroll_code,
            user=request.user,
            instructor=courseUnit.course.addedBy,
            is_live=False,
            is_test=self.tester_mode,
            is_preview=False
        ).annotate(
            not_finished=Case(
                When(state_id__isnull=True, then=0),
                When(state_id__isnull=False, then=1),
                default=0,
                output_field=IntegerField())
        ).order_by('-not_finished', '-last_modify_timestamp')

    def get(self, request, enroll_key, chat_id=None):
        enroll_code = self.get_enroll_code_object(enroll_key)
        courseUnit = enroll_code.courseUnit
        unit = courseUnit.unit
        if not self.check_unitlessons_with_order_null_exists(unit):
            return render(
                request,
                'lti/error.html',
                {'message': 'There are no Lessons to display for that Courselet.'}
            )
        if self.check_course_not_published_and_user_is_not_instructor(request, courseUnit):
            return render(
                request,
                'lti/error.html',
                {'message': 'This Courselet is not published yet or you have no permisions to open it.'}
            )
        if not self.user_enrolled(request, courseUnit):
            enrolling = Role.objects.get_or_create(user=request.user,
                                                   course=courseUnit.course,
                                                   role=Role.SELFSTUDY)[0]
            enrolling.role = Role.ENROLLED
            enrolling.save()

        # new chat will be created only if chat_id is 0
        chat, i_chat_id = self.get_or_init_chat(enroll_code, chat_id)
        lessons = unit.get_exercises()

        if chat and chat.is_live:
            lessons = Message.objects.filter(
                chat=chat,
                contenttype='unitlesson',
                kind='orct',
                type='message',
                owner=request.user,
            )

        will_learn, need_to_know = self.get_will_learn_need_know(unit, courseUnit)

        try:
            instructor_icon = courseUnit.course.addedBy.instructor.icon_url
        except AttributeError:
            instructor_icon = ''

        chat_sessions = self.get_chat_sessions(request, enroll_code, courseUnit)
        back_url_name, back_url = self.get_back_url(**locals())
        last_history = chat_sessions.filter(state__isnull=True, progress=100).order_by('id').last()
        updated_thread_id = None


        if last_history:
            updated_thread_id = get_updated_thread_id(last_history)

        return render(
            request,
            self.template_name,
            {
                'chat_sessions_exists': len(chat_sessions),  # mark for frontend
                'chat_sessions': chat_sessions,  # .exclude(id=chat.id), # TODO: UNCOMMENT this line to exclude current chat from sessions
                'most_recent_complete_session': last_history,
                'updated_thread_id': updated_thread_id or -1,
                'chat': chat,
                'chat_id': i_chat_id,
                'course': courseUnit.course,
                'instructor_icon': instructor_icon,
                'unit': unit,
                'img_url': unit.img_url,
                'small_img_url': unit.small_img_url,
                'will_learn': will_learn,
                'need_to_know': need_to_know,
                'lessons': lessons,
                'lesson_cnt': len(lessons),
                'duration': len(lessons) * 3,
                'fsmstate': chat.state if chat else None,
                'enroll_code': enroll_key,
                # 'next_point': next_point,
                'back_url': back_url,
                'back_url_name': back_url_name
            }
        )
Example #14
0
 class X(object):
     a = di.depends(object, 'a')
Example #15
0
 class Girl:
     father = di.depends(User, 'user')
Example #16
0
        class Consumer:
            value = di.depends(str, 'name')

            def hello(self):
                return "Hello {}!".format(self.value)
Example #17
0
 class Consumer:
     a = di.depends(int)
     b = di.depends(int)
Example #18
0
class MessageSerializer(serializers.ModelSerializer):
    """
    Message serializer.
    """
    next_handler = injections.depends(ProgressHandler)

    input = serializers.SerializerMethodField()
    # errors = serializers.CharField(source='get_errors', read_only=True)
    addMessages = serializers.SerializerMethodField()
    nextMessagesUrl = serializers.CharField(source='get_next_url',
                                            read_only=True)

    class Meta:
        model = Message
        fields = (
            'id',
            'input',
            'addMessages',
            'nextMessagesUrl',
            # 'errors',
        )

    def set_group(self, obj):
        try:
            getattr(self, 'qs')
        except AttributeError:
            self.qs = [obj]
            if obj.timestamp:
                current = obj
                for message in obj.chat.message_set.filter(
                        timestamp__gt=obj.timestamp):
                    if self.next_handler.group_filter(current, message):
                        current = message
                        self.qs.append(message)

    def get_input(self, obj):
        """
        Getting description for next message.
        """
        self.set_group(obj)
        incl_msg = []
        sub_kind = None
        for i in self.qs:
            if i.contenttype == 'uniterror' or i.kind == 'abort':
                incl_msg.append(i.id)
            if i.contenttype == 'unitlesson' and i.content:
                if i.content.lesson.sub_kind == 'choices':
                    sub_kind = 'choices'
                    incl_msg.append(i.id)
                if i.content.sub_kind == 'numbers':
                    sub_kind = 'numbers'
                if i.content.lesson.sub_kind == 'equation':
                    sub_kind = 'equation'
                elif i.content.lesson.sub_kind == 'canvas':
                    sub_kind = 'canvas'
            # Add UnitLesson id for JS to check during selection validation
            if i.contenttype == 'unitlesson' and i.kind == 'faqs':
                incl_msg.append(i.id)

        input_data = {
            'type':
            obj.get_next_input_type(),
            'url':
            obj.get_next_url(),
            'options':
            obj.get_options(),
            'doWait':
            obj.chat.state.fsmNode.name.startswith('WAIT_')
            if obj.chat.state else False,
            'includeSelectedValuesFromMessages':
            incl_msg,
        }
        if i.contenttype == 'unitlesson':
            if sub_kind == 'numbers':
                input_data[
                    'html'] = '<input type="number" name="{}" value="{}">'.format(
                        "text",
                        0,
                    )
            elif sub_kind == 'canvas':
                input_data['html'] = '<input type="hidden" />'

            input_data['subType'] = sub_kind

        if input_data['doWait']:
            input_data['html'] = '&nbsp;'
        elif not obj.chat.next_point:
            chat_id = obj.chat.enroll_code.courseUnit.course.id
            course_url = reverse('lms:course_view',
                                 kwargs={'course_id': chat_id})
            html = f"""
                <button class="btn chat-option"
                        data-option-value="close-courselet"
                        onclick="window.location.href='{course_url}'">
                Close courselet
                </button>
            """ if settings.SHOW_CLOSE_BTN and obj.chat.resources_is_done(
            ) else '&nbsp;'
            input_data['html'] = html
        return InputSerializer().to_representation(input_data)

    def get_addMessages(self, obj):
        self.set_group(obj)
        return InternalMessageSerializer(many=True).to_representation(self.qs)
Example #19
0
class ChatInitialView(View):
    """
    Entry point for Chat UI.
    """
    next_handler = injections.depends(ProgressHandler)

    @method_decorator(login_required)
    def get(self, request, enroll_key):
        enroll_code = get_object_or_404(EnrollUnitCode, enrollCode=enroll_key)
        courseUnit = enroll_code.courseUnit
        unit = courseUnit.unit
        if not unit.unitlesson_set.filter(order__isnull=False).exists():
            return render(request, 'lti/error.html', {
                'message':
                'There are no Lessons to display for that Courselet.'
            })
        if (not courseUnit.is_published() and not User.objects.filter(
                id=request.user.id,
                role__role=Role.INSTRUCTOR,
                role__course=courseUnit.course).exists()):
            return render(request, 'lti/error.html',
                          {'message': 'This Courselet is not published yet.'})
        if not Role.objects.filter(user=request.user.id,
                                   course=courseUnit.course,
                                   role=Role.ENROLLED):
            enrolling = Role.objects.get_or_create(user=request.user,
                                                   course=courseUnit.course,
                                                   role=Role.SELFSTUDY)[0]
            enrolling.role = Role.ENROLLED
            enrolling.save()

        chat = Chat.objects.filter(enroll_code=enroll_code,
                                   user=request.user).first()
        if not chat and enroll_key:
            chat = Chat(user=request.user,
                        enroll_code=enroll_code,
                        instructor=courseUnit.course.addedBy)
            chat.save(request)
        if chat.message_set.count() == 0:
            next_point = self.next_handler.start_point(unit=unit,
                                                       chat=chat,
                                                       request=request)
        else:
            next_point = chat.next_point

        lessons = unit.get_exercises()

        will_learn = set()
        need_to_know = set()
        for unit_lesson in unit.get_exercises():
            # QuerySet for "You will learn" and "Need to know" section
            containers_with_querysets = (
                (will_learn,
                 ConceptLink.objects.filter(
                     Q(lesson=unit_lesson.lesson),
                     (Q(relationship=ConceptLink.DEFINES)
                      | Q(relationship=ConceptLink.TESTS)))),
                (need_to_know,
                 ConceptLink.objects.filter(lesson=unit_lesson.lesson,
                                            relationship=ConceptLink.ASSUMES)))
            for contaner, qs in containers_with_querysets:
                for concept_link in qs:
                    title = concept_link.concept.title
                    if concept_link.lesson.url:
                        url = concept_link.lesson.url
                    else:
                        ul = UnitLesson.objects.filter(
                            lesson__concept=concept_link.concept).values(
                                'id').first()
                        if ul:
                            url = reverse('ct:study_concept',
                                          args=(courseUnit.course.id, unit.id,
                                                ul['id']))
                    if url:
                        contaner.add((title, url))

        return render(
            request, 'chat/main_view.html', {
                'chat_id': chat.id,
                'course': courseUnit.course,
                'unit': unit,
                'img_url': unit.img_url,
                'small_img_url': unit.small_img_url,
                'will_learn': will_learn,
                'need_to_know': need_to_know,
                'chat_id': chat.id,
                'lessons': lessons,
                'lesson_cnt': len(lessons),
                'duration': len(lessons) * 3,
                'next_point': next_point,
                'fsmstate': chat.state,
            })