Vote casting

This commit is contained in:
simonwt 2026-04-03 00:50:38 +01:00
parent 8704ad0e70
commit 80786c4965
12 changed files with 152 additions and 42 deletions

View file

@ -2,10 +2,10 @@
## Debates ## Debates
1. Not sure about the name `jobs` and `run_job`. Requests is an 1. Hating the name `jobs` and `run_job`. Requests is an
existing package dependency though. `tasks` seems to broard. I'm sure existing package dependency though. `tasks` seems to broard. I'm sure
there's probably an already existing name that I can't articulate how there's probably an already existing name that I can't articulate how
to find. to find. `apirequests`, `rqsts`, `apicalls`?
2. Should these `job` be called with dot notation? Or with slashes? Or 2. Should these `job` be called with dot notation? Or with slashes? Or
something else? Is it okay to have these as strings? something else? Is it okay to have these as strings?
3. Should we do validation in the `jobs` or let the server do that all? 3. Should we do validation in the `jobs` or let the server do that all?
@ -14,5 +14,5 @@ something else? Is it okay to have these as strings?
## ToDo: ## ToDo:
1. Make more jobs 1. Make more jobs
2. Make wrappers to make it less cumbersome when posting etc 2. Make more wrappers
3. Publish to PyPi or whatever 3. Write more documentation

View file

@ -0,0 +1 @@
from .votecast import votecast

View file

@ -0,0 +1,12 @@
def votecast(API, payload: dict) -> dict:
"""
Casts a vote in the API.
Args:
payload (dict): The data for the vote.
Returns:
dict: The vote data.
"""
vote_data = API.make_request("POST", "content", "votecast", data=payload, authenticate=True)
return vote_data

View file

@ -2,3 +2,4 @@ from .get_parent_pksk_from_path import get_parent_pksk_from_path
from .get_post_pksk import get_post_pksk from .get_post_pksk import get_post_pksk
from .make_comment_sk import make_comment_sk from .make_comment_sk import make_comment_sk
from .make_post_sk import make_post_sk from .make_post_sk import make_post_sk
from .get_child_spksk_from_paths import get_child_spksk_from_paths

View file

@ -0,0 +1,34 @@
from trustcafeapiwrapper.utils import get_parent_pksk_from_path, get_post_pksk, make_comment_sk, make_post_sk
def get_child_spksk_from_paths(parent_path: str, item_path: str):
'''
If it's a post we want to create a pk/sk like:
'{entity}#{parent_slug}' / 'post#{post_slug}'
If it's a comment we want to create a pk/sk like:
'post#{post_slug}' / 'comment#{comment_slug}'
'''
slug = item_path.split('/')[-1]
if item_path.startswith('/post'):
# It's a reaction on a post
top_level_parent_pk = get_parent_pksk_from_path(parent_path)
item_pksk = get_post_pksk(top_level_parent_pk, item_path)
entity = 'post'
else:
# It's a reaction on a comment
item_pksk = {
'pk': make_post_sk(parent_path),
'sk': make_comment_sk(item_path)
}
entity = 'comment'
return {
"pk": item_pksk.get('pk', None),
"sk": item_pksk.get('sk', None),
"entity": entity,
"slug": slug
}

View file

@ -1,5 +1,5 @@
from trustcafeapiwrapper.utils import get_parent_pksk_from_path, get_post_pksk, make_comment_sk, make_post_sk
from trustcafeapiwrapper.utils import get_child_spksk_from_paths
def react(reaction_type: str, parent_path: str, item_path: str): def react(reaction_type: str, parent_path: str, item_path: str):
""" """
React to something. ie a post or a comment. React to something. ie a post or a comment.
@ -12,40 +12,11 @@ def react(reaction_type: str, parent_path: str, item_path: str):
dict: A dictionary containing the job name and payload for creating the post dict: A dictionary containing the job name and payload for creating the post
that will be processed by the API client wrapper function. that will be processed by the API client wrapper function.
""" """
parent = get_child_spksk_from_paths(parent_path, item_path)
'''
If it's a post we want to create a pk/sk like:
'{entity}#{parent_slug}' / 'post#{post_slug}'
If it's a comment we want to create a pk/sk like:
'post#{post_slug}' / 'comment#{comment_slug}'
'''
slug = item_path.split('/')[-1]
if item_path.startswith('/post'):
# It's a reaction on a post
top_level_parent_pk = get_parent_pksk_from_path(parent_path)
item_pksk = get_post_pksk(top_level_parent_pk, item_path)
entity = 'post'
else:
# It's a reaction on a comment
item_pksk = {
'pk': make_post_sk(parent_path),
'sk': make_comment_sk(item_path)
}
entity = 'comment'
return { return {
"job_function": "reaction.reacttosomething", "job_function": "reaction.reacttosomething",
"payload": { "payload": {
"reaction": reaction_type, "reaction": reaction_type,
"parent": { "parent": parent
"pk": item_pksk.get('pk', None),
"sk": item_pksk.get('sk', None),
"entity": entity,
"slug": slug
}
} }
} }

View file

@ -0,0 +1 @@
from .votecast import votecast

View file

@ -0,0 +1,21 @@
from trustcafeapiwrapper.utils import get_child_spksk_from_paths
def votecast(vote: str, parent_path: str, item_path: str):
"""
Creates a new vote in the API.
Args:
Returns:
dict: A dictionary containing the job name and payload for creating the post
that will be processed by the API client wrapper function.
"""
parent = get_child_spksk_from_paths(parent_path, item_path)
return {
"job_function": "vote.votecast",
"payload": {
"vote": vote,
"parent": parent
}
}

View file

@ -148,7 +148,7 @@ from trustcafeapiwrapper.wrappers.post.create_post import create_post
# post_text="This is a test post created via the create_post wrapper function.", # post_text="This is a test post created via the create_post wrapper function.",
# parent_path="/branch/music", # parent_path="/branch/music",
# )) # ))
from trustcafeapiwrapper.wrappers.reaction import react # from trustcafeapiwrapper.wrappers.reaction import react
# save_response(create_post( # save_response(create_post(
# "This is a test post created via the create_post wrapper function.", # "This is a test post created via the create_post wrapper function.",
# "/userprofile/simon-little", # "/userprofile/simon-little",
@ -163,8 +163,14 @@ from trustcafeapiwrapper.wrappers.reaction import react
# "This is a test post created via the create_post wrapper function.", # "This is a test post created via the create_post wrapper function.",
# ))) # )))
save_response(API.wrapped(react( # save_response(API.wrapped(react(
"thumbs_up", # "thumbs_up",
# "/",
# "/post/1775075313-63ffb852"
# )))
from trustcafeapiwrapper.wrappers.vote import votecast
save_response(API.wrapped(votecast(
"up",
"/", "/",
"/post/1775075313-63ffb852" "/post/1775075313-63ffb852"
))) )))

View file

@ -0,0 +1,24 @@
import unittest
from trustcafeapiwrapper.utils.get_child_spksk_from_paths import get_child_spksk_from_paths
class TestGetChildSpkskFromPaths(unittest.TestCase):
def test_post_reaction(self):
parent_path = '/user/johndoe'
item_path = '/post/12345'
expected_output = {
"pk": "userprofile#johndoe",
"sk": "post#12345",
"entity": "post",
"slug": "12345"
}
self.assertEqual(get_child_spksk_from_paths(parent_path, item_path), expected_output)
def test_comment_reaction(self):
parent_path = '/post/12345'
item_path = '/comment/67890'
expected_output = {
"pk": "post#12345",
"sk": "comment#67890",
"entity": "comment",
"slug": "67890"
}
self.assertEqual(get_child_spksk_from_paths(parent_path, item_path), expected_output)

34
tests/wrappers/vote.py Normal file
View file

@ -0,0 +1,34 @@
import unittest
from trustcafeapiwrapper.wrappers.vote.votecast import votecast
class TestVoteCast(unittest.TestCase):
def test_vote_cast_to_post(self):
vote = 'up'
parent_path = '/'
item_path = '/post/12345'
result = votecast(vote, parent_path, item_path)
self.assertIsInstance(result, dict)
self.assertIn("job_function", result)
self.assertIn("payload", result)
self.assertEqual(result["job_function"], "vote.votecast")
self.assertEqual(result["payload"]["vote"], vote)
self.assertEqual(result["payload"]["parent"]["pk"], "maintrunk#maintrunk")
self.assertEqual(result["payload"]["parent"]["sk"], "post#12345")
self.assertEqual(result["payload"]["parent"]["entity"], "post")
self.assertEqual(result["payload"]["parent"]["slug"], "12345")
def test_vote_cast_to_comment(self):
vote = 'down'
parent_path = '/post/12345'
item_path = '/comment/67890'
result = votecast(vote, parent_path, item_path)
self.assertIsInstance(result, dict)
self.assertIn("job_function", result)
self.assertIn("payload", result)
self.assertEqual(result["job_function"], "vote.votecast")
self.assertEqual(result["payload"]["vote"], vote)
self.assertEqual(result["payload"]["parent"]["pk"], "post#12345")
self.assertEqual(result["payload"]["parent"]["sk"], "comment#67890")
self.assertEqual(result["payload"]["parent"]["entity"], "comment")
self.assertEqual(result["payload"]["parent"]["slug"], "67890")

View file

@ -2,11 +2,16 @@ import sys
sys.path.insert(0, './src/') sys.path.insert(0, './src/')
import unittest import unittest
from tests.wrappers.create_post import TestCreatePost
from tests.wrappers.create_comment import TestCreateComment
from tests.wrappers.react import TestReact
from tests.utils.get_post_pksk import TestGetPostPksk from tests.utils.get_post_pksk import TestGetPostPksk
from tests.utils.get_parent_pksk_from_path import TestGetParentPkskFromPath from tests.utils.get_parent_pksk_from_path import TestGetParentPkskFromPath
from tests.utils.make_comment_sk import TestMakeCommentSk from tests.utils.make_comment_sk import TestMakeCommentSk
from tests.utils.make_post_sk import TestMakePostSk from tests.utils.make_post_sk import TestMakePostSk
from tests.utils.get_child_spksk_from_paths import TestGetChildSpkskFromPaths
from tests.wrappers.create_post import TestCreatePost
from tests.wrappers.create_comment import TestCreateComment
from tests.wrappers.react import TestReact
from tests.wrappers.vote import TestVoteCast
unittest.main() unittest.main()