Fix Slack API calls that require form-urlencoded encoding (#7)
Some checks are pending
Deploy / deploy (push) Waiting to run

conversations.members, conversations.open, and users.info reject
JSON body with 'missing required field'. Use form-urlencoded for
these methods while keeping JSON for chat.postMessage and
files.upload which require it for structured blocks/payloads.
This commit is contained in:
Adam Moussa 2026-05-12 20:05:48 -04:00 • committed by GitHub
parent 135c6be6f7
commit 11ea599bbd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,7 +1,8 @@
import json
import os
import urllib.request
import urllib.error
import urllib.parse
import urllib.request
from shared.secrets import get_secret, get_parameter
_token = None
@ -18,14 +19,19 @@ def _get_channel() -> str:
return get_parameter(os.environ["SLACK_CHANNEL_PARAM"])
def _api_call(method: str, payload: dict) -> dict:
data = json.dumps(payload).encode()
def _api_call(method: str, payload: dict, use_json: bool = True) -> dict:
if use_json:
data = json.dumps(payload).encode()
content_type = "application/json; charset=utf-8"
else:
data = urllib.parse.urlencode(payload).encode()
content_type = "application/x-www-form-urlencoded"
req = urllib.request.Request(
f"https://slack.com/api/{method}",
data=data,
headers={
"Authorization": f"Bearer {_get_token()}",
"Content-Type": "application/json",
"Content-Type": content_type,
},
)
with urllib.request.urlopen(req) as resp:
@ -40,7 +46,7 @@ def post_channel_message(text: str, blocks: list[dict] | None = None):
def send_dm(user_id: str, text: str, blocks: list[dict] | None = None):
open_resp = _api_call("conversations.open", {"users": user_id})
open_resp = _api_call("conversations.open", {"users": user_id}, use_json=False)
if not open_resp.get("ok"):
return open_resp
channel = open_resp["channel"]["id"]
@ -69,7 +75,7 @@ def get_channel_members(channel_id: str) -> list[str]:
payload = {"channel": channel_id, "limit": 200}
if cursor:
payload["cursor"] = cursor
resp = _api_call("conversations.members", payload)
resp = _api_call("conversations.members", payload, use_json=False)
if not resp.get("ok"):
break
members.extend(resp.get("members", []))
@ -80,7 +86,7 @@ def get_channel_members(channel_id: str) -> list[str]:
def get_user_info(user_id: str) -> dict | None:
resp = _api_call("users.info", {"user": user_id})
resp = _api_call("users.info", {"user": user_id}, use_json=False)
if resp.get("ok"):
return resp["user"]
return None