# -*- coding: utf-8 -*- """ Copyright 2015 Grégory Soutadé This file is part of Dénote. Dénote is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Dénote is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Dénote. If not, see . """ from datetime import datetime import re from django.db import models from django.contrib.auth.models import AbstractUser from django.http import HttpResponse from django.db.models.signals import pre_init, post_init, pre_delete, post_delete from django.db.models.signals import pre_save, post_save from django.dispatch import receiver import markdown2 from search import Search class User(AbstractUser): hidden_categories = models.TextField(blank=True) home_notes_visibility = models.IntegerField(default=0, choices=[(0, 'private'), (1, 'registered'), (2, 'public')]) default_template = models.ForeignKey('Template', null=True, on_delete=models.SET_NULL) def getPreference(self, name): if name == 'hidden_categories': return HttpResponse('{"hidden_categories" : [' + self.hidden_categories + ']}', 'application/json') else: raise Http404 def setPreference(self, name, value): if name == 'hidden_categories': categories = [] for c in value.split(','): if c == '-1' or \ (c and Category.objects.filter(id=c).exists()): categories.append(c) self.hidden_categories = ','.join(categories) self.save() return HttpResponse('') else: raise Http404 class Category(models.Model): author = models.ForeignKey(User, null=True, on_delete=models.CASCADE) name = models.CharField(max_length=50, unique=True, blank=False) class Note(models.Model): PRIVATE = 0 REGISTERED = 1 PUBLIC = 2 VISIBILITY = ((PRIVATE, 'Private'), (REGISTERED, 'Registered'), (PUBLIC, 'Public') ) author = models.ForeignKey(User, null=False, on_delete=models.CASCADE) title = models.CharField(max_length=100, blank=False) long_summary = models.CharField(max_length=255) short_summary = models.CharField(max_length=255) text = models.TextField(blank=False) transformed_text = models.TextField() created_date = models.DateTimeField() modified_date = models.DateTimeField() visibility = models.IntegerField(default=PRIVATE, choices=VISIBILITY) category = models.ForeignKey(Category, null=True, on_delete=models.SET_NULL) def _wrap(self, text, limit, max_limit): if len(text) < limit: return text lower_limit = upper_limit = limit while text[lower_limit-1] != ' ' and\ lower_limit > 1: lower_limit -= 1 while text[upper_limit-1] != ' ' and\ upper_limit < len(text): upper_limit += 1 lower = limit - lower_limit upper = upper_limit - limit if lower > max_limit and upper > max_limit: cur_limit = limit + max_limit else: if lower < upper: cur_limit = limit - lower else: cur_limit = limit + upper if cur_limit and text[cur_limit-1] == ' ': cur_limit -= 1 return text[:cur_limit] + '...' def _summarize(self): # Remove markup self.long_summary = re.sub(r'<[^>]+>', '', self.transformed_text) self.long_summary = re.sub(r'&[^;]+;', '', self.long_summary) # Remove return self.long_summary = re.sub(r'\n', ' ', self.long_summary) self.long_summary = re.sub(r'\r', ' ', self.long_summary) # Remove duplicated spaces self.long_summary = re.sub(r' [ ]+', ' ', self.long_summary) self.long_summary = self.long_summary.strip() self.short_summary = self.long_summary[:] self.long_summary = self._wrap(self.long_summary, 100, 5) self.short_summary = self._wrap(self.short_summary, 30, 5) def save(self): self.modified_date = datetime.now() self.transformed_text = markdown2.markdown(self.text, extras=['fenced-code-blocks']) self._summarize() s = Search() super(Note, self).save() class Template(models.Model): name = models.CharField(max_length=30, blank=False, unique=True) author = models.ForeignKey(User, null=False, on_delete=models.CASCADE) title = models.CharField(max_length=100, blank=True) text = models.TextField(blank=True) visibility = models.IntegerField(default=Note.PRIVATE, choices=Note.VISIBILITY) category = models.ForeignKey(Category, null=True, on_delete=models.SET_NULL) @receiver(post_save, sender=Note) def post_save_note_signal(sender, **kwargs): s = Search() if kwargs['created']: s.index_note(kwargs['instance'].id) else: s.edit_note(kwargs['instance'].id) @receiver(pre_delete, sender=Note) def pre_delete_note_signal(sender, **kwargs): s = Search() s.delete_note(kwargs['instance'].id) def manage_category(user, cat_name): category = None if cat_name: category = Category.objects.filter(name=cat_name) # Create a new one if not category: if len(cat_name) > 50: cat_name = cat_name[:50] category = Category(author=user, name=cat_name) category.save() else: category = category[0] return category