diff --git a/instaloader/structures.py b/instaloader/structures.py index c1f95c4..6136070 100644 --- a/instaloader/structures.py +++ b/instaloader/structures.py @@ -152,7 +152,7 @@ _hashtag_regex = re.compile(r"(?:#)((?:\w){1,150})") # support Unicode and a word/beginning of string delimiter at the beginning to ensure # that no email addresses join the list of mentions. # http://blog.jstassen.com/2016/03/code-regex-for-instagram-username-and-hashtags/ -_mention_regex = re.compile(r"(?:^|[^\w\n]|_)(?:@)(\w(?:(?:\w|(?:\.(?!\.))){0,28}(?:\w))?)", re.ASCII) +_mention_regex = re.compile(r"(?:^|\W|_)(?:@)(\w(?:(?:\w|(?:\.(?!\.))){0,28}(?:\w))?)", re.ASCII) def _optional_normalize(string: Optional[str]) -> Optional[str]: diff --git a/test/instaloader_unittests.py b/test/instaloader_unittests.py index 0cb7c40..87d5990 100644 --- a/test/instaloader_unittests.py +++ b/test/instaloader_unittests.py @@ -210,5 +210,28 @@ class TestInstaloaderLoggedIn(TestInstaloaderAnonymously): break +class TestCaptionMentions(unittest.TestCase): + """Caption parsing, which requires no network access.""" + + @staticmethod + def _post_with_caption(caption: str) -> instaloader.Post: + return instaloader.Post(None, {"shortcode": "BhrEy4nBFVU", "caption": caption}) + + def test_caption_mentions(self): + for caption, expected in [ + ("@alice at the beginning", ["alice"]), + ("preceded by a space @bob", ["bob"]), + ("preceded by a newline\n@carol", ["carol"]), + ("multiple lines\n@dave\n@erin", ["dave", "erin"]), + ("no mentions here", []), + ]: + with self.subTest(caption=caption): + self.assertEqual(self._post_with_caption(caption).caption_mentions, expected) + + def test_caption_mentions_ignores_email_addresses(self): + post = self._post_with_caption("write to alice@example.com\ncontact @bob instead") + self.assertEqual(post.caption_mentions, ["bob"]) + + if __name__ == '__main__': unittest.main()