def add_original_emojis(session, sticker, raw_emojis): """Add the original emojis to the sticker's tags and to the original_emoji relationship.""" for raw_emoji in raw_emojis: emoji = Tag.get_or_create(session, raw_emoji, True, True) if emoji not in sticker.tags: sticker.tags.append(emoji) if emoji not in sticker.original_emojis: sticker.original_emojis.append(emoji)
def sticker_factory(session, file_id, tag_names=None, default_language=True): """Create a sticker and eventually add tags.""" sticker = Sticker(file_id) if tag_names: for tag_name in tag_names: tag = Tag.get_or_create(session, tag_name, default_language, False) sticker.tags.append(tag) session.add(sticker) session.commit() return sticker
def sticker_factory(session, file_id, tag_names=None, international=False): """Create a sticker and eventually add tags.""" sticker = Sticker(file_id, file_id + "unique") if tag_names: for tag_name in tag_names: tag = Tag.get_or_create(session, tag_name, international, False) sticker.tags.append(tag) session.add(sticker) session.commit() return sticker
def add_emojis(self, session, emojis): """Add tags for every emoji in the incoming string.""" from stickerfinder.models import Tag self.original_emojis = emojis for emoji in emojis: tag = Tag.get_or_create(session, emoji, emoji=True, is_default_language=True) if tag not in self.tags: self.tags.append(tag)
def test_original_emoji_stays_on_replace(session, user, sticker_set): """Original emojis will remain if tags are added in replace mode.""" sticker = sticker_set.stickers[0] # Add an original emoji tag to the sticker tag = Tag('😲', False, True) sticker.tags.append(tag) sticker.original_emojis.append(tag) session.commit() # Now tag the sticker in replace mode tag_sticker(session, 'new-tag', sticker, user, replace=True) assert_sticker_contains_tags(sticker, ['new-tag', '😲']) assert len(sticker.tags) == 2 assert sticker.original_emojis[0] in sticker.tags
def test_nsfw_search(session, strict_inline_search, user): """Test nsfw search for stickers.""" context = Context('nsfw p**n roflcopter', '', user) sticker_set = strict_inline_search[0] sticker_set.nsfw = True # Add specific sticker to tag sticker = sticker_set.stickers[0] tag = Tag.get_or_create(session, 'p**n', True, False) sticker.tags.append(tag) session.commit() matching_stickers, fuzzy_matching_stickers, duration = get_matching_stickers(session, context) assert len(matching_stickers) == 1 assert matching_stickers[0][0] == sticker.file_id
def undo_user_changes_revert(session, user): """Undo the revert of all changes of a user.""" affected_stickers = session.query(Sticker) \ .options( joinedload(Sticker.changes), ) \ .join(Sticker.changes) \ .join(Change.user) \ .filter(User.id == user.id) \ .filter(Change.reverted.is_(True)) \ .all() for sticker in affected_stickers: updated_languages = set() # Changes are sorted by created_at desc # We want to revert all changes until the last valid change for change in sticker.changes: # No reverted change, this is a valid tag change. if change.reverted is False and change.user != user: continue # Only undo the newest reverted change per language if change.is_default_language not in updated_languages: new_tags = change.new_tags.split(',') tags = [ tag for tag in sticker.tags if (tag.is_default_language != change.is_default_language or tag.emoji) ] for new_tag in new_tags: tag = Tag.get_or_create(session, new_tag, False, change.is_default_language) if tag not in tags: tags.append(tag) sticker.tags = tags updated_languages.add(change.is_default_language) change.reverted = False user.reverted = False session.add(user) session.commit()
def test_convert_tag_to_emoji(session, user, sticker_set): """Tags will be converted to emojis, if they appear in the original emojis.""" sticker = sticker_set.stickers[0] # Add an original emoji tag to the sticker tag = Tag('😲', False, False) sticker.tags.append(tag) session.commit() assert not tag.emoji assert not tag.international # Now tag the sticker in replace mode add_original_emojis(session, sticker, '😲') session.commit() assert tag.emoji assert not tag.international assert len(sticker.tags) == 1 assert sticker.original_emojis[0] in sticker.tags
def tag_sticker(session, text, sticker, user, tg_chat=None, chat=None, message_id=None, replace=False, single_sticker=False): """Tag a single sticker.""" text = text.lower() # Remove the /tag command if text.startswith('/tag'): text = text.split(' ')[1:] # Extract all texts from message and clean/filter them raw_tags = get_tags_from_text(text) # No tags, early return if len(raw_tags) == 0: return # Only use the first few tags. This should prevent abuse from tag spammers. raw_tags = raw_tags[:10] # Inform us if the user managed to hit a special count of changes if tg_chat and len(user.changes) in reward_messages: reward = reward_messages[len(user.changes)] call_tg_func(tg_chat, 'send_message', [reward]) sentry.captureMessage( f'User hit {len(user.changes)} changes!', level='info', extra={ 'user': user, 'changes': len(user.changes), }, ) # List of tags that are newly added to this sticker new_tags = [] # List of all new tags (raw_tags, but with resolved entities) # We need this, if we want to replace all tags incoming_tags = [] # Initialize the new tags array with the tags don't have the current language setting. for raw_tag in raw_tags: incoming_tag = Tag.get_or_create(session, raw_tag, user.is_default_language, False) incoming_tags.append(incoming_tag) # Add the tag to the list of new tags, if it doesn't exist on this sticker yet if incoming_tag not in sticker.tags: new_tags.append(incoming_tag) # We got no new tags if len(new_tags) == 0: session.commit() return # List of removed tags. This is only used, if we actually replace the sticker's tags removed_tags = [] # Remove replace old tags if replace: # Merge the original emojis, since they should always be present on a sticker incoming_tags = incoming_tags + sticker.original_emojis # Find out, which stickers have been removed removed_tags = [ tag for tag in sticker.tags if tag not in incoming_tags ] sticker.tags = incoming_tags else: for new_tag in new_tags: sticker.tags.append(new_tag) # Create a change for logging change = Change(user, sticker, user.is_default_language, new_tags, removed_tags, chat=chat, message_id=message_id) session.add(change) session.commit() # Change the inline keyboard to allow fast fixing of the sticker's tags if tg_chat and chat and not single_sticker and chat.last_sticker_message_id: keyboard = get_fix_sticker_tags_keyboard(chat.current_sticker.file_id) call_tg_func(tg_chat.bot, 'edit_message_reply_markup', [tg_chat.id, chat.last_sticker_message_id], {'reply_markup': keyboard})
def tag_sticker(session, text, sticker, user, tg_chat, chat=None, keep_old=False): """Tag a single sticker.""" text = text.lower() # Remove the /tag command if text.startswith('/tag'): text = text.split(' ')[1:] call_tg_func(tg_chat, 'send_message', ["You don't need to add the /tag command ;)"]) incoming_tags = get_tags_from_text(text) is_default_language = user.is_default_language and sticker.sticker_set.is_default_language # Only use the first few tags. This should prevent abuse from tag spammers. incoming_tags = incoming_tags[:15] # Clean the tags from unwanted words incoming_tags = [tag for tag in incoming_tags if tag not in blacklist] if len(user.changes) in reward_messages: reward = reward_messages[len(user.changes)] call_tg_func(tg_chat, 'send_message', [reward]) sentry.captureMessage( f'User hit {len(user.changes)} changes!', level='info', extra={ 'user': user, 'changes': len(user.changes), }, ) if len(incoming_tags) > 0: # Initialize the new tags array with the tags don't have the current language setting. tags = [ tag for tag in sticker.tags if tag.is_default_language is not is_default_language ] for incoming_tag in incoming_tags: tag = session.query(Tag).get(incoming_tag) if tag is None: tag = Tag(incoming_tag, False, is_default_language) if tag not in tags: tags.append(tag) session.add(tag) # Keep old sticker tags if they are emojis and not in the new tags set for tag in sticker.tags: if tag.name in sticker.original_emojis and tag not in tags: tags.append(tag) # Get the old tags for tracking old_tags_as_text = sticker.tags_as_text(is_default_language) if keep_old: for tag in tags: if tag not in sticker.tags: sticker.tags.append(tag) else: # Remove replace old tags sticker.tags = tags # Create a change for logging if old_tags_as_text != sticker.tags_as_text(is_default_language): change = Change(user, sticker, old_tags_as_text, is_default_language) session.add(change) session.commit() if chat and chat.last_sticker_message_id: # Change the inline keyboard to allow fast fixing of the sticker's tags keyboard = get_fix_sticker_tags_keyboard(chat.current_sticker.file_id) call_tg_func(tg_chat.bot, 'edit_message_reply_markup', [tg_chat.id, chat.last_sticker_message_id], {'reply_markup': keyboard}) # Reset last sticker message id chat.last_sticker_message_id = None
def tag_sticker( session, text, sticker, user, tg_chat=None, chat=None, message_id=None, replace=False, single_sticker=False, ): """Tag a single sticker.""" # Extract all texts from message and clean/filter them raw_tags = get_tags_from_text(text) # No tags, early return if len(raw_tags) == 0: return # Only use the first few tags. This should prevent abuse from tag spammers. if len(raw_tags) > 10: raw_tags = raw_tags[:10] call_tg_func( tg_chat, "send_message", [ "Please don't send that many tags. Try to describe everything as brief as possible." ], ) # Inform us if the user managed to hit a special count of changes if tg_chat and len(user.changes) in reward_messages: reward = reward_messages[len(user.changes)] call_tg_func(tg_chat, "send_message", [reward]) sentry.captureMessage( f"User hit {len(user.changes)} changes!", level="info", extra={ "user": user.username, "user_id": user.id, "changes": len(user.changes), }, ) # List of tags that are newly added to this sticker new_tags = [] # List of all new tags (raw_tags, but with resolved entities) # We need this, if we want to replace all tags incoming_tags = [] international = user.international or sticker.sticker_set.international # Initialize the new tags array with the tags don't have the current language setting. for raw_tag in raw_tags: incoming_tag = Tag.get_or_create(session, raw_tag, international, False) incoming_tags.append(incoming_tag) # Add the tag to the list of new tags, if it doesn't exist on this sticker yet if incoming_tag not in sticker.tags: new_tags.append(incoming_tag) # We got no new tags if len(new_tags) == 0 and replace is False: session.commit() return # List of removed tags. This is only used, if we actually replace the sticker's tags removed_tags = [] # Remove replace old tags if replace: # Merge the original emojis, since they should always be present on a sticker incoming_tags = incoming_tags + sticker.original_emojis # Find out, which stickers have been removed removed_tags = [ tag for tag in sticker.tags if tag not in incoming_tags ] sticker.tags = incoming_tags else: for new_tag in new_tags: sticker.tags.append(new_tag) # Create a change for logging change = Change( user, sticker, international, new_tags, removed_tags, chat=chat, message_id=message_id, ) session.add(change) session.commit() # Change the inline keyboard to allow fast fixing of the sticker's tags if tg_chat and chat and not single_sticker and chat.last_sticker_message_id: keyboard = get_fix_sticker_tags_keyboard(chat.current_sticker.file_id) call_tg_func( tg_chat.bot, "edit_message_reply_markup", [tg_chat.id, chat.last_sticker_message_id], {"reply_markup": keyboard}, )