Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial tests for mentions listener and minor corrections #9

Merged
merged 12 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Initial documentation ([#4](https://github.com/XaviArnaus/masto-feed/pull/4))
- Make Log rotation as default ([#5](https://github.com/XaviArnaus/masto-feed/pull/5))
- Avoid answering with ERROR_INVALID_ACTION if it's organic mention ([#8](https://github.com/XaviArnaus/masto-feed/pull/8))
- Tests for mentions listener([#9](https://github.com/XaviArnaus/masto-feed/pull/9))

### Fixed

Expand Down
4 changes: 4 additions & 0 deletions config/main.yaml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ app:
name: "MastoFeed"
# User used for publishing (with domain, in a @[email protected] pattern)
user: "@[email protected]"
# [String] User that behaves as Admin (can ADD, UPDATE and REMOVE)
admin: "@[email protected]"
# [Bool] Restrict write operations to admin only?
restrict_writes: True

# Logging config
logger:
Expand Down
75 changes: 46 additions & 29 deletions mastofeed/lib/mentions_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from mastofeed.lib.publisher import Publisher
from definitions import ROOT_DIR
from slugify import slugify
from bs4 import BeautifulSoup as bs4
from bs4 import BeautifulSoup
import re


Expand Down Expand Up @@ -66,7 +66,7 @@ class MentionParser:
INFO_LIST_HEADER = "The registered Feeds are:\n\n"

DEFAULT_STORAGE_FILE = "storage/feeds.yaml"
REGEXP_TEXT_WITHIN_QUOTES = r'"([\w+_\./\\\'\s\-]*)"'
REGEXP_TEXT_WITHIN_QUOTES = r'"([\w+_\./\\\'\’\`\s\-]*)"'

mention: Mention = None
action: MentionAction = None
Expand Down Expand Up @@ -103,7 +103,7 @@ def parse(self) -> bool:
raise RuntimeError("Load the mention successfully before trying to parse it")

# Before anything, remove the HTML stuff
content = bs4(self.mention.content, features="html.parser").get_text()
content = BeautifulSoup(self.mention.content, features="html.parser").get_text()

# Removing the self username from the mention, so we have a clean string to parse
username_position, content = self.remove_self_username_from_content(content=content)
Expand All @@ -127,6 +127,11 @@ def parse(self) -> bool:
# We work by words, so split the mentionby spaces:
words = content.split()

# If the mention was empty, behave polite like an organinc mention.
if len(words) == 0:
self.error = self.ERROR_NO_COMMAND
return False

# First word must be the verb/action, from the valid ones
self.action = MentionAction.valid_or_none(words.pop(0))
self._logger.debug(f"Got an action: {self.action}")
Expand Down Expand Up @@ -309,7 +314,10 @@ def answer_back(self) -> bool:

def _format_answer(self, text: str) -> str:

return f"@{self.mention.username} {text}"
# It's a mess: sometimes with, sometimes without...
username = self.mention.username.lstrip("@")

return f"@{username} {text}"

def parse_complements(self, words: list, quoted_text: str = None) -> bool:

Expand Down Expand Up @@ -377,14 +385,18 @@ def parse_complements(self, words: list, quoted_text: str = None) -> bool:
if not self._feeds_storage.key_exists(first_word):
self.error = self.ERROR_NOT_FOUND_ALIAS
return False
# We check again if we still have words
if len(words) == 0:
self.error = self.ERROR_MISSING_PARAMS
return False
# Second needs to be a valid URL
second_word = words.pop(0)
if not Url.is_valid(second_word):
self.error = self.ERROR_INVALID_URL
return False
# It could be already a RSS URL
if Url.is_a_valid_feed(first_word):
rss_url = first_word
rss_url = second_word
else:
# ... and contain a RSS
list_of_possible_rss_urls = Url.findfeeds(second_word)
Expand Down Expand Up @@ -450,7 +462,9 @@ def is_alias_valid(self, alias) -> bool:
return alias == slugify(alias)

def small_user(self, username) -> str:
return f"@{username.split('@')[1]}"
# Generalising having the username with or without the @ in front
username = username.lstrip("@")
return f"@{username.split('@')[0]}"

def user_can_write(self) -> str:
return self._restrict_writes and (
Expand All @@ -466,37 +480,40 @@ def get_text_inside_quotes(self, content) -> str:

return m.group(1)

def remove_self_username_from_content(self, content: str):
def remove_self_username_from_content(self, content: str) -> tuple:
"""
Removes the self username from the content.

It returns a tuple where:
- index 0 is the position where the username was found
- index 1 is the content once cleaned
"""

# This is a mention. There has to be ALWAYS the self username anywhere in the content.
# The username is expressed as short @feeder or long @[email protected].
# Let's start with the long one, as it's the one we have without calculations.

username_position = content.find(self.me)

# We get a non -1 integer, meaning that the username is there
if username_position >= 0:
# Remove the username from the content
content = content.replace(self.me, "")
# Now return the position it was found
return username_position, content

# Still here? Let's try now with the small version of the username
small_me = self.small_user(self.me)
username_position = content.find(small_me)

# We get a non -1 integer, meaning that the username is there
if username_position >= 0:
# Remove the username from the content
content = content.replace(small_me, "")
# Now return the position it was found
return username_position, content

# Cannot be that you're already here! Then return something unexpected
return -1, content
# First we try to find the long username
username = self.me
username_position = content.find(username)
if username_position < 0:
# Not found, then we try the short username
username = self.small_user(self.me)
username_position = content.find(username)
if username_position < 0:
# Not found either, which is strange as it is a mention!
# then return as is.
return -1, content

# Now just remove the found username
content = content.replace(username, "")

# Apply some string cleanings,
# as removing may have left unwanted spaces
content = content.replace(" ", " ").lstrip()

# Return position and cleaned content
return username_position, content.replace(" ", " ").lstrip()


class MentionAction:
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ markers = ["slow"]
pythonpath = [
"."
]
filterwarnings = [
"ignore::bs4.MarkupResemblesLocatorWarning"
]

[tool.yapf]
column_limit = 96
Expand Down
Loading
Loading