diff --git a/src/trustcafeapiwrapper/jobs/follow/__init__.py b/src/trustcafeapiwrapper/jobs/follow/__init__.py new file mode 100644 index 0000000..994e9c0 --- /dev/null +++ b/src/trustcafeapiwrapper/jobs/follow/__init__.py @@ -0,0 +1 @@ +from .follow import follow \ No newline at end of file diff --git a/src/trustcafeapiwrapper/jobs/follow/follow.py b/src/trustcafeapiwrapper/jobs/follow/follow.py new file mode 100644 index 0000000..91d8ee4 --- /dev/null +++ b/src/trustcafeapiwrapper/jobs/follow/follow.py @@ -0,0 +1,12 @@ +def follow(API, payload: dict) -> dict: + """ + Creates or updates a follow relationship in the API. + + Args: + payload (dict): The data for the follow relationship. + + Returns: + dict: The follow relationship data. + """ + follow_data = API.make_request("POST", "content", "relfollow", data=payload, authenticate=True) + return follow_data \ No newline at end of file diff --git a/src/trustcafeapiwrapper/utils/__init__.py b/src/trustcafeapiwrapper/utils/__init__.py index 08e5cba..1b28d26 100644 --- a/src/trustcafeapiwrapper/utils/__init__.py +++ b/src/trustcafeapiwrapper/utils/__init__.py @@ -4,4 +4,5 @@ from .make_comment_sk import make_comment_sk from .make_post_sk import make_post_sk from .get_child_spksk_from_paths import get_child_spksk_from_paths from .get_user_slug_from_path import get_user_slug_from_path -from .get_userprofile_pksk_from_slug import get_userprofile_pksk_from_slug \ No newline at end of file +from .get_userprofile_pksk_from_slug import get_userprofile_pksk_from_slug +from .get_entity_from_str import get_entity_from_str \ No newline at end of file diff --git a/src/trustcafeapiwrapper/utils/get_entity_from_str.py b/src/trustcafeapiwrapper/utils/get_entity_from_str.py new file mode 100644 index 0000000..529d69b --- /dev/null +++ b/src/trustcafeapiwrapper/utils/get_entity_from_str.py @@ -0,0 +1,34 @@ +def get_entity_from_str(entity): + + # Translate the more obvious names to our + # obscure internal ones - sorry about that! + if entity == 'branch': + entity = 'subwiki' + elif entity == 'user': + entity = 'userprofile' + elif entity == 'follow': + entity = 'relfollow' + elif entity == 'trust': + entity = 'reltrust' + elif entity == 'block': + entity = 'userblock' + elif entity == 'mute': + entity = 'usermute' + + + valid = [ + 'comment', + 'post', + 'reaction', + 'relfollow', + 'reltrust', + 'subwiki', + 'userblock', + 'usermute', + 'userprofile', + 'vote', + ] + if entity not in valid: + raise ValueError(f"Invalid entity: {entity}. Must be one of {', '.join(valid)}.") + + return entity diff --git a/src/trustcafeapiwrapper/utils/get_parent_pksk_from_path.py b/src/trustcafeapiwrapper/utils/get_parent_pksk_from_path.py index 4cd061a..b328f21 100644 --- a/src/trustcafeapiwrapper/utils/get_parent_pksk_from_path.py +++ b/src/trustcafeapiwrapper/utils/get_parent_pksk_from_path.py @@ -1,13 +1,11 @@ +from .get_entity_from_str import get_entity_from_str def get_parent_pksk_from_path(parent_path): if parent_path == '/': return 'maintrunk#maintrunk' entity, slug = parent_path.strip('/').split('/') - if entity == 'branch': - entity = 'subwiki' - elif entity == 'user': - entity = 'userprofile' + entity = get_entity_from_str(entity) if entity not in ['userprofile', 'subwiki']: raise ValueError(f"Invalid parent entity: {entity}. Must be 'userprofile' or 'subwiki'.") diff --git a/src/trustcafeapiwrapper/wrappers/follow/follow.py b/src/trustcafeapiwrapper/wrappers/follow/follow.py new file mode 100644 index 0000000..c3c513a --- /dev/null +++ b/src/trustcafeapiwrapper/wrappers/follow/follow.py @@ -0,0 +1,39 @@ +from trustcafeapiwrapper.utils.get_entity_from_str import get_entity_from_str + +def follow( + entity: str, + is_following: bool, + parent_slug: str, + ): + """ + Creates new or update existing follow entry in the API. + + Args: + entity (str): The type of entity to follow (userprofile | subwiki). + is_following (bool): Indicates whether the entity is being followed. + parent_slug (str): The slug of the parent entity. + + Returns: + dict: A dictionary containing the job name and payload for creating the post + that will be processed by the API client wrapper function. + """ + entity = get_entity_from_str(entity) + + itemPKSK = f"{entity}#{parent_slug}" + + return { + "job_function": "follow.follow", + "payload": { + "isFollowing": is_following, + "parent": { + "pk": itemPKSK, + "sk": itemPKSK + }, + "followType": entity, + "preferences": { + "notification": True, + "emailNew": False, + "emailDigest": True + } + } + } diff --git a/tests/utils/get_entity_from_str.py b/tests/utils/get_entity_from_str.py new file mode 100644 index 0000000..540db96 --- /dev/null +++ b/tests/utils/get_entity_from_str.py @@ -0,0 +1,19 @@ +import unittest +from trustcafeapiwrapper.utils.get_entity_from_str import get_entity_from_str + +class TestGetEntityFromStr(unittest.TestCase): + def test_branch(self): + self.assertEqual(get_entity_from_str('branch'), 'subwiki') + + def test_user(self): + self.assertEqual(get_entity_from_str('user'), 'userprofile') + + def test_subwiki(self): + self.assertEqual(get_entity_from_str('subwiki'), 'subwiki') + + def test_userprofile(self): + self.assertEqual(get_entity_from_str('userprofile'), 'userprofile') + + def test_invalid_entity(self): + with self.assertRaises(ValueError): + get_entity_from_str('invalidentity') \ No newline at end of file diff --git a/tests/wrappers/follow.py b/tests/wrappers/follow.py new file mode 100644 index 0000000..1994d71 --- /dev/null +++ b/tests/wrappers/follow.py @@ -0,0 +1,23 @@ +import unittest +from trustcafeapiwrapper.wrappers.follow.follow import follow + +class TestFollow(unittest.TestCase): + def test_follow(self): + + result = follow( + entity='user', + is_following=True, + parent_slug='janedoe' + ) + + self.assertIsInstance(result, dict) + self.assertIn("job_function", result) + self.assertIn("payload", result) + self.assertEqual(result["job_function"], "follow.follow") + self.assertIsInstance(result["payload"], dict) + self.assertIn("isFollowing", result["payload"]) + self.assertIn("parent", result["payload"]) + self.assertIn("followType", result["payload"]) + self.assertIn("preferences", result["payload"]) + self.assertEqual(result["payload"]["isFollowing"], True) + self.assertEqual(result["payload"]["parent"]["pk"], "userprofile#janedoe") \ No newline at end of file diff --git a/unittests.py b/unittests.py index d0dc1b9..c79f4d8 100644 --- a/unittests.py +++ b/unittests.py @@ -2,6 +2,7 @@ import sys sys.path.insert(0, './src/') import unittest +from tests.utils.get_entity_from_str import TestGetEntityFromStr from tests.utils.get_post_pksk import TestGetPostPksk from tests.utils.get_parent_pksk_from_path import TestGetParentPkskFromPath from tests.utils.make_comment_sk import TestMakeCommentSk @@ -16,7 +17,7 @@ from tests.wrappers.create_comment import TestCreateComment from tests.wrappers.react import TestReact from tests.wrappers.vote import TestVoteCast from tests.wrappers.trust import TestTrustCreateOrUpdate - +from tests.wrappers.follow import TestFollow from tests.apiclient import TestAPIClient