From a34c0388a3653d593d1030e613faf8951a1cc0c5 Mon Sep 17 00:00:00 2001 From: uukelele Date: Mon, 2 Mar 2026 16:56:15 +0000 Subject: [PATCH 1/4] add `is_followed_by_me` to fix #571 Signed-off-by: uukelele --- scratchattach/site/user.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/scratchattach/site/user.py b/scratchattach/site/user.py index a36506f7..379bcd70 100644 --- a/scratchattach/site/user.py +++ b/scratchattach/site/user.py @@ -494,6 +494,29 @@ def is_followed_by(self, user): return followed return followed + def is_followed_by_me(self): + """ + You can only use this function if this object was created using :meth:`scratchattach.session.Session.connect_user` + + Returns: + boolean: Whether the user is followed by the user currently logged in. + """ + self._assert_permission() + with requests.no_error_handling(): + resp = requests.get( + f"https://scratch.mit.edu/users/{self.username}/", + headers=self._headers, + cookies=self._cookies, + ) + soup = BeautifulSoup(resp.text, "html.parser") + follow_btn = soup.select_one("div.follow-button") + if not follow_btn: + print("Warning: follow button not found in page.") + return False # defualt to not followed + data_control = follow_btn.get("data-control") + return data_control == 'unfollow' # True if unfollow, False if not + + def project_count(self): with requests.no_error_handling(): text = requests.get( From 67fdb3371617989bb4f98b8ecc058dd5b8b50026 Mon Sep 17 00:00:00 2001 From: uukelele Date: Mon, 2 Mar 2026 17:02:53 +0000 Subject: [PATCH 2/4] add tests for `is_followed_by_me` Signed-off-by: uukelele --- tests/test_user.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_user.py b/tests/test_user.py index 6346dee4..477ffd51 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -106,6 +106,11 @@ def test_user(): assert status_data["status"] == "Sample status" assert status_data["color"] == "#855cd6" + uukelele = sess.connect_user("uukelele") # could use anyone ScratchAttachV2 is following right now but i think its cool that its following my account - uukelele, 2026 + assert uukelele.is_followed_by_me() + # and someone he is not following + assert not griffpatch.is_followed_by_me() + if __name__ == "__main__": test_user() From 25d85560d2370df9a14d9c05bbbad6b414838c01 Mon Sep 17 00:00:00 2001 From: uukelele Date: Mon, 2 Mar 2026 17:06:31 +0000 Subject: [PATCH 3/4] you named it wrong Signed-off-by: uukelele --- tests/test_user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_user.py b/tests/test_user.py index 477ffd51..4dfefe46 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -6,7 +6,7 @@ def test_user(): if not credentials_available(): warnings.warn( - "Skipped test_studio because there were no credentials available." + "Skipped test_user because there were no credentials available." ) return sess = session() From ec01dfaa2f014ceb0eedf9eac014e031e822a6dc Mon Sep 17 00:00:00 2001 From: uukelele Date: Mon, 2 Mar 2026 17:29:26 +0000 Subject: [PATCH 4/4] fix: assert that user is logged in but don't require to be profile owner Signed-off-by: uukelele --- scratchattach/site/user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scratchattach/site/user.py b/scratchattach/site/user.py index 379bcd70..51db4c61 100644 --- a/scratchattach/site/user.py +++ b/scratchattach/site/user.py @@ -501,7 +501,7 @@ def is_followed_by_me(self): Returns: boolean: Whether the user is followed by the user currently logged in. """ - self._assert_permission() + self._assert_auth() with requests.no_error_handling(): resp = requests.get( f"https://scratch.mit.edu/users/{self.username}/",