2026-07-19 17:52:14 +03:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""Read and write Posts on the Muninn API.
|
|
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
python3 posts.py list [--status STATUS] [--site-id ID] [--social-account-id ID] [--due]
|
|
|
|
|
python3 posts.py get POST_ID
|
|
|
|
|
python3 posts.py create --site-id ID --type TYPE --body BODY
|
2026-07-21 14:04:45 +03:00
|
|
|
[--social-account-id ID] [--title TITLE] [--target TARGET]
|
2026-07-19 17:52:14 +03:00
|
|
|
[--status STATUS] [--scheduled-at DATETIME]
|
|
|
|
|
python3 posts.py update POST_ID [--site-id ID] [--social-account-id ID]
|
2026-07-21 14:04:45 +03:00
|
|
|
[--type TYPE] [--title TITLE] [--body BODY] [--target TARGET]
|
2026-07-19 17:52:14 +03:00
|
|
|
[--status STATUS] [--scheduled-at DATETIME]
|
|
|
|
|
[--published-url URL]
|
|
|
|
|
python3 posts.py delete POST_ID
|
|
|
|
|
|
|
|
|
|
Base URL defaults to http://localhost:8001, override with the
|
|
|
|
|
MUNINN_API_URL environment variable.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
|
|
import _client
|
|
|
|
|
|
|
|
|
|
TYPES = ["twitter", "instagram", "facebook", "reddit", "tiktok", "linkedin", "youtube", "blog", "other"]
|
2026-07-21 14:04:45 +03:00
|
|
|
STATUSES = ["draft", "scheduled", "publishing", "published", "failed"]
|
2026-07-19 17:52:14 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> None:
|
|
|
|
|
parser = argparse.ArgumentParser(description="Posts API client")
|
|
|
|
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
|
|
|
|
|
|
|
|
list_parser = subparsers.add_parser("list", help="List posts")
|
|
|
|
|
list_parser.add_argument("--status", choices=STATUSES)
|
|
|
|
|
list_parser.add_argument("--site-id", type=int)
|
|
|
|
|
list_parser.add_argument("--social-account-id", type=int)
|
|
|
|
|
list_parser.add_argument(
|
|
|
|
|
"--due", action="store_true", help="Only posts that are scheduled and due now"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
get_parser = subparsers.add_parser("get", help="Get a single post")
|
|
|
|
|
get_parser.add_argument("post_id", type=int)
|
|
|
|
|
|
|
|
|
|
create_parser = subparsers.add_parser("create", help="Create a post")
|
|
|
|
|
create_parser.add_argument("--site-id", type=int, required=True)
|
|
|
|
|
create_parser.add_argument("--type", choices=TYPES, required=True)
|
|
|
|
|
create_parser.add_argument("--body", required=True)
|
|
|
|
|
create_parser.add_argument("--social-account-id", type=int)
|
|
|
|
|
create_parser.add_argument("--title")
|
2026-07-21 14:04:45 +03:00
|
|
|
create_parser.add_argument("--target", help="Network-specific destination, e.g. a subreddit for Reddit posts")
|
2026-07-19 17:52:14 +03:00
|
|
|
create_parser.add_argument("--status", choices=STATUSES)
|
|
|
|
|
create_parser.add_argument("--scheduled-at", help="ISO 8601 datetime, e.g. 2026-07-20T09:00:00")
|
|
|
|
|
|
|
|
|
|
update_parser = subparsers.add_parser("update", help="Update a post")
|
|
|
|
|
update_parser.add_argument("post_id", type=int)
|
|
|
|
|
update_parser.add_argument("--site-id", type=int)
|
|
|
|
|
update_parser.add_argument("--social-account-id", type=int)
|
|
|
|
|
update_parser.add_argument("--type", choices=TYPES)
|
|
|
|
|
update_parser.add_argument("--title")
|
|
|
|
|
update_parser.add_argument("--body")
|
2026-07-21 14:04:45 +03:00
|
|
|
update_parser.add_argument("--target", help="Network-specific destination, e.g. a subreddit for Reddit posts")
|
2026-07-19 17:52:14 +03:00
|
|
|
update_parser.add_argument("--status", choices=STATUSES)
|
|
|
|
|
update_parser.add_argument("--scheduled-at", help="ISO 8601 datetime")
|
|
|
|
|
update_parser.add_argument("--published-url")
|
|
|
|
|
|
|
|
|
|
delete_parser = subparsers.add_parser("delete", help="Delete a post")
|
|
|
|
|
delete_parser.add_argument("post_id", type=int)
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
if args.command == "list":
|
|
|
|
|
params = {
|
|
|
|
|
"status": args.status,
|
|
|
|
|
"site_id": args.site_id,
|
|
|
|
|
"social_account_id": args.social_account_id,
|
|
|
|
|
}
|
|
|
|
|
if args.due:
|
|
|
|
|
params["due"] = 1
|
|
|
|
|
_client.request("GET", "/api/posts", params=params)
|
|
|
|
|
|
|
|
|
|
elif args.command == "get":
|
|
|
|
|
_client.request("GET", f"/api/posts/{args.post_id}")
|
|
|
|
|
|
|
|
|
|
elif args.command == "create":
|
|
|
|
|
body = {
|
|
|
|
|
"site_id": args.site_id,
|
|
|
|
|
"social_account_id": args.social_account_id,
|
|
|
|
|
"type": args.type,
|
|
|
|
|
"title": args.title,
|
|
|
|
|
"body": args.body,
|
2026-07-21 14:04:45 +03:00
|
|
|
"target": args.target,
|
2026-07-19 17:52:14 +03:00
|
|
|
"status": args.status,
|
|
|
|
|
"scheduled_at": args.scheduled_at,
|
|
|
|
|
}
|
|
|
|
|
body = {key: value for key, value in body.items() if value is not None}
|
|
|
|
|
_client.request("POST", "/api/posts", body=body)
|
|
|
|
|
|
|
|
|
|
elif args.command == "update":
|
|
|
|
|
body = {
|
|
|
|
|
"site_id": args.site_id,
|
|
|
|
|
"social_account_id": args.social_account_id,
|
|
|
|
|
"type": args.type,
|
|
|
|
|
"title": args.title,
|
|
|
|
|
"body": args.body,
|
2026-07-21 14:04:45 +03:00
|
|
|
"target": args.target,
|
2026-07-19 17:52:14 +03:00
|
|
|
"status": args.status,
|
|
|
|
|
"scheduled_at": args.scheduled_at,
|
|
|
|
|
"published_url": args.published_url,
|
|
|
|
|
}
|
|
|
|
|
body = {key: value for key, value in body.items() if value is not None}
|
|
|
|
|
_client.request("PATCH", f"/api/posts/{args.post_id}", body=body)
|
|
|
|
|
|
|
|
|
|
elif args.command == "delete":
|
|
|
|
|
_client.request("DELETE", f"/api/posts/{args.post_id}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
main()
|