+ status_ids = map status_id statuses
+
+
+-- |Parse one username from a word.
+parse_username :: String -> Maybe String
+parse_username word =
+ case matches of
+ Nothing -> Nothing
+ Just [] -> Nothing
+ Just (first_match:_) -> Just first_match
+ where
+ username_regex = mkRegex "@([a-zA-Z0-9_]+)"
+ matches = matchRegex username_regex word
+
+
+-- |Parse all usernames of the form \@username from a status.
+parse_usernames_from_status :: Status -> [String]
+parse_usernames_from_status status =
+ catMaybes (map parse_username status_words)
+ where
+ status_words = splitWs (text status)
+
+-- |Get all referenced users' timeline URLs.
+make_user_timeline_urls :: Status -> [String]
+make_user_timeline_urls status =
+ map screen_name_to_timeline_url usernames
+ where
+ usernames = parse_usernames_from_status status
+
+
+status_tests :: [Test]
+status_tests = [ test_parse_usernames ]
+
+
+test_parse_usernames :: Test
+test_parse_usernames =
+ TestCase $
+ assertEqual
+ "All usernames are parsed."
+ expected_usernames
+ actual_usernames
+ where
+ dummy_user = User { screen_name = "nobody" }
+ dummy_status = Status { status_id = 1,
+ created_at = "never",
+ text = "Hypothesis: @donsbot and @bonus500 are two personalities belonging to the same person.",
+ user = dummy_user,
+ reply = False,
+ retweet = False
+ }
+
+ actual_usernames = parse_usernames_from_status dummy_status
+ expected_usernames = ["donsbot", "bonus500"]