示例#1
0
 def update_content(self, text, on_error=None):
     _, old_metadata, _ = render_markdown(self.text)
     html, metadata, messages = render_markdown(text, on_error=on_error)
     self.text = text
     self.text_html = html
     self.save()
     all_the_pings = list(
         filter(lambda user_name: user_name != self.author.username,
                metadata.get('ping', [])))
     all_the_pings = list(
         set(all_the_pings) - set(old_metadata.get('ping', [])))
     max_ping_count = settings.ZDS_APP['comment']['max_pings']
     first_pings = all_the_pings[:max_ping_count]
     for username in first_pings:
         pinged_user = User.objects.filter(username=username).first()
         if not pinged_user:
             continue
         signals.new_content.send(sender=self.__class__,
                                  instance=self,
                                  user=pinged_user)
     unpinged_usernames = set(old_metadata.get('ping',
                                               [])) - set(all_the_pings)
     unpinged_users = User.objects.filter(
         username__in=list(unpinged_usernames))
     for unpinged_user in unpinged_users:
         signals.unsubscribe.send(self.author,
                                  instance=self,
                                  user=unpinged_user)
示例#2
0
    def update_content(self, text, on_error=None):
        """
        Updates the content of this comment.

        This method will render the new comment to HTML, store the rendered
        version, and store data to later analyze pings and spam.

        This method updates fields, but does not save the instance.

        :param text: The new comment content.
        :param on_error: A callable called if zmd returns an error, provided
                         with a single argument: a list of user-friendly errors.
                         See render_markdown.
        """
        # This attribute will be used by `_save_check_spam`, called after save (but not saved into the database).
        # We only update it if it does not already exist, so if this method is called multiple times, the oldest
        # version (i.e. the one currently in the database) is used for comparison. `_save_check_spam` will delete
        # the attribute, so if we re-save the same instance, this will be re-set.
        if not hasattr(self, "old_text"):
            self.old_text = self.text

        _, old_metadata, _ = render_markdown(self.text)
        html, new_metadata, _ = render_markdown(text, on_error=on_error)

        # These attributes will be used by `_save_compute_pings` to create notifications if needed.
        # For the same reason as `old_text`, we only update `old_metadata` if not already set.
        if not hasattr(self, "old_metadata"):
            self.old_metadata = old_metadata
        self.new_metadata = new_metadata

        self.text = text
        self.text_html = html
示例#3
0
文件: models.py 项目: Vultik/zds-site
    def update_content(self, text, on_error=None):
        _, old_metadata, _ = render_markdown(self.text)
        html, metadata, messages = render_markdown(text, on_error=on_error)
        self.text = text
        self.text_html = html
        self.save()

        def filter_usernames(original_list):
            # removes duplicates and the message's author
            filtered_list = []
            for username in original_list:
                if username != self.author.username and username not in filtered_list:
                    filtered_list.append(username)
            return filtered_list

        max_pings_allowed = settings.ZDS_APP["comment"]["max_pings"]
        pinged_usernames_from_new_text = filter_usernames(
            metadata.get("ping", []))[:max_pings_allowed]
        pinged_usernames_from_old_text = filter_usernames(
            old_metadata.get("ping", []))[:max_pings_allowed]

        pinged_usernames = set(pinged_usernames_from_new_text) - set(
            pinged_usernames_from_old_text)
        pinged_users = User.objects.filter(username__in=pinged_usernames)
        for pinged_user in pinged_users:
            signals.ping.send(sender=self.__class__,
                              instance=self,
                              user=pinged_user)

        unpinged_usernames = set(pinged_usernames_from_old_text) - set(
            pinged_usernames_from_new_text)
        unpinged_users = User.objects.filter(username__in=unpinged_usernames)
        for unpinged_user in unpinged_users:
            signals.unping.send(self.author, instance=self, user=unpinged_user)
示例#4
0
    def test_edit_detail(self):
        # Login as staff
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))

        # Check that the original content is displayed
        response = self.client.get(reverse('edit-detail', args=[self.edit.pk]))
        original_text_html, *_ = render_markdown(self.edit.original_text, disable_ping=True)
        self.assertContains(response, original_text_html)
示例#5
0
    def test_edit_detail(self):
        # Login as staff
        self.assertTrue(self.client.login(username=self.staff.username, password='******'))

        # Check that the original content is displayed
        response = self.client.get(reverse('edit-detail', args=[self.edit.pk]))
        original_text_html, *_ = render_markdown(self.edit.original_text, disable_ping=True)
        self.assertContains(response, original_text_html)
示例#6
0
    def test_edit_detail(self):
        # Login as staff
        self.client.force_login(self.staff)

        # Check that the original content is displayed
        response = self.client.get(reverse("edit-detail", args=[self.edit.pk]))
        original_text_html, *_ = render_markdown(self.edit.original_text,
                                                 disable_ping=True)
        self.assertContains(response, original_text_html)
示例#7
0
    def update_content(self, text):
        from zds.notification.models import ping_url

        self.text = text
        md_instance = get_markdown_instance(ping_url=ping_url)
        self.text_html = render_markdown(md_instance, self.text)
        self.save()
        for username in list(md_instance.metadata.get('ping', []))[:settings.ZDS_APP['comment']['max_pings']]:
            signals.new_content.send(sender=self.__class__, instance=self, user=User.objects.get(username=username))
示例#8
0
def publish_use_manifest(db_object, base_dir,
                         versionable_content: VersionedContent):
    base_content = export_content(versionable_content, with_text=True)

    md, metadata, __ = render_markdown(
        base_content,
        disable_jsfiddle=not db_object.js_support,
        full_json=True,
        stats=True)
    publish_container_new(db_object, base_dir, versionable_content, md)
    return metadata.get("stats", {}).get("signs", 0)
示例#9
0
    def test_edit_detail(self):
        # Login as staff
        self.assertTrue(
            self.client.login(username=self.staff.username,
                              password='******'))

        # Check that the original content is displayed
        response = self.client.get(reverse('edit-detail', args=[self.edit.pk]))
        md_instance = get_markdown_instance(ping_url=None)
        original_text_html = render_markdown(md_instance,
                                             self.edit.original_text)
        self.assertContains(response, original_text_html)
示例#10
0
    def publish(self, md_file_path, base_name, **kwargs):
        md_flat_content = _read_flat_markdown(md_file_path)
        published_content_entity = self.get_published_content_entity(md_file_path)
        html_flat_content, *_ = render_markdown(md_flat_content, disable_ping=True,
                                                disable_js=True)
        html_file_path = path.splitext(md_file_path)[0] + '.html'
        if str(MD_PARSING_ERROR) in html_flat_content:
            logging.getLogger(self.__class__.__name__).error('HTML could not be rendered')
            return

        with open(html_file_path, mode='w', encoding='utf-8') as final_file:
            final_file.write(html_flat_content)
        shutil.move(html_file_path, published_content_entity.get_extra_contents_directory())
示例#11
0
    def publish(self, md_file_path, base_name, **kwargs):
        md_flat_content = _read_flat_markdown(md_file_path)
        published_content_entity = self.get_published_content_entity(
            md_file_path)
        html_flat_content, *_ = render_markdown(md_flat_content,
                                                disable_ping=True,
                                                disable_js=True)
        html_file_path = path.splitext(md_file_path)[0] + '.html'
        if str(MD_PARSING_ERROR) in html_flat_content:
            logging.getLogger(
                self.__class__.__name__).error('HTML could not be rendered')
            return

        with open(html_file_path, mode='w', encoding='utf-8') as final_file:
            final_file.write(html_flat_content)
        shutil.move(html_file_path,
                    published_content_entity.get_extra_contents_directory())
示例#12
0
    def publish(self, md_file_path, base_name, **kwargs):
        md_flat_content = _read_flat_markdown(md_file_path)
        published_content_entity = self.get_published_content_entity(md_file_path)
        gallery_pk = published_content_entity.content.gallery.pk
        depth_to_size_map = {
            1: "small",  # in fact this is an "empty" tutorial (i.e it is empty or has intro and/or conclusion)
            2: "small",
            3: "middle",
            4: "big",
        }
        public_versionned_source = published_content_entity.content.load_version(
            sha=published_content_entity.sha_public
        )
        base_directory = Path(base_name).parent
        image_dir = base_directory / "images"
        with contextlib.suppress(FileExistsError):
            image_dir.mkdir(parents=True)
        if (settings.MEDIA_ROOT / "galleries" / str(gallery_pk)).exists():
            for image in (settings.MEDIA_ROOT / "galleries" / str(gallery_pk)).iterdir():
                with contextlib.suppress(OSError):
                    shutil.copy2(str(image.absolute()), str(image_dir))
        content_type = depth_to_size_map[public_versionned_source.get_tree_level()]
        if self.latex_classes:
            content_type += ", " + self.latex_classes
        title = published_content_entity.title()
        authors = [a.username for a in published_content_entity.authors.all()]

        licence = published_content_entity.content.licence.code
        licence_short = licence.replace("CC", "").strip().lower()
        licence_logo = licences.get(licence_short, False)
        if licence_logo:
            licence_url = "https://creativecommons.org/licenses/{}/4.0/legalcode".format(licence_short)
            # we need a specific case for CC-0 as it is "public-domain"
            if licence_logo == licences["0"]:
                licence_url = "https://creativecommons.org/publicdomain/zero/1.0/legalcode.fr"
        else:
            licence = str(_("Tous droits réservés"))
            licence_logo = licences["copyright"]
            licence_url = ""

        replacement_image_url = str(settings.MEDIA_ROOT)
        if not replacement_image_url.endswith("/") and settings.MEDIA_URL.endswith("/"):
            replacement_image_url += "/"
        elif replacement_image_url.endswith("/") and not settings.MEDIA_URL.endswith("/"):
            replacement_image_url = replacement_image_url[:-1]
        content, __, messages = render_markdown(
            md_flat_content,
            output_format="texfile",
            # latex template arguments
            content_type=content_type,
            title=title,
            authors=authors,
            license=licence,
            license_directory=str(LICENSES_BASE_PATH),
            license_logo=licence_logo,
            license_url=licence_url,
            smileys_directory=str(SMILEYS_BASE_PATH / "svg"),
            images_download_dir=str(base_directory / "images"),
            local_url_to_local_path=[settings.MEDIA_URL, replacement_image_url],
        )
        if content == "" and messages:
            raise FailureDuringPublication("Markdown was not parsed due to {}".format(messages))
        zmd_class_dir_path = Path(settings.ZDS_APP["content"]["latex_template_repo"])
        if zmd_class_dir_path.exists() and zmd_class_dir_path.is_dir():
            with contextlib.suppress(FileExistsError):
                zmd_class_link = base_directory / "zmdocument.cls"
                zmd_class_link.symlink_to(zmd_class_dir_path / "zmdocument.cls")
                luatex_dir_link = base_directory / "utf8.lua"
                luatex_dir_link.symlink_to(zmd_class_dir_path / "utf8.lua", target_is_directory=True)
        true_latex_extension = ".".join(self.extension.split(".")[:-1]) + ".tex"
        latex_file_path = base_name + true_latex_extension
        pdf_file_path = base_name + self.extension
        default_logo_original_path = Path(__file__).parent / ".." / ".." / "assets" / "images" / "*****@*****.**"
        with contextlib.suppress(FileExistsError):
            shutil.copy(str(default_logo_original_path), str(base_directory / "default_logo.png"))
        with open(latex_file_path, mode="w", encoding="utf-8") as latex_file:
            latex_file.write(content)
        shutil.copy2(latex_file_path, published_content_entity.get_extra_contents_directory())

        self.full_tex_compiler_call(latex_file_path, draftmode="-draftmode")
        self.full_tex_compiler_call(latex_file_path, draftmode="-draftmode")
        self.make_glossary(base_name.split("/")[-1], latex_file_path)
        self.full_tex_compiler_call(latex_file_path)

        shutil.copy2(pdf_file_path, published_content_entity.get_extra_contents_directory())
示例#13
0
    def publish(self, md_file_path, base_name, **kwargs):
        md_flat_content = _read_flat_markdown(md_file_path)
        published_content_entity = self.get_published_content_entity(
            md_file_path)
        gallery_pk = published_content_entity.content.gallery.pk
        depth_to_size_map = {
            1:
            'small',  # in fact this is an "empty" tutorial (i.e it is empty or has intro and/or conclusion)
            2: 'small',
            3: 'middle',
            4: 'big'
        }
        public_versionned_source = published_content_entity.content\
            .load_version(sha=published_content_entity.sha_public)
        base_directory = Path(base_name).parent
        image_dir = base_directory / 'images'
        with contextlib.suppress(FileExistsError):
            image_dir.mkdir(parents=True)
        if (settings.MEDIA_ROOT / 'galleries' / str(gallery_pk)).exists():
            for image in (settings.MEDIA_ROOT / 'galleries' /
                          str(gallery_pk)).iterdir():
                with contextlib.suppress(OSError):
                    shutil.copy2(str(image.absolute()), str(image_dir))
        content_type = depth_to_size_map[
            public_versionned_source.get_tree_level()]
        if self.latex_classes:
            content_type += ', ' + self.latex_classes
        title = published_content_entity.title()
        authors = [a.username for a in published_content_entity.authors.all()]

        licence = published_content_entity.content.licence.code
        licence_short = licence.replace('CC', '').strip().lower()
        licence_logo = licences.get(licence_short, False)
        if licence_logo:
            licence_url = 'https://creativecommons.org/licenses/{}/4.0/legalcode'.format(
                licence_short)
            # we need a specific case for CC-0 as it is "public-domain"
            if licence_logo == licences['0']:
                licence_url = 'https://creativecommons.org/publicdomain/zero/1.0/legalcode.fr'
        else:
            licence = str(_('Tous droits réservés'))
            licence_logo = licences['copyright']
            licence_url = ''

        replacement_image_url = str(settings.MEDIA_ROOT)
        if not replacement_image_url.endswith(
                '/') and settings.MEDIA_URL.endswith('/'):
            replacement_image_url += '/'
        elif replacement_image_url.endswith(
                '/') and not settings.MEDIA_URL.endswith('/'):
            replacement_image_url = replacement_image_url[:-1]
        content, __, messages = render_markdown(
            md_flat_content,
            output_format='texfile',
            # latex template arguments
            content_type=content_type,
            title=title,
            authors=authors,
            license=licence,
            license_directory=str(LICENSES_BASE_PATH),
            license_logo=licence_logo,
            license_url=licence_url,
            smileys_directory=str(SMILEYS_BASE_PATH / 'svg'),
            images_download_dir=str(base_directory / 'images'),
            local_url_to_local_path=[
                settings.MEDIA_URL, replacement_image_url
            ])
        if content == '' and messages:
            raise FailureDuringPublication(
                'Markdown was not parsed due to {}'.format(messages))
        zmd_class_dir_path = Path(
            settings.ZDS_APP['content']['latex_template_repo'])
        if zmd_class_dir_path.exists() and zmd_class_dir_path.is_dir():
            with contextlib.suppress(FileExistsError):
                zmd_class_link = base_directory / 'zmdocument.cls'
                zmd_class_link.symlink_to(zmd_class_dir_path /
                                          'zmdocument.cls')
                luatex_dir_link = base_directory / 'utf8.lua'
                luatex_dir_link.symlink_to(zmd_class_dir_path / 'utf8.lua',
                                           target_is_directory=True)
        true_latex_extension = '.'.join(
            self.extension.split('.')[:-1]) + '.tex'
        latex_file_path = base_name + true_latex_extension
        pdf_file_path = base_name + self.extension
        default_logo_original_path = Path(
            __file__
        ).parent / '..' / '..' / 'assets' / 'images' / '*****@*****.**'
        with contextlib.suppress(FileExistsError):
            shutil.copy(str(default_logo_original_path),
                        str(base_directory / 'default_logo.png'))
        with open(latex_file_path, mode='w', encoding='utf-8') as latex_file:
            latex_file.write(content)
        shutil.copy2(latex_file_path,
                     published_content_entity.get_extra_contents_directory())

        self.full_tex_compiler_call(latex_file_path, draftmode='-draftmode')
        self.full_tex_compiler_call(latex_file_path, draftmode='-draftmode')
        self.make_glossary(base_name.split('/')[-1], latex_file_path)
        self.full_tex_compiler_call(latex_file_path)

        shutil.copy2(pdf_file_path,
                     published_content_entity.get_extra_contents_directory())
示例#14
0
    def publish(self, md_file_path, base_name, **kwargs):
        md_flat_content = _read_flat_markdown(md_file_path)
        published_content_entity = self.get_published_content_entity(md_file_path)
        gallery_pk = published_content_entity.content.gallery.pk
        depth_to_size_map = {
            1: 'small',  # in fact this is an "empty" tutorial (i.e it is empty or has intro and/or conclusion)
            2: 'small',
            3: 'middle',
            4: 'big'
        }
        public_versionned_source = published_content_entity.content\
            .load_version(sha=published_content_entity.sha_public)
        base_directory = Path(base_name).parent
        image_dir = base_directory / 'images'
        with contextlib.suppress(FileExistsError):
            image_dir.mkdir(parents=True)
        if Path(settings.MEDIA_ROOT, 'galleries', str(gallery_pk)).exists():
            for image in Path(settings.MEDIA_ROOT, 'galleries', str(gallery_pk)).iterdir():
                with contextlib.suppress(OSError):
                    shutil.copy2(str(image.absolute()), str(image_dir))
        content_type = depth_to_size_map[public_versionned_source.get_tree_level()]
        if self.latex_classes:
            content_type += ', ' + self.latex_classes
        title = published_content_entity.title()
        authors = [a.username for a in published_content_entity.authors.all()]
        smileys_directory = SMILEYS_BASE_PATH

        licence = published_content_entity.content.licence.code
        licence_short = licence.replace('CC', '').strip().lower()
        licence_logo = licences.get(licence_short, False)
        if licence_logo:
            licence_url = 'https://creativecommons.org/licenses/{}/4.0/legalcode'.format(licence_short)
        else:
            licence = str(_('Tous droits réservés'))
            licence_logo = licences['copyright']
            licence_url = ''

        replacement_image_url = settings.MEDIA_ROOT
        if not replacement_image_url.endswith('/') and settings.MEDIA_URL.endswith('/'):
            replacement_image_url += '/'
        elif replacement_image_url.endswith('/') and not settings.MEDIA_URL.endswith('/'):
            replacement_image_url = replacement_image_url[:-1]
        content, __, messages = render_markdown(
            md_flat_content,
            output_format='texfile',
            # latex template arguments
            content_type=content_type,
            title=title,
            authors=authors,
            license=licence,
            license_directory=LICENSES_BASE_PATH,
            license_logo=licence_logo,
            license_url=licence_url,
            smileys_directory=smileys_directory,
            images_download_dir=str(base_directory / 'images'),
            local_url_to_local_path=[settings.MEDIA_URL, replacement_image_url]
        )
        if content == '' and messages:
            raise FailureDuringPublication('Markdown was not parsed due to {}'.format(messages))
        zmd_class_dir_path = Path(settings.ZDS_APP['content']['latex_template_repo'])
        if zmd_class_dir_path.exists() and zmd_class_dir_path.is_dir():
            with contextlib.suppress(FileExistsError):
                zmd_class_link = base_directory / 'zmdocument.cls'
                zmd_class_link.symlink_to(zmd_class_dir_path / 'zmdocument.cls')
                luatex_dir_link = base_directory / 'utf8.lua'
                luatex_dir_link.symlink_to(zmd_class_dir_path / 'utf8.lua', target_is_directory=True)
        true_latex_extension = '.'.join(self.extension.split('.')[:-1]) + '.tex'
        latex_file_path = base_name + true_latex_extension
        pdf_file_path = base_name + self.extension
        default_logo_original_path = Path(__file__).parent / '..' / '..' / 'assets' / 'images' / 'logo.png'
        with contextlib.suppress(FileExistsError):
            shutil.copy(str(default_logo_original_path), str(base_directory / 'default_logo.png'))
        with open(latex_file_path, mode='w', encoding='utf-8') as latex_file:
            latex_file.write(content)

        try:
            self.full_tex_compiler_call(latex_file_path)
            self.full_tex_compiler_call(latex_file_path)
            self.make_glossary(base_name.split('/')[-1], latex_file_path)
            self.full_tex_compiler_call(latex_file_path)
        except FailureDuringPublication:
            logging.getLogger(self.__class__.__name__).exception('could not publish %s', base_name + self.extension)
        else:
            shutil.copy2(latex_file_path, published_content_entity.get_extra_contents_directory())
            shutil.copy2(pdf_file_path, published_content_entity.get_extra_contents_directory())
            logging.info('published latex=%s, pdf=%s', published_content_entity.has_type('tex'),
                         published_content_entity.has_type(self.doc_type))