Merge branch 'dev' into 'main'
Dev See merge request trustcafe/trustcafe-api-wrapper!10
This commit is contained in:
commit
89fc8706cb
10 changed files with 194 additions and 36 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -26,4 +26,6 @@ dist/*
|
|||
|
||||
# Test Artifacts
|
||||
token_data.json
|
||||
token_data_alpha.json
|
||||
token_dataproduction.json
|
||||
test_output.json
|
||||
|
|
@ -25,6 +25,11 @@ potentially misleading.
|
|||
1. Make more jobs
|
||||
2. Make more wrappers
|
||||
3. Write more documentation
|
||||
4. Wrappers should also accept actual keys for when you know them
|
||||
5. Add utility to manage the token easily to encourage reuse over
|
||||
new tokens every time
|
||||
|
||||
|
||||
|
||||
Trust
|
||||
Follow
|
||||
|
|
|
|||
|
|
@ -24,6 +24,30 @@ API = APIClient(
|
|||
debug=False,
|
||||
)
|
||||
```
|
||||
## Handle token (easy way)
|
||||
|
||||
```python
|
||||
API.handle_token()
|
||||
```
|
||||
## Handling the token yourself
|
||||
|
||||
```python
|
||||
|
||||
def getMyToken():
|
||||
# get the token from your personal store
|
||||
# initially this will be None
|
||||
return token_data
|
||||
|
||||
def saveMyToken():
|
||||
# save your token to your personal store
|
||||
return True
|
||||
|
||||
# Use the old token or None if we haven't logged in ever from here
|
||||
API.set_token(getMyToken())
|
||||
# Get a new one if we don't have one or if the existing one is expired
|
||||
if not API.is_token_valid():
|
||||
saveMyToken(API.sign_in())
|
||||
```
|
||||
|
||||
## Use a wrapper
|
||||
Wrappers make it as simple as possible to perform an action.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "trustcafeapiwrapper"
|
||||
version = "0.1.0.10"
|
||||
version = "0.1.0.11"
|
||||
description = "Wraps the Trust Cafe API"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import requests
|
||||
import os,requests
|
||||
import simplejson as json
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from pydantic import (
|
||||
PrivateAttr, BaseModel, SecretStr, HttpUrl
|
||||
)
|
||||
|
|
@ -153,6 +152,28 @@ class APIClient(BaseModel):
|
|||
current_time = int(time.time())
|
||||
return self._access_token and current_time < self._access_token_timeout
|
||||
|
||||
def handle_token(self, token_data_path=None):
|
||||
"""
|
||||
Handle access token retrieval and caching.
|
||||
"""
|
||||
if token_data_path is None:
|
||||
token_data_path = f"token_data_{self.environment}.json"
|
||||
|
||||
if os.path.exists(token_data_path):
|
||||
with open(token_data_path, "r") as f:
|
||||
token_data = json.load(f)
|
||||
self.set_token(token_data)
|
||||
else:
|
||||
if self.debug:
|
||||
print(f"No token data file found at '{token_data_path}'. A new token will be obtained.")
|
||||
raise FileNotFoundError(f"Token data file '{token_data_path}' not found. Please ensure the file exists or handle token retrieval appropriately.")
|
||||
|
||||
# Get a new one if we don't have one or if the existing one is expired
|
||||
if not self.is_token_valid():
|
||||
tokendata = self.sign_in()
|
||||
with open(token_data_path, "w") as f:
|
||||
json.dump(tokendata, f, indent=2)
|
||||
|
||||
def run_job(self, job_function, *args, **kwargs):
|
||||
"""
|
||||
Utility method to run a job function with the API client as the first argument.
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
|
||||
from trustcafeapiwrapper.utils.get_parent_pksk_from_path import get_parent_pksk_from_path
|
||||
from trustcafeapiwrapper.utils.get_post_pksk import get_post_pksk
|
||||
def create_comment(comment_text, post_slug, parent_path, blur_label=None, version=3):
|
||||
def create_comment(comment_text, post_slug=None, parent_path=None, post_key=None, blur_label=None, version=3):
|
||||
"""
|
||||
Creates a new comment.
|
||||
|
||||
Args:
|
||||
|
||||
comment_text (str): The text content of the comment.
|
||||
parent_path (str): The parent path for the comment, in the format 'userprofile/slug' or 'subwiki/slug'.
|
||||
post_slug (str, optional): The slug of the post to which the comment belongs.
|
||||
parent_path (str, optional): The parent path for the comment, in the format 'userprofile/slug' or 'subwiki/slug'.
|
||||
post_key (dict, optional): A dictionary containing the primary key (pk) and sort key (sk) of the post.
|
||||
blur_label (str, optional): An optional label for blurring the comment content.
|
||||
version (int, optional): The version of the comment structure to use, default is 3.
|
||||
|
||||
|
|
@ -15,9 +18,20 @@ def create_comment(comment_text, post_slug, parent_path, blur_label=None, versio
|
|||
dict: A dictionary containing the job name and payload for creating the comment
|
||||
that will be processed by the API client wrapper function.
|
||||
"""
|
||||
|
||||
parent_pksk = get_parent_pksk_from_path(parent_path)
|
||||
post_pksk = get_post_pksk(parent_pksk, post_slug)
|
||||
if post_key is not None:
|
||||
post_pksk = {
|
||||
"pk": post_key.get('pk'),
|
||||
"sk": post_key.get('sk')
|
||||
}
|
||||
elif parent_path is not None and post_slug is not None:
|
||||
parent_pksk = get_parent_pksk_from_path(parent_path)
|
||||
post_pksk = get_post_pksk(parent_pksk, post_slug)
|
||||
else:
|
||||
raise ValueError("Either post_key or both parent_path and post_slug must be provided.")
|
||||
|
||||
if comment_text is None or comment_text.strip() == "":
|
||||
raise ValueError("Comment text cannot be empty.")
|
||||
|
||||
return {
|
||||
"job_function": "comment.create",
|
||||
"payload": {
|
||||
|
|
@ -26,7 +40,7 @@ def create_comment(comment_text, post_slug, parent_path, blur_label=None, versio
|
|||
"parent": {
|
||||
"pk": post_pksk['pk'],
|
||||
"sk": post_pksk['sk'],
|
||||
"slug": parent_path.split('/')[-1]
|
||||
"slug": post_pksk.get('sk', '').replace('post#', ''),
|
||||
},
|
||||
"topLevel": {
|
||||
"pk": post_pksk['pk'],
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
from trustcafeapiwrapper.utils import get_post_pksk, get_parent_pksk_from_path
|
||||
|
||||
def update_post(parent_path, post_path, post_text, blur_label=None, card_url=None, collaborative=False):
|
||||
def update_post( post_text, post_path=None, parent_path='/', post_key=None, blur_label=None, card_url=None, collaborative=False):
|
||||
"""
|
||||
Updates an existing post.
|
||||
|
||||
Args:
|
||||
post_slug (str): The slug of the post to update.
|
||||
post_text (str): The new text for the post.
|
||||
post_path (str, optional): The path of the post to update. Defaults to None.
|
||||
parent_path (str, optional): The parent path for the post. Defaults to '/'.
|
||||
post_key (dict, optional): A dictionary containing the primary key (pk) and sort key (sk) of the post. Defaults to None.
|
||||
blur_label (str, optional): The blur label for the post. Defaults to None.
|
||||
card_url (str, optional): The card URL for the post. Defaults to None.
|
||||
collaborative (bool, optional): Whether the post is collaborative. Defaults to False.
|
||||
|
|
@ -15,21 +17,38 @@ def update_post(parent_path, post_path, post_text, blur_label=None, card_url=Non
|
|||
Returns:
|
||||
dict: The updated post data.
|
||||
"""
|
||||
parent_pksk = get_parent_pksk_from_path(parent_path)
|
||||
post_pksk = get_post_pksk(parent_pksk, post_path)
|
||||
if post_key is not None:
|
||||
post_pksk = {
|
||||
'pk': post_key.get('pk', None),
|
||||
'sk': post_key.get('sk', None)
|
||||
}
|
||||
elif post_path is not None and parent_path is not None:
|
||||
parent_pksk = get_parent_pksk_from_path(parent_path)
|
||||
post_pksk = get_post_pksk(parent_pksk, post_path)
|
||||
else:
|
||||
raise ValueError("Either post_path and parent_path or post_key must be provided.")
|
||||
|
||||
|
||||
if post_text is None:
|
||||
raise ValueError("post_text is required.")
|
||||
|
||||
|
||||
payload = {
|
||||
"key": {
|
||||
"pk": post_pksk.get('pk', None),
|
||||
"sk": post_pksk.get('sk', None)
|
||||
},
|
||||
"postSlug": post_path.strip('/post/'),
|
||||
"blurLabel": blur_label,
|
||||
"cardUrl": card_url,
|
||||
"postText": post_text,
|
||||
"collaborative": collaborative,
|
||||
|
||||
"postSlug": post_pksk.get('sk', '').replace('post#', ''),
|
||||
"postText": post_text
|
||||
}
|
||||
if collaborative is not None:
|
||||
payload["collaborative"] = collaborative
|
||||
|
||||
if blur_label is not None:
|
||||
payload["blurLabel"] = blur_label
|
||||
|
||||
if card_url is not None:
|
||||
payload["cardUrl"] = card_url
|
||||
|
||||
return {
|
||||
"job_function": "post.update",
|
||||
|
|
|
|||
17
testing.py
17
testing.py
|
|
@ -26,16 +26,7 @@ API = APIClient(
|
|||
# Keep a token cache to avoid unnecessary sign-ins during development.
|
||||
# (In production, you'd handle this more robustly and securely)
|
||||
|
||||
if os.path.exists("token_data.json"):
|
||||
with open("token_data.json", "r") as f:
|
||||
token_data = json.load(f)
|
||||
API.set_token(token_data)
|
||||
|
||||
# Get a new one if we don't have one or if the existing one is expired
|
||||
if not API.is_token_valid():
|
||||
tokendata = API.sign_in()
|
||||
with open("token_data.json", "w") as f:
|
||||
json.dump(tokendata, f, indent=2)
|
||||
API.handle_token() # This will load the token from file if it exists and is valid, or sign in to get a new one if not.
|
||||
|
||||
'''
|
||||
END IMPORTANT BIT
|
||||
|
|
@ -50,8 +41,8 @@ def save_response(response):
|
|||
|
||||
|
||||
# print("-----------Get a user profile----------------")
|
||||
# profile = API.run_job('userprofile.get', "simon-little")
|
||||
# print(profile)
|
||||
profile = API.run_job('userprofile.get', "simon-little")
|
||||
print(profile)
|
||||
# print("-------------- Get a branch -----------------")
|
||||
# branch = API.run_job('branch.get', "music")
|
||||
# print(branch)
|
||||
|
|
@ -138,7 +129,7 @@ def save_response(response):
|
|||
# x += 1
|
||||
|
||||
# save_response(API.run_job('notification.listnotifications'))
|
||||
save_response(API.run_job('notification.markallasread'))
|
||||
# save_response(API.run_job('notification.markallasread'))
|
||||
|
||||
# save_response(API.run_job('feed.cafefeed'))
|
||||
|
||||
|
|
|
|||
|
|
@ -19,4 +19,23 @@ class TestCreateComment(unittest.TestCase):
|
|||
self.assertEqual(result["payload"]["commentText"], self.comment_text)
|
||||
self.assertEqual(result["payload"]["blurLabel"], self.blur_label)
|
||||
self.assertEqual(result["payload"]["parent"]["pk"], "maintrunk#maintrunk")
|
||||
self.assertEqual(result["payload"]["parent"]["sk"], "post#1774951384-98fe38df")
|
||||
self.assertEqual(result["payload"]["parent"]["sk"], "post#1774951384-98fe38df")
|
||||
|
||||
def test_create_comment_with_post_key(self):
|
||||
post_key = {
|
||||
"pk": "maintrunk#maintrunk",
|
||||
"sk": "post#1774951384-98fe38df"
|
||||
}
|
||||
result = create_comment(
|
||||
comment_text=self.comment_text,
|
||||
post_key=post_key,
|
||||
blur_label=self.blur_label
|
||||
)
|
||||
self.assertIsInstance(result, dict)
|
||||
self.assertIn("job_function", result)
|
||||
self.assertIn("payload", result)
|
||||
self.assertEqual(result["job_function"], "comment.create")
|
||||
self.assertEqual(result["payload"]["commentText"], self.comment_text)
|
||||
self.assertEqual(result["payload"]["blurLabel"], self.blur_label)
|
||||
self.assertEqual(result["payload"]["parent"]["pk"], post_key["pk"])
|
||||
self.assertEqual(result["payload"]["parent"]["sk"], post_key["sk"])
|
||||
|
|
@ -21,10 +21,73 @@ class TestUpdatePost(unittest.TestCase):
|
|||
self.assertIn("payload", result)
|
||||
self.assertEqual(result["job_function"], "post.update")
|
||||
self.assertEqual(result["payload"]["postText"], self.post_text)
|
||||
self.assertEqual(result["payload"]["blurLabel"], self.blur_label)
|
||||
self.assertEqual(result["payload"]["cardUrl"], self.card_url)
|
||||
self.assertEqual(result["payload"]["collaborative"], self.collaborative)
|
||||
self.assertEqual(result["payload"]["postSlug"], "1235-abcv")
|
||||
self.assertEqual(result["payload"]["key"]["pk"], "maintrunk#maintrunk")
|
||||
self.assertEqual(result["payload"]["key"]["sk"], "post#1235-abcv")
|
||||
self.assertNotIn("slug", result["payload"]["key"])
|
||||
self.assertNotIn("slug", result["payload"]["key"])
|
||||
|
||||
def test_update_post_with_post_key(self):
|
||||
post_key = {
|
||||
"pk": "maintrunk#maintrunk",
|
||||
"sk": "post#1235-abcv"
|
||||
}
|
||||
result = update_post(
|
||||
post_key=post_key,
|
||||
post_text=self.post_text,
|
||||
blur_label=self.blur_label,
|
||||
card_url=self.card_url,
|
||||
collaborative=self.collaborative,
|
||||
)
|
||||
self.assertIsInstance(result, dict)
|
||||
self.assertIn("job_function", result)
|
||||
self.assertIn("payload", result)
|
||||
self.assertEqual(result["job_function"], "post.update")
|
||||
self.assertEqual(result["payload"]["postText"], self.post_text)
|
||||
self.assertEqual(result["payload"]["postSlug"], "1235-abcv")
|
||||
self.assertEqual(result["payload"]["key"]["pk"], post_key["pk"])
|
||||
self.assertEqual(result["payload"]["key"]["sk"], post_key["sk"])
|
||||
self.assertNotIn("slug", result["payload"]["key"])
|
||||
|
||||
def test_update_collaborative_post(self):
|
||||
collaborative = True
|
||||
result = update_post(
|
||||
parent_path='/',
|
||||
post_path='/post/1235-abcv',
|
||||
post_text=self.post_text,
|
||||
blur_label=self.blur_label,
|
||||
card_url=self.card_url,
|
||||
collaborative=collaborative
|
||||
)
|
||||
self.assertIsInstance(result, dict)
|
||||
self.assertIn("job_function", result)
|
||||
self.assertIn("payload", result)
|
||||
self.assertEqual(result["job_function"], "post.update")
|
||||
self.assertEqual(result["payload"]["postText"], self.post_text)
|
||||
self.assertEqual(result["payload"]["postSlug"], "1235-abcv")
|
||||
self.assertEqual(result["payload"]["key"]["pk"], "maintrunk#maintrunk")
|
||||
self.assertEqual(result["payload"]["key"]["sk"], "post#1235-abcv")
|
||||
self.assertNotIn("slug", result["payload"]["key"])
|
||||
self.assertTrue(result["payload"]["collaborative"])
|
||||
|
||||
def test_update_blur_label_and_card_url(self):
|
||||
blur_label = "Sensitive Content"
|
||||
card_url = "https://example.com/card"
|
||||
result = update_post(
|
||||
parent_path='/',
|
||||
post_path='/post/1235-abcv',
|
||||
post_text=self.post_text,
|
||||
blur_label=blur_label,
|
||||
card_url=card_url,
|
||||
collaborative=self.collaborative
|
||||
)
|
||||
self.assertIsInstance(result, dict)
|
||||
self.assertIn("job_function", result)
|
||||
self.assertIn("payload", result)
|
||||
self.assertEqual(result["job_function"], "post.update")
|
||||
self.assertEqual(result["payload"]["postText"], self.post_text)
|
||||
self.assertEqual(result["payload"]["postSlug"], "1235-abcv")
|
||||
self.assertEqual(result["payload"]["key"]["pk"], "maintrunk#maintrunk")
|
||||
self.assertEqual(result["payload"]["key"]["sk"], "post#1235-abcv")
|
||||
self.assertNotIn("slug", result["payload"]["key"])
|
||||
self.assertEqual(result["payload"]["blurLabel"], blur_label)
|
||||
self.assertEqual(result["payload"]["cardUrl"], card_url)
|
||||
Loading…
Add table
Add a link
Reference in a new issue