import boards from boards.models import Tag, TagAlias, Attachment from boards.models.attachment import AttachmentSticker from boards.models.user import UserSettings MAX_TRIPCODE_COLLISIONS = 50 __author__ = 'neko259' SESSION_SETTING = 'setting' SETTING_THEME = 'theme' SETTING_FAVORITE_TAGS = 'favorite_tags' SETTING_FAVORITE_THREADS = 'favorite_threads' SETTING_HIDDEN_TAGS = 'hidden_tags' SETTING_USERNAME = 'username' SETTING_LAST_NOTIFICATION_ID = 'last_notification' SETTING_IMAGE_VIEWER = 'image_viewer' SETTING_IMAGES = 'images_aliases' SETTING_ONLY_FAVORITES = 'only_favorites' SETTING_LAST_POSTS = 'last_posts' SETTING_CONFIRMED_USER = 'confirmed_user' SETTING_SUBSCRIBE_BY_DEFAULT = 'subscribe_by_default' DEFAULT_THEME = 'md' class SettingsManager: """ Base settings manager class. get_setting and set_setting methods should be overriden. """ def __init__(self): pass def get_theme(self) -> str: theme = self.get_setting(SETTING_THEME) if not theme: theme = DEFAULT_THEME self.set_setting(SETTING_THEME, theme) return theme def set_theme(self, theme): self.set_setting(SETTING_THEME, theme) def get_setting(self, setting, default=None): pass def set_setting(self, setting, value): pass def get_fav_tags(self) -> list: tag_names = self.get_setting(SETTING_FAVORITE_TAGS) tags = [] if tag_names: tags = list(Tag.objects.filter(aliases__in=TagAlias.objects .filter_localized(parent__aliases__name__in=tag_names)) .order_by('aliases__name')) return tags def add_fav_tag(self, tag): tags = self.get_setting(SETTING_FAVORITE_TAGS) if not tags: tags = [tag.get_name()] else: if not tag.get_name() in tags: tags.append(tag.get_name()) tags.sort() self.set_setting(SETTING_FAVORITE_TAGS, tags) def del_fav_tag(self, tag): tags = self.get_setting(SETTING_FAVORITE_TAGS) if tag.get_name() in tags: tags.remove(tag.get_name()) self.set_setting(SETTING_FAVORITE_TAGS, tags) def get_hidden_tags(self) -> list: tag_names = self.get_setting(SETTING_HIDDEN_TAGS) tags = [] if tag_names: tags = list(Tag.objects.filter(aliases__in=TagAlias.objects .filter_localized(parent__aliases__name__in=tag_names)) .order_by('aliases__name')) return tags def add_hidden_tag(self, tag): tags = self.get_setting(SETTING_HIDDEN_TAGS) if not tags: tags = [tag.get_name()] else: if not tag.get_name() in tags: tags.append(tag.get_name()) tags.sort() self.set_setting(SETTING_HIDDEN_TAGS, tags) def del_hidden_tag(self, tag): tags = self.get_setting(SETTING_HIDDEN_TAGS) if tag.get_name() in tags: tags.remove(tag.get_name()) self.set_setting(SETTING_HIDDEN_TAGS, tags) def add_or_read_fav_thread(self, opening_post): last_post_ids = self.get_setting(SETTING_LAST_POSTS) if not last_post_ids: last_post_ids = [] self.del_fav_thread(opening_post) last_post_id = opening_post.get_thread().get_replies().last().id last_post_ids.append(last_post_id) self.set_setting(SETTING_LAST_POSTS, last_post_ids) def del_fav_thread(self, opening_post): last_posts_ids = self.get_setting(SETTING_LAST_POSTS) for post in self.get_last_posts(): if post.get_thread() == opening_post.get_thread(): last_posts_ids.remove(post.id) self.set_setting(SETTING_LAST_POSTS, last_posts_ids) def thread_is_fav(self, opening_post): for post in self.get_last_posts(): if post.get_thread() == opening_post.get_thread(): return True return False def get_notification_usernames(self): names = set() name_list = self.get_setting(SETTING_USERNAME) if name_list is not None: name_list = name_list.strip() if len(name_list) > 0: names = name_list.lower().split(',') names = set(name.strip() for name in names) return names def get_attachment_by_alias(self, alias): images = self.get_setting(SETTING_IMAGES) if images and alias in images: try: return Attachment.objects.get(id=images.get(alias)) except Attachment.DoesNotExist: self.remove_attachment_alias(alias) def add_attachment_alias(self, alias, attachment): images = self.get_setting(SETTING_IMAGES) if images is None: images = dict() images[alias] = attachment.id self.set_setting(SETTING_IMAGES, images) def remove_attachment_alias(self, alias): images = self.get_setting(SETTING_IMAGES) del images[alias] self.set_setting(SETTING_IMAGES, images) def get_stickers(self): images = self.get_setting(SETTING_IMAGES) stickers = [] if images: for key, value in images.items(): try: attachment = Attachment.objects.get(id=value) stickers.append(AttachmentSticker(name=key, attachment=attachment)) except Attachment.DoesNotExist: self.remove_attachment_alias(key) return stickers def tag_is_fav(self, tag): fav_tag_names = self.get_setting(SETTING_FAVORITE_TAGS) return fav_tag_names is not None and tag.get_name() in fav_tag_names def tag_is_hidden(self, tag): hidden_tag_names = self.get_setting(SETTING_HIDDEN_TAGS) return hidden_tag_names is not None and tag.get_name() in hidden_tag_names def get_last_posts(self): post_ids = self.get_setting(SETTING_LAST_POSTS) or [] return list(boards.models.Post.objects.filter(id__in=post_ids).order_by('thread__id')) class SessionSettingsManager(SettingsManager): """ Session-based settings manager. All settings are saved to the user's session. """ def __init__(self, session): SettingsManager.__init__(self) self.session = session def get_setting(self, setting, default=None): if setting in self.session: return self.session[setting] else: self.set_setting(setting, default) return default def set_setting(self, setting, value): self.session[setting] = value class DatabaseSettingsManager(SessionSettingsManager): def __init__(self, session): super().__init__(session) # First time a user accesses the server, his session is not saved # and does not have the key yet. In order to create the settings object # we need to save it manually if not session.session_key: session.save() self.settings, created = UserSettings.objects.get_or_create(session_key=session.session_key) def add_fav_tag(self, tag): self.settings.fav_tags.add(tag) def del_fav_tag(self, tag): self.settings.fav_tags.remove(tag) def get_fav_tags(self) -> list: return self.settings.fav_tags.filter( aliases__in=TagAlias.objects.filter_localized())\ .order_by('aliases__name') def get_hidden_tags(self) -> list: return self.settings.hidden_tags.all() def add_hidden_tag(self, tag): self.settings.hidden_tags.add(tag) def del_hidden_tag(self, tag): self.settings.hidden_tags.remove(tag) def tag_is_fav(self, tag): return self.settings.fav_tags.filter(id=tag.id).exists() def tag_is_hidden(self, tag): return self.settings.hidden_tags.filter(id=tag.id).exists() def get_user_settings(self): return self.settings def get_settings_manager(request) -> SettingsManager: """ Get settings manager based on the request object. Currently database-based settings manager is implemented over the session-based one (settings that are not connected to the database in any way are stored in session). Pure session-based manager is also supported but not used by default. """ return DatabaseSettingsManager(request.session)