diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 2c76b2f..b2503e9 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: 9620bfba-8df9-4d0e-8796-8423b39f97f0 management: - docChecksum: ed2fd953cba3e99fb81365252925a0d4 + docChecksum: d6bce8a263f0ec11d54bdf026957ba2f docVersion: 1.1.0 speakeasyVersion: internal generationVersion: internal - releaseVersion: 2.2.0 - configChecksum: da63d9409ef6e27083aab8b1d6def56f + releaseVersion: 2.3.0 + configChecksum: 7d03dc7ad5513ecf24cd3879ea525e09 repoURL: https://github.com/moderation-api/sdk-python installationURL: https://github.com/moderation-api/sdk-python.git published: true @@ -72,6 +72,12 @@ trackedFiles: last_write_checksum: sha1:194bc3084d569fc2bb26899942dee223ea69fc41 docs/models/alcohol.md: last_write_checksum: sha1:4d9eade3ffde7dc311481a156704ee4dc52715bd + docs/models/allowcontentrequest.md: + last_write_checksum: sha1:e1acbe5ac42e39a2464b487835142097f3dab19e + docs/models/allowcontentrequestbody.md: + last_write_checksum: sha1:403636697fbd91486377be9110f1b2f735358d75 + docs/models/allowcontentresponse.md: + last_write_checksum: sha1:20e3c8189cf6b66d216b585d2896f2ca30dfe16e docs/models/audiorequest.md: last_write_checksum: sha1:c66c1f8a42e100aaa611130ab915647e54cdccf4 docs/models/audioresponse.md: @@ -84,6 +90,12 @@ trackedFiles: last_write_checksum: sha1:c04f6b8cc50257203e9df45a36f95f86a8d6f270 docs/models/block.md: last_write_checksum: sha1:a59f8f13228667d39879853ad05332c707c0afc8 + docs/models/blockauthorrequest.md: + last_write_checksum: sha1:bf88e48b05d14bcad8da391fd3700ddf580133be + docs/models/blockauthorrequestbody.md: + last_write_checksum: sha1:35c9dbe84e97ec2898508b1e0d1988e5faa5eb6c + docs/models/blockauthorresponse.md: + last_write_checksum: sha1:9255e9512d056dbd020bbaad505ef7a6176492b2 docs/models/bucket.md: last_write_checksum: sha1:df24d99e697de42164d0769adff95be2eda03e8c docs/models/cannabis.md: @@ -241,7 +253,7 @@ trackedFiles: docs/models/executeactionrequest.md: last_write_checksum: sha1:0abecf77c13cb692445ccdfcea1b5959da107f0f docs/models/executeactionrequestbody.md: - last_write_checksum: sha1:0d3920ab521ccbdb6a396510bcc6e626ffd634b7 + last_write_checksum: sha1:85d6a7f9539c102d8a4fbd8532770e16450861b5 docs/models/executeactionresponse.md: last_write_checksum: sha1:0295450e86664ce938a9b7bb2050e1e06b768543 docs/models/extremism.md: @@ -552,6 +564,12 @@ trackedFiles: last_write_checksum: sha1:fba885e8add400d72b780c52abb91ffd8a5fe95f docs/models/recommendation.md: last_write_checksum: sha1:351c193d6cbdcebed4ce87ac40e10299dad0f979 + docs/models/rejectcontentrequest.md: + last_write_checksum: sha1:f17f79e318e47c3f65aa2604f9fdada1172d9582 + docs/models/rejectcontentrequestbody.md: + last_write_checksum: sha1:24e92cecc432025106378837155aad383c2bc688 + docs/models/rejectcontentresponse.md: + last_write_checksum: sha1:d40ccad4daf2640f62678ce50b154a029d225b6d docs/models/religion.md: last_write_checksum: sha1:5759f26a6aa19140b1595347d3284cfd22fa7a27 docs/models/removewordlistwordsrequest.md: @@ -634,6 +652,12 @@ trackedFiles: last_write_checksum: sha1:442e8d07c3a40bb6189ee3c5b535e3b374010f3f docs/models/submitcontenttrustlevel.md: last_write_checksum: sha1:05eb0efa74f798971e34f40eecf67eb9bfe9e9c3 + docs/models/suspendauthorrequest.md: + last_write_checksum: sha1:b38150d96529a0523edadc9d49dac4c95340b9a8 + docs/models/suspendauthorrequestbody.md: + last_write_checksum: sha1:5992448c11bfcfede8f856bf16eb8ce7e9584d46 + docs/models/suspendauthorresponse.md: + last_write_checksum: sha1:becd4d4a2d16dd8bfee2639f2b9bed2430cc01ff docs/models/textrequest.md: last_write_checksum: sha1:4529f2616ee38260d041098b726352fc28bfad4f docs/models/textresponse.md: @@ -656,6 +680,12 @@ trackedFiles: last_write_checksum: sha1:9a8f87757f57244dc70008c44a580a323dd80c1a docs/models/trustlevel.md: last_write_checksum: sha1:59c7fab1ac94b8a21cebb6f15e753672b4ac8f1f + docs/models/unblockauthorrequest.md: + last_write_checksum: sha1:12316c78bd81399b088b82aaefebb416e8d9317c + docs/models/unblockauthorrequestbody.md: + last_write_checksum: sha1:491870352640b13418fbb9b53a47284de2bc71d4 + docs/models/unblockauthorresponse.md: + last_write_checksum: sha1:d011cfdf60105b021cc8a5a07656c0f1b228d502 docs/models/unicodespoofing.md: last_write_checksum: sha1:f226ab0193558bada5d79ae06526d468409f932e docs/models/unresolvequeueitemrequest.md: @@ -749,17 +779,17 @@ trackedFiles: docs/sdks/account/README.md: last_write_checksum: sha1:c32364abb6cabbbee7f5bf82fe310cacd7413f8e docs/sdks/actions/README.md: - last_write_checksum: sha1:07376377faa14d3c68ca073e3022836a766a1c29 + last_write_checksum: sha1:89df32db9f98a933b1b656125c592b7100bb5b53 docs/sdks/analytics/README.md: last_write_checksum: sha1:b9e0da42f3bf64aae7181769cd178a301b735833 docs/sdks/apikeys/README.md: last_write_checksum: sha1:7c2084b4693e79cbe12a987e1c524e7d6802fb0c docs/sdks/authors/README.md: - last_write_checksum: sha1:b5fad9c672b593e40cb528ab2b433df39c46d381 + last_write_checksum: sha1:61f22d9141f136d08255b9125f79d1f85ed399e4 docs/sdks/channels/README.md: last_write_checksum: sha1:01c0e51bc630e4f5cb937e39faf535e894547fd3 docs/sdks/contentsdk/README.md: - last_write_checksum: sha1:ae7567227195c2042169e7821e2dec64c311bebe + last_write_checksum: sha1:620ee485059acf28c3f0aa6494465e677bcd220f docs/sdks/feedback/README.md: last_write_checksum: sha1:ccbebb9f1e1102d390b4dbf114a5a4f783ef0abd docs/sdks/items/README.md: @@ -781,7 +811,7 @@ trackedFiles: pylintrc: last_write_checksum: sha1:cb40e5fd2885dcf20f7c572a590b2656efe282a0 pyproject.toml: - last_write_checksum: sha1:d22ee36bb66dd2ff46a523fdf3a7ab3ec9d19fe0 + last_write_checksum: sha1:1e60e4220ba83b27bcc713c1decc4f8afa66a682 scripts/prepare_readme.py: last_write_checksum: sha1:7b330dc0eb57c916a1158fd90c6227f8dc517c83 scripts/publish.sh: @@ -795,23 +825,23 @@ trackedFiles: src/moderation_api/_hooks/types.py: last_write_checksum: sha1:bb2a67c388c536a910bd205bd9582065c5d2de39 src/moderation_api/_version.py: - last_write_checksum: sha1:b53e0176440b60608a08fc1969b89e3be0c31739 + last_write_checksum: sha1:d6a55674cb763ada777bc63efed80be0caf384d9 src/moderation_api/account.py: last_write_checksum: sha1:184d7da98d57398f23b83a572d3105e361ba430f src/moderation_api/actions.py: - last_write_checksum: sha1:857f21700842ddcf2db17d4636ea07911312c080 + last_write_checksum: sha1:bd53c19de12cb21c3df0b14d054516a02ce75107 src/moderation_api/analytics.py: last_write_checksum: sha1:e943d3f3a63389f916542a9149ae9b199ac77aaa src/moderation_api/apikeys.py: last_write_checksum: sha1:c8a66456925ce3c5837af354536f49485fd71967 src/moderation_api/authors.py: - last_write_checksum: sha1:069689daa8a72d5f5b19cb6abfe6ce4937e4eaa1 + last_write_checksum: sha1:a5b4534344df6807fbcc4a554a0848c25c3a93fa src/moderation_api/basesdk.py: last_write_checksum: sha1:026fbd5780e5d5c70d00c0e8503e124ce2cf9779 src/moderation_api/channels.py: last_write_checksum: sha1:427f7ba3e717e4cdadbff8bca70a602c9a2a9c81 src/moderation_api/content_sdk.py: - last_write_checksum: sha1:5aa0a894d0ee19d44a783a38b6778e3709c333ac + last_write_checksum: sha1:248ea437a26352455ced96ea4d7d532da3634a51 src/moderation_api/errors/__init__.py: last_write_checksum: sha1:043e566785713d1aee1f2709cf3083cb51df01f6 src/moderation_api/errors/authenticationerror.py: @@ -843,13 +873,17 @@ trackedFiles: src/moderation_api/items.py: last_write_checksum: sha1:ea935d11d6bb0b939b051752b76a99101eae16d0 src/moderation_api/models/__init__.py: - last_write_checksum: sha1:4f26f94e991f1a48603551e4c7627628febd5cbd + last_write_checksum: sha1:ff7e6ce34a5955018fba5e858e24bca2d04891bb src/moderation_api/models/addwordlistwordsop.py: last_write_checksum: sha1:45d3dd92a286fa5b17f4eb79b5ed12062d019f4d + src/moderation_api/models/allowcontentop.py: + last_write_checksum: sha1:d0bdc545268bdf609ecda0560afc62ed14c138b5 src/moderation_api/models/authenticationerror.py: last_write_checksum: sha1:63c299ddbc05b97c083d497836594c1619815fab src/moderation_api/models/badrequesterror.py: last_write_checksum: sha1:c259e6e34c6c5d53f479ee4ae1125d49441d001a + src/moderation_api/models/blockauthorop.py: + last_write_checksum: sha1:9b7944496400ce5bcab28db6c029e2dd5c3492d0 src/moderation_api/models/channel.py: last_write_checksum: sha1:3f3a27e1b1c4d719244f22748c0af2b043729b27 src/moderation_api/models/conflicterror.py: @@ -887,7 +921,7 @@ trackedFiles: src/moderation_api/models/errorissue.py: last_write_checksum: sha1:12ac40f4f3533dad0cb604a67f2f70e6b07254f0 src/moderation_api/models/executeactionop.py: - last_write_checksum: sha1:a9333bbe8bb479afc965f2472ce055d02760cfeb + last_write_checksum: sha1:2a76f0555a89f2531e4c6e811c654a57ebf1698d src/moderation_api/models/getaccountop.py: last_write_checksum: sha1:d71cab397b15d4514f7c585fe89669cfc815a75b src/moderation_api/models/getactionop.py: @@ -962,6 +996,8 @@ trackedFiles: last_write_checksum: sha1:f0499600ece3ef0b74a2d4a73d20b665a32793b7 src/moderation_api/models/ratelimiterror.py: last_write_checksum: sha1:0e2a9611cd0b938fcdcab514d2f667fb6286bfe1 + src/moderation_api/models/rejectcontentop.py: + last_write_checksum: sha1:570991ad9f3bde1a39f0b2cbec4ada287dc3f835 src/moderation_api/models/removewordlistwordsop.py: last_write_checksum: sha1:7cb9e8a08223096df7ffece80ff363b0208a56fe src/moderation_api/models/resolvequeueitemop.py: @@ -972,6 +1008,10 @@ trackedFiles: last_write_checksum: sha1:dc71db919301e2ed408358e7b2066a8cb30c581b src/moderation_api/models/submitcontentop.py: last_write_checksum: sha1:c5ab5a0c1f431ef17bba685a3b70ce1a3434bb77 + src/moderation_api/models/suspendauthorop.py: + last_write_checksum: sha1:16ac1063324d990bb67359ec71ef772f5673db2c + src/moderation_api/models/unblockauthorop.py: + last_write_checksum: sha1:06364d4cb648bb8729583e07a789ace9b16af7fa src/moderation_api/models/unresolvequeueitemop.py: last_write_checksum: sha1:90f2dd46899295dc1849fb3a31039b76cebc0c2c src/moderation_api/models/updateactionop.py: @@ -993,7 +1033,7 @@ trackedFiles: src/moderation_api/queue_sdk.py: last_write_checksum: sha1:feca1dbd8b00911ac6b83221a115e030d8f0a57c src/moderation_api/sdk.py: - last_write_checksum: sha1:3a1d4d29e2c54908fac0d6ebed40ae54790c1277 + last_write_checksum: sha1:5c29cebee780498f511074216b3cb6178b57c276 src/moderation_api/sdkconfiguration.py: last_write_checksum: sha1:80f7a8dc676b19a1c1a145d30be50f52e6a92672 src/moderation_api/types/__init__.py: @@ -2007,4 +2047,94 @@ examples: application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://impractical-bin.info/"} "429": application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://damaged-bandwidth.name"} + blockAuthor: + speakeasy-default-block-author: + parameters: + path: + id: "" + requestBody: + application/json: {} + responses: + "200": + application/json: {"success": false} + "400": + application/json: {"type": "invalid_request_error", "code": "invalid_request", "message": "Invalid input data", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://mammoth-appliance.org/"} + "401": + application/json: {"type": "authentication_error", "code": "unauthorized", "message": "Authorization not provided", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://clumsy-ectoderm.com/"} + "404": + application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://square-custody.com"} + "429": + application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://mysterious-dime.name/"} + suspendAuthor: + speakeasy-default-suspend-author: + parameters: + path: + id: "" + requestBody: + application/json: {} + responses: + "200": + application/json: {"success": true} + "400": + application/json: {"type": "invalid_request_error", "code": "invalid_request", "message": "Invalid input data", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://cluttered-hubris.name/"} + "401": + application/json: {"type": "authentication_error", "code": "unauthorized", "message": "Authorization not provided", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://far-off-farm.net/"} + "404": + application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://scented-farmer.info"} + "429": + application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://miserly-cuckoo.org/"} + unblockAuthor: + speakeasy-default-unblock-author: + parameters: + path: + id: "" + requestBody: + application/json: {} + responses: + "200": + application/json: {"success": false} + "400": + application/json: {"type": "invalid_request_error", "code": "invalid_request", "message": "Invalid input data", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://utter-cornet.org"} + "401": + application/json: {"type": "authentication_error", "code": "unauthorized", "message": "Authorization not provided", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://oddball-bathhouse.biz/"} + "404": + application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://apprehensive-fisherman.info/"} + "429": + application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://unhappy-simple.net/"} + rejectContent: + speakeasy-default-reject-content: + parameters: + path: + id: "" + requestBody: + application/json: {} + responses: + "200": + application/json: {"success": true} + "400": + application/json: {"type": "invalid_request_error", "code": "invalid_request", "message": "Invalid input data", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://expert-pasta.com"} + "401": + application/json: {"type": "authentication_error", "code": "unauthorized", "message": "Authorization not provided", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://vibrant-adaptation.name"} + "404": + application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://boiling-gym.com/"} + "429": + application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://spanish-backburn.net"} + allowContent: + speakeasy-default-allow-content: + parameters: + path: + id: "" + requestBody: + application/json: {} + responses: + "200": + application/json: {"success": true} + "400": + application/json: {"type": "invalid_request_error", "code": "invalid_request", "message": "Invalid input data", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://earnest-fishery.com"} + "401": + application/json: {"type": "authentication_error", "code": "unauthorized", "message": "Authorization not provided", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://meager-climb.biz/"} + "404": + application/json: {"type": "not_found_error", "code": "resource_not_found", "message": "Not found", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://confused-bell.org"} + "429": + application/json: {"type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Rate limit exceeded", "request_id": "h8fkz6kkzoa446ffve37atys", "doc_url": "https://nervous-partridge.org/"} examplesVersion: 1.0.2 diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index ddcef65..b23df5b 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -32,7 +32,7 @@ generation: generateNewTests: true skipResponseBodyAssertions: false python: - version: 2.2.0 + version: 2.3.0 additionalDependencies: dev: {} main: {} diff --git a/.speakeasy/openapi.json b/.speakeasy/openapi.json index cabb255..9a2cf7e 100644 --- a/.speakeasy/openapi.json +++ b/.speakeasy/openapi.json @@ -5103,6 +5103,14 @@ "description": "Optional duration in milliseconds for actions with timeouts", "type": "number", "minimum": 0 + }, + "moderator": { + "description": "The user ID or email of the organization member who made the decision. The action is recorded as theirs.", + "type": "string" + }, + "createCasebookCase": { + "description": "Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.", + "type": "boolean" } }, "required": [ @@ -5342,6 +5350,672 @@ "x-speakeasy-ignore": true } }, + "/content/{id}/reject": { + "post": { + "operationId": "rejectContent", + "summary": "Reject content", + "description": "Reject a content item with the built-in reject action, and resolve it in the review queue.", + "tags": [ + "Content" + ], + "security": [ + { + "Authorization": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string", + "description": "The content ID you sent when you submitted the content, or the ID Moderation API assigned." + }, + "required": true, + "description": "The content ID you sent when you submitted the content, or the ID Moderation API assigned." + }, + { + "in": "header", + "name": "Project-Id", + "required": false, + "schema": { + "type": "string" + }, + "description": "The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.", + "x-speakeasy-name-override": "projectId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "reason": { + "description": "Why the action was taken. Saved with the action and sent in the webhook event.", + "type": "string" + }, + "queueId": { + "description": "The queue the content is reviewed in. Defaults to the project's default queue.", + "type": "string" + }, + "moderator": { + "description": "The user ID or email of the organization member who made the decision. The action is recorded as theirs.", + "type": "string" + }, + "createCasebookCase": { + "description": "Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.", + "type": "boolean" + } + } + }, + "example": { + "reason": "Spam" + } + } + } + }, + "responses": { + "200": { + "description": "Action executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the action was executed successfully" + } + }, + "required": [ + "success" + ], + "additionalProperties": false, + "description": "Execution result" + } + } + } + }, + "400": { + "description": "Invalid input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "401": { + "description": "Authorization not provided", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + }, + "429": { + "description": "Too many requests. Retry after the number of seconds in the `Retry-After` header.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RateLimitError" + } + } + } + } + }, + "x-speakeasy-group": "content", + "x-speakeasy-name-override": "reject", + "x-speakeasy-mcp": { + "title": "Reject content", + "scopes": [ + "destructive" + ], + "readOnlyHint": false, + "destructiveHint": true + } + } + }, + "/content/{id}/allow": { + "post": { + "operationId": "allowContent", + "summary": "Allow content", + "description": "Allow a content item with the built-in allow action, and resolve it in the review queue.", + "tags": [ + "Content" + ], + "security": [ + { + "Authorization": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string", + "description": "The content ID you sent when you submitted the content, or the ID Moderation API assigned." + }, + "required": true, + "description": "The content ID you sent when you submitted the content, or the ID Moderation API assigned." + }, + { + "in": "header", + "name": "Project-Id", + "required": false, + "schema": { + "type": "string" + }, + "description": "The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.", + "x-speakeasy-name-override": "projectId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "reason": { + "description": "Why the action was taken. Saved with the action and sent in the webhook event.", + "type": "string" + }, + "queueId": { + "description": "The queue the content is reviewed in. Defaults to the project's default queue.", + "type": "string" + }, + "moderator": { + "description": "The user ID or email of the organization member who made the decision. The action is recorded as theirs.", + "type": "string" + }, + "createCasebookCase": { + "description": "Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.", + "type": "boolean" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Action executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the action was executed successfully" + } + }, + "required": [ + "success" + ], + "additionalProperties": false, + "description": "Execution result" + } + } + } + }, + "400": { + "description": "Invalid input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "401": { + "description": "Authorization not provided", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + }, + "429": { + "description": "Too many requests. Retry after the number of seconds in the `Retry-After` header.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RateLimitError" + } + } + } + } + }, + "x-speakeasy-group": "content", + "x-speakeasy-name-override": "allow", + "x-speakeasy-mcp": { + "title": "Allow content", + "scopes": [ + "write" + ], + "readOnlyHint": false, + "destructiveHint": false + } + } + }, + "/authors/{id}/block": { + "post": { + "operationId": "blockAuthor", + "summary": "Block author", + "description": "Block an author with the built-in block action. A blocked author cannot post new content until unblocked.", + "tags": [ + "Authors" + ], + "security": [ + { + "Authorization": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string", + "description": "Either external ID or the ID assigned by moderation API." + }, + "required": true, + "description": "Either external ID or the ID assigned by moderation API." + }, + { + "in": "header", + "name": "Project-Id", + "required": false, + "schema": { + "type": "string" + }, + "description": "The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.", + "x-speakeasy-name-override": "projectId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "reason": { + "description": "Why the action was taken. Saved with the action and sent in the webhook event.", + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Action executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the action was executed successfully" + } + }, + "required": [ + "success" + ], + "additionalProperties": false, + "description": "Execution result" + } + } + } + }, + "400": { + "description": "Invalid input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "401": { + "description": "Authorization not provided", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + }, + "429": { + "description": "Too many requests. Retry after the number of seconds in the `Retry-After` header.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RateLimitError" + } + } + } + } + }, + "x-speakeasy-group": "authors", + "x-speakeasy-name-override": "block", + "x-speakeasy-mcp": { + "title": "Block author", + "scopes": [ + "destructive" + ], + "readOnlyHint": false, + "destructiveHint": true + } + } + }, + "/authors/{id}/suspend": { + "post": { + "operationId": "suspendAuthor", + "summary": "Suspend author", + "description": "Block an author for a limited time with the built-in suspend action.", + "tags": [ + "Authors" + ], + "security": [ + { + "Authorization": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string", + "description": "Either external ID or the ID assigned by moderation API." + }, + "required": true, + "description": "Either external ID or the ID assigned by moderation API." + }, + { + "in": "header", + "name": "Project-Id", + "required": false, + "schema": { + "type": "string" + }, + "description": "The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.", + "x-speakeasy-name-override": "projectId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "reason": { + "description": "Why the action was taken. Saved with the action and sent in the webhook event.", + "type": "string" + }, + "duration": { + "description": "How long the suspension lasts, in milliseconds. Defaults to 24 hours.", + "type": "number", + "minimum": 0 + } + } + }, + "example": { + "reason": "Violation of community guidelines", + "duration": 604800000 + } + } + } + }, + "responses": { + "200": { + "description": "Action executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the action was executed successfully" + } + }, + "required": [ + "success" + ], + "additionalProperties": false, + "description": "Execution result" + } + } + } + }, + "400": { + "description": "Invalid input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "401": { + "description": "Authorization not provided", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + }, + "429": { + "description": "Too many requests. Retry after the number of seconds in the `Retry-After` header.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RateLimitError" + } + } + } + } + }, + "x-speakeasy-group": "authors", + "x-speakeasy-name-override": "suspend", + "x-speakeasy-mcp": { + "title": "Suspend author", + "scopes": [ + "destructive" + ], + "readOnlyHint": false, + "destructiveHint": true + } + } + }, + "/authors/{id}/unblock": { + "post": { + "operationId": "unblockAuthor", + "summary": "Unblock author", + "description": "Unblock a blocked or suspended author with the built-in unblock action, so they can post new content again.", + "tags": [ + "Authors" + ], + "security": [ + { + "Authorization": [] + } + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string", + "description": "Either external ID or the ID assigned by moderation API." + }, + "required": true, + "description": "Either external ID or the ID assigned by moderation API." + }, + { + "in": "header", + "name": "Project-Id", + "required": false, + "schema": { + "type": "string" + }, + "description": "The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.", + "x-speakeasy-name-override": "projectId" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "reason": { + "description": "Why the action was taken. Saved with the action and sent in the webhook event.", + "type": "string" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Action executed successfully", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the action was executed successfully" + } + }, + "required": [ + "success" + ], + "additionalProperties": false, + "description": "Execution result" + } + } + } + }, + "400": { + "description": "Invalid input data", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BadRequestError" + } + } + } + }, + "401": { + "description": "Authorization not provided", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationError" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotFoundError" + } + } + } + }, + "429": { + "description": "Too many requests. Retry after the number of seconds in the `Retry-After` header.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RateLimitError" + } + } + } + } + }, + "x-speakeasy-group": "authors", + "x-speakeasy-name-override": "unblock", + "x-speakeasy-mcp": { + "title": "Unblock author", + "scopes": [ + "write" + ], + "readOnlyHint": false, + "destructiveHint": false + } + } + }, "/webhooks": { "get": { "operationId": "listWebhooks", diff --git a/CHANGELOG.md b/CHANGELOG.md index b265fa4..3757ff2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## 2.3.0 (2026-10-28) + +Full Changelog: [v2.2.0...v2.3.0](https://github.com/moderation-api/sdk-python/compare/v2.2.0...v2.3.0) + +### API changes + +- `POST /actions/execute`: added the new optional request property `createCasebookCase` +- `POST /actions/execute`: added the new optional request property `moderator` +- `POST /authors/{id}/block`: endpoint added +- `POST /authors/{id}/suspend`: endpoint added +- `POST /authors/{id}/unblock`: endpoint added +- `POST /content/{id}/allow`: endpoint added +- `POST /content/{id}/reject`: endpoint added + ## 2.2.0 (2026-10-26) Full Changelog: [v2.1.1...v2.2.0](https://github.com/moderation-api/sdk-python/compare/v2.1.1...v2.2.0) diff --git a/README.md b/README.md index fa4341c..f5fc557 100644 --- a/README.md +++ b/README.md @@ -367,6 +367,9 @@ Create the organization client only where you manage projects and channels, for * [retrieve](docs/sdks/authors/README.md#retrieve) - Get author details * [update](docs/sdks/authors/README.md#update) - Update author details * [delete](docs/sdks/authors/README.md#delete) - Delete an author +* [block](docs/sdks/authors/README.md#block) - Block author +* [suspend](docs/sdks/authors/README.md#suspend) - Suspend author +* [unblock](docs/sdks/authors/README.md#unblock) - Unblock author ### [Channels](docs/sdks/channels/README.md) @@ -379,6 +382,8 @@ Create the organization client only where you manage projects and channels, for ### [Content](docs/sdks/contentsdk/README.md) +* [reject](docs/sdks/contentsdk/README.md#reject) - Reject content +* [allow](docs/sdks/contentsdk/README.md#allow) - Allow content * [submit](docs/sdks/contentsdk/README.md#submit) - Submit content ### [Feedback](docs/sdks/feedback/README.md) @@ -578,10 +583,10 @@ with ModerationAPI( **Inherit from [`ModerationAPIError`](./src/moderation_api/errors/moderationapierror.py)**: -* [`NotFoundError`](./src/moderation_api/errors/notfounderror.py): The resource does not exist or the key cannot see it. Status code `404`. Applicable to 39 of 53 methods.* -* [`PermissionDeniedError`](./src/moderation_api/errors/permissiondeniederror.py): The API key cannot do this, or the plan limit for this resource is reached. Status code `403`. Applicable to 36 of 53 methods.* -* [`InternalServerError`](./src/moderation_api/errors/internalservererror.py): Something went wrong on our side. Retry with backoff. Status code `500`. Applicable to 23 of 53 methods.* -* [`ConflictError`](./src/moderation_api/errors/conflicterror.py): The request conflicts with the current state of a resource. Status code `409`. Applicable to 2 of 53 methods.* +* [`NotFoundError`](./src/moderation_api/errors/notfounderror.py): The resource does not exist or the key cannot see it. Status code `404`. Applicable to 44 of 58 methods.* +* [`PermissionDeniedError`](./src/moderation_api/errors/permissiondeniederror.py): The API key cannot do this, or the plan limit for this resource is reached. Status code `403`. Applicable to 36 of 58 methods.* +* [`InternalServerError`](./src/moderation_api/errors/internalservererror.py): Something went wrong on our side. Retry with backoff. Status code `500`. Applicable to 23 of 58 methods.* +* [`ConflictError`](./src/moderation_api/errors/conflicterror.py): The request conflicts with the current state of a resource. Status code `409`. Applicable to 2 of 58 methods.* * [`ResponseValidationError`](./src/moderation_api/errors/responsevalidationerror.py): Type mismatch between the response data and the expected Pydantic model. Provides access to the Pydantic validation error via the `cause` attribute. diff --git a/docs/models/allowcontentrequest.md b/docs/models/allowcontentrequest.md new file mode 100644 index 0000000..016c902 --- /dev/null +++ b/docs/models/allowcontentrequest.md @@ -0,0 +1,10 @@ +# AllowContentRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | The content ID you sent when you submitted the content, or the ID Moderation API assigned. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `body` | [models.AllowContentRequestBody](../models/allowcontentrequestbody.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/models/allowcontentrequestbody.md b/docs/models/allowcontentrequestbody.md new file mode 100644 index 0000000..7fe2494 --- /dev/null +++ b/docs/models/allowcontentrequestbody.md @@ -0,0 +1,11 @@ +# AllowContentRequestBody + + +## Fields + +| Field | Type | Required | Description | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `queue_id` | *Optional[str]* | :heavy_minus_sign: | The queue the content is reviewed in. Defaults to the project's default queue. | +| `moderator` | *Optional[str]* | :heavy_minus_sign: | The user ID or email of the organization member who made the decision. The action is recorded as theirs. | +| `create_casebook_case` | *Optional[bool]* | :heavy_minus_sign: | Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. | \ No newline at end of file diff --git a/docs/models/allowcontentresponse.md b/docs/models/allowcontentresponse.md new file mode 100644 index 0000000..03d0cb3 --- /dev/null +++ b/docs/models/allowcontentresponse.md @@ -0,0 +1,10 @@ +# AllowContentResponse + +Execution result + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `success` | *bool* | :heavy_check_mark: | Whether the action was executed successfully | \ No newline at end of file diff --git a/docs/models/blockauthorrequest.md b/docs/models/blockauthorrequest.md new file mode 100644 index 0000000..fff036d --- /dev/null +++ b/docs/models/blockauthorrequest.md @@ -0,0 +1,10 @@ +# BlockAuthorRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Either external ID or the ID assigned by moderation API. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `body` | [models.BlockAuthorRequestBody](../models/blockauthorrequestbody.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/models/blockauthorrequestbody.md b/docs/models/blockauthorrequestbody.md new file mode 100644 index 0000000..0024307 --- /dev/null +++ b/docs/models/blockauthorrequestbody.md @@ -0,0 +1,8 @@ +# BlockAuthorRequestBody + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | \ No newline at end of file diff --git a/docs/models/blockauthorresponse.md b/docs/models/blockauthorresponse.md new file mode 100644 index 0000000..420378f --- /dev/null +++ b/docs/models/blockauthorresponse.md @@ -0,0 +1,10 @@ +# BlockAuthorResponse + +Execution result + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `success` | *bool* | :heavy_check_mark: | Whether the action was executed successfully | \ No newline at end of file diff --git a/docs/models/executeactionrequestbody.md b/docs/models/executeactionrequestbody.md index f95f87a..e29e339 100644 --- a/docs/models/executeactionrequestbody.md +++ b/docs/models/executeactionrequestbody.md @@ -5,11 +5,13 @@ Input parameters ## Fields -| Field | Type | Required | Description | -| --------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------- | -| `action_key` | *str* | :heavy_check_mark: | ID or key of the action to execute | -| `content_ids` | List[*str*] | :heavy_minus_sign: | IDs of the content items to apply the action to. Provide this or authorIds. | -| `author_ids` | List[*str*] | :heavy_minus_sign: | IDs of the authors to apply the action to. Provide this or contentIds. | -| `value` | *Optional[str]* | :heavy_minus_sign: | Optional value to provide with the action | -| `queue_id` | *Optional[str]* | :heavy_minus_sign: | Optional queue ID if the action is queue-specific | -| `duration` | *Optional[float]* | :heavy_minus_sign: | Optional duration in milliseconds for actions with timeouts | \ No newline at end of file +| Field | Type | Required | Description | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `action_key` | *str* | :heavy_check_mark: | ID or key of the action to execute | +| `content_ids` | List[*str*] | :heavy_minus_sign: | IDs of the content items to apply the action to. Provide this or authorIds. | +| `author_ids` | List[*str*] | :heavy_minus_sign: | IDs of the authors to apply the action to. Provide this or contentIds. | +| `value` | *Optional[str]* | :heavy_minus_sign: | Optional value to provide with the action | +| `queue_id` | *Optional[str]* | :heavy_minus_sign: | Optional queue ID if the action is queue-specific | +| `duration` | *Optional[float]* | :heavy_minus_sign: | Optional duration in milliseconds for actions with timeouts | +| `moderator` | *Optional[str]* | :heavy_minus_sign: | The user ID or email of the organization member who made the decision. The action is recorded as theirs. | +| `create_casebook_case` | *Optional[bool]* | :heavy_minus_sign: | Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. | \ No newline at end of file diff --git a/docs/models/rejectcontentrequest.md b/docs/models/rejectcontentrequest.md new file mode 100644 index 0000000..a7931f7 --- /dev/null +++ b/docs/models/rejectcontentrequest.md @@ -0,0 +1,10 @@ +# RejectContentRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | The content ID you sent when you submitted the content, or the ID Moderation API assigned. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `body` | [models.RejectContentRequestBody](../models/rejectcontentrequestbody.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/models/rejectcontentrequestbody.md b/docs/models/rejectcontentrequestbody.md new file mode 100644 index 0000000..41e1706 --- /dev/null +++ b/docs/models/rejectcontentrequestbody.md @@ -0,0 +1,11 @@ +# RejectContentRequestBody + + +## Fields + +| Field | Type | Required | Description | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `queue_id` | *Optional[str]* | :heavy_minus_sign: | The queue the content is reviewed in. Defaults to the project's default queue. | +| `moderator` | *Optional[str]* | :heavy_minus_sign: | The user ID or email of the organization member who made the decision. The action is recorded as theirs. | +| `create_casebook_case` | *Optional[bool]* | :heavy_minus_sign: | Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. | \ No newline at end of file diff --git a/docs/models/rejectcontentresponse.md b/docs/models/rejectcontentresponse.md new file mode 100644 index 0000000..b48e4d1 --- /dev/null +++ b/docs/models/rejectcontentresponse.md @@ -0,0 +1,10 @@ +# RejectContentResponse + +Execution result + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `success` | *bool* | :heavy_check_mark: | Whether the action was executed successfully | \ No newline at end of file diff --git a/docs/models/suspendauthorrequest.md b/docs/models/suspendauthorrequest.md new file mode 100644 index 0000000..6d73cd7 --- /dev/null +++ b/docs/models/suspendauthorrequest.md @@ -0,0 +1,10 @@ +# SuspendAuthorRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Either external ID or the ID assigned by moderation API. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `body` | [models.SuspendAuthorRequestBody](../models/suspendauthorrequestbody.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/models/suspendauthorrequestbody.md b/docs/models/suspendauthorrequestbody.md new file mode 100644 index 0000000..07a831e --- /dev/null +++ b/docs/models/suspendauthorrequestbody.md @@ -0,0 +1,9 @@ +# SuspendAuthorRequestBody + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `duration` | *Optional[float]* | :heavy_minus_sign: | How long the suspension lasts, in milliseconds. Defaults to 24 hours. | \ No newline at end of file diff --git a/docs/models/suspendauthorresponse.md b/docs/models/suspendauthorresponse.md new file mode 100644 index 0000000..7485757 --- /dev/null +++ b/docs/models/suspendauthorresponse.md @@ -0,0 +1,10 @@ +# SuspendAuthorResponse + +Execution result + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `success` | *bool* | :heavy_check_mark: | Whether the action was executed successfully | \ No newline at end of file diff --git a/docs/models/unblockauthorrequest.md b/docs/models/unblockauthorrequest.md new file mode 100644 index 0000000..fe54d2a --- /dev/null +++ b/docs/models/unblockauthorrequest.md @@ -0,0 +1,10 @@ +# UnblockAuthorRequest + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Either external ID or the ID assigned by moderation API. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `body` | [models.UnblockAuthorRequestBody](../models/unblockauthorrequestbody.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/models/unblockauthorrequestbody.md b/docs/models/unblockauthorrequestbody.md new file mode 100644 index 0000000..849ffa7 --- /dev/null +++ b/docs/models/unblockauthorrequestbody.md @@ -0,0 +1,8 @@ +# UnblockAuthorRequestBody + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | \ No newline at end of file diff --git a/docs/models/unblockauthorresponse.md b/docs/models/unblockauthorresponse.md new file mode 100644 index 0000000..595c322 --- /dev/null +++ b/docs/models/unblockauthorresponse.md @@ -0,0 +1,10 @@ +# UnblockAuthorResponse + +Execution result + + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | -------------------------------------------- | +| `success` | *bool* | :heavy_check_mark: | Whether the action was executed successfully | \ No newline at end of file diff --git a/docs/sdks/actions/README.md b/docs/sdks/actions/README.md index d7ca661..b49ce1f 100644 --- a/docs/sdks/actions/README.md +++ b/docs/sdks/actions/README.md @@ -300,6 +300,8 @@ with ModerationAPI( | `value` | *Optional[str]* | :heavy_minus_sign: | Optional value to provide with the action | | `queue_id` | *Optional[str]* | :heavy_minus_sign: | Optional queue ID if the action is queue-specific | | `duration` | *Optional[float]* | :heavy_minus_sign: | Optional duration in milliseconds for actions with timeouts | +| `moderator` | *Optional[str]* | :heavy_minus_sign: | The user ID or email of the organization member who made the decision. The action is recorded as theirs. | +| `create_casebook_case` | *Optional[bool]* | :heavy_minus_sign: | Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. | | `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | ### Response diff --git a/docs/sdks/authors/README.md b/docs/sdks/authors/README.md index 7e13e97..2dbca21 100644 --- a/docs/sdks/authors/README.md +++ b/docs/sdks/authors/README.md @@ -9,6 +9,9 @@ * [retrieve](#retrieve) - Get author details * [update](#update) - Update author details * [delete](#delete) - Delete an author +* [block](#block) - Block author +* [suspend](#suspend) - Suspend author +* [unblock](#unblock) - Unblock author ## list @@ -266,4 +269,143 @@ with ModerationAPI( | errors.NotFoundError | 404 | application/json | | errors.RateLimitError | 429 | application/json | | errors.InternalServerError | 500 | application/json | +| errors.ModerationAPIDefaultError | 4XX, 5XX | \*/\* | + +## block + +Block an author with the built-in block action. A blocked author cannot post new content until unblocked. + +### Example Usage + + +```python +from moderation_api import ModerationAPI +import os + + +with ModerationAPI( + secret_key=os.getenv("MODAPI_SECRET_KEY", ""), +) as ma_client: + + res = ma_client.authors.block(id="") + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Either external ID or the ID assigned by moderation API. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.BlockAuthorResponse](../../models/blockauthorresponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------- | -------------------------------- | -------------------------------- | +| errors.BadRequestError | 400 | application/json | +| errors.AuthenticationError | 401 | application/json | +| errors.NotFoundError | 404 | application/json | +| errors.RateLimitError | 429 | application/json | +| errors.ModerationAPIDefaultError | 4XX, 5XX | \*/\* | + +## suspend + +Block an author for a limited time with the built-in suspend action. + +### Example Usage + + +```python +from moderation_api import ModerationAPI +import os + + +with ModerationAPI( + secret_key=os.getenv("MODAPI_SECRET_KEY", ""), +) as ma_client: + + res = ma_client.authors.suspend(id="", reason="Violation of community guidelines", duration=604800000.0) + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Either external ID or the ID assigned by moderation API. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `duration` | *Optional[float]* | :heavy_minus_sign: | How long the suspension lasts, in milliseconds. Defaults to 24 hours. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.SuspendAuthorResponse](../../models/suspendauthorresponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------- | -------------------------------- | -------------------------------- | +| errors.BadRequestError | 400 | application/json | +| errors.AuthenticationError | 401 | application/json | +| errors.NotFoundError | 404 | application/json | +| errors.RateLimitError | 429 | application/json | +| errors.ModerationAPIDefaultError | 4XX, 5XX | \*/\* | + +## unblock + +Unblock a blocked or suspended author with the built-in unblock action, so they can post new content again. + +### Example Usage + + +```python +from moderation_api import ModerationAPI +import os + + +with ModerationAPI( + secret_key=os.getenv("MODAPI_SECRET_KEY", ""), +) as ma_client: + + res = ma_client.authors.unblock(id="") + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | Either external ID or the ID assigned by moderation API. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.UnblockAuthorResponse](../../models/unblockauthorresponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------- | -------------------------------- | -------------------------------- | +| errors.BadRequestError | 400 | application/json | +| errors.AuthenticationError | 401 | application/json | +| errors.NotFoundError | 404 | application/json | +| errors.RateLimitError | 429 | application/json | | errors.ModerationAPIDefaultError | 4XX, 5XX | \*/\* | \ No newline at end of file diff --git a/docs/sdks/contentsdk/README.md b/docs/sdks/contentsdk/README.md index 1400bad..e18cb22 100644 --- a/docs/sdks/contentsdk/README.md +++ b/docs/sdks/contentsdk/README.md @@ -4,8 +4,108 @@ ### Available Operations +* [reject](#reject) - Reject content +* [allow](#allow) - Allow content * [submit](#submit) - Submit content +## reject + +Reject a content item with the built-in reject action, and resolve it in the review queue. + +### Example Usage + + +```python +from moderation_api import ModerationAPI +import os + + +with ModerationAPI( + secret_key=os.getenv("MODAPI_SECRET_KEY", ""), +) as ma_client: + + res = ma_client.content.reject(id="", reason="Spam") + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | The content ID you sent when you submitted the content, or the ID Moderation API assigned. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `queue_id` | *Optional[str]* | :heavy_minus_sign: | The queue the content is reviewed in. Defaults to the project's default queue. | +| `moderator` | *Optional[str]* | :heavy_minus_sign: | The user ID or email of the organization member who made the decision. The action is recorded as theirs. | +| `create_casebook_case` | *Optional[bool]* | :heavy_minus_sign: | Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.RejectContentResponse](../../models/rejectcontentresponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------- | -------------------------------- | -------------------------------- | +| errors.BadRequestError | 400 | application/json | +| errors.AuthenticationError | 401 | application/json | +| errors.NotFoundError | 404 | application/json | +| errors.RateLimitError | 429 | application/json | +| errors.ModerationAPIDefaultError | 4XX, 5XX | \*/\* | + +## allow + +Allow a content item with the built-in allow action, and resolve it in the review queue. + +### Example Usage + + +```python +from moderation_api import ModerationAPI +import os + + +with ModerationAPI( + secret_key=os.getenv("MODAPI_SECRET_KEY", ""), +) as ma_client: + + res = ma_client.content.allow(id="") + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | :heavy_check_mark: | The content ID you sent when you submitted the content, or the ID Moderation API assigned. | +| `project_id` | *Optional[str]* | :heavy_minus_sign: | The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. | +| `reason` | *Optional[str]* | :heavy_minus_sign: | Why the action was taken. Saved with the action and sent in the webhook event. | +| `queue_id` | *Optional[str]* | :heavy_minus_sign: | The queue the content is reviewed in. Defaults to the project's default queue. | +| `moderator` | *Optional[str]* | :heavy_minus_sign: | The user ID or email of the organization member who made the decision. The action is recorded as theirs. | +| `create_casebook_case` | *Optional[bool]* | :heavy_minus_sign: | Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.AllowContentResponse](../../models/allowcontentresponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| -------------------------------- | -------------------------------- | -------------------------------- | +| errors.BadRequestError | 400 | application/json | +| errors.AuthenticationError | 401 | application/json | +| errors.NotFoundError | 404 | application/json | +| errors.RateLimitError | 429 | application/json | +| errors.ModerationAPIDefaultError | 4XX, 5XX | \*/\* | + ## submit Submit content diff --git a/pyproject.toml b/pyproject.toml index 344d2e7..76e4b0f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "moderation_api" -version = "2.2.0" +version = "2.3.0" description = "The official Python library for the Moderation API" authors = [{ name = "Moderation API" },] readme = "README-PYPI.md" diff --git a/src/moderation_api/_version.py b/src/moderation_api/_version.py index ddddf70..0b01af1 100644 --- a/src/moderation_api/_version.py +++ b/src/moderation_api/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "moderation_api" -__version__: str = "2.2.0" +__version__: str = "2.3.0" __openapi_doc_version__: str = "1.1.0" __gen_version__: str = "internal" -__user_agent__: str = "speakeasy-sdk/python 2.2.0 internal 1.1.0 moderation_api" +__user_agent__: str = "speakeasy-sdk/python 2.3.0 internal 1.1.0 moderation_api" try: if __package__ is not None: diff --git a/src/moderation_api/actions.py b/src/moderation_api/actions.py index 278bc07..200e6ee 100644 --- a/src/moderation_api/actions.py +++ b/src/moderation_api/actions.py @@ -1426,6 +1426,8 @@ def execute( value: Optional[str] = None, queue_id: Optional[str] = None, duration: Optional[float] = None, + moderator: Optional[str] = None, + create_casebook_case: Optional[bool] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1442,6 +1444,8 @@ def execute( :param value: Optional value to provide with the action :param queue_id: Optional queue ID if the action is queue-specific :param duration: Optional duration in milliseconds for actions with timeouts + :param moderator: The user ID or email of the organization member who made the decision. The action is recorded as theirs. + :param create_casebook_case: Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -1466,6 +1470,8 @@ def execute( value=value, queue_id=queue_id, duration=duration, + moderator=moderator, + create_casebook_case=create_casebook_case, ), ) @@ -1556,6 +1562,8 @@ async def execute_async( value: Optional[str] = None, queue_id: Optional[str] = None, duration: Optional[float] = None, + moderator: Optional[str] = None, + create_casebook_case: Optional[bool] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1572,6 +1580,8 @@ async def execute_async( :param value: Optional value to provide with the action :param queue_id: Optional queue ID if the action is queue-specific :param duration: Optional duration in milliseconds for actions with timeouts + :param moderator: The user ID or email of the organization member who made the decision. The action is recorded as theirs. + :param create_casebook_case: Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -1596,6 +1606,8 @@ async def execute_async( value=value, queue_id=queue_id, duration=duration, + moderator=moderator, + create_casebook_case=create_casebook_case, ), ) diff --git a/src/moderation_api/authors.py b/src/moderation_api/authors.py index e2bf28b..0e8415a 100644 --- a/src/moderation_api/authors.py +++ b/src/moderation_api/authors.py @@ -1429,3 +1429,717 @@ async def delete_async( ) raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + def block( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.BlockAuthorResponse: + r"""Block author + + Block an author with the built-in block action. A blocked author cannot post new content until unblocked. + + :param id: Either external ID or the ID assigned by moderation API. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.BlockAuthorRequest( + id=id, + project_id=project_id, + body=models.BlockAuthorRequestBody( + reason=reason, + ), + ) + + req = self._build_request( + method="POST", + path="/authors/{id}/block", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.BlockAuthorRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="blockAuthor", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Authors"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.BlockAuthorResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + async def block_async( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.BlockAuthorResponse: + r"""Block author + + Block an author with the built-in block action. A blocked author cannot post new content until unblocked. + + :param id: Either external ID or the ID assigned by moderation API. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.BlockAuthorRequest( + id=id, + project_id=project_id, + body=models.BlockAuthorRequestBody( + reason=reason, + ), + ) + + req = self._build_request_async( + method="POST", + path="/authors/{id}/block", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.BlockAuthorRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="blockAuthor", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Authors"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.BlockAuthorResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + def suspend( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + duration: Optional[float] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.SuspendAuthorResponse: + r"""Suspend author + + Block an author for a limited time with the built-in suspend action. + + :param id: Either external ID or the ID assigned by moderation API. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param duration: How long the suspension lasts, in milliseconds. Defaults to 24 hours. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.SuspendAuthorRequest( + id=id, + project_id=project_id, + body=models.SuspendAuthorRequestBody( + reason=reason, + duration=duration, + ), + ) + + req = self._build_request( + method="POST", + path="/authors/{id}/suspend", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.SuspendAuthorRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="suspendAuthor", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Authors"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.SuspendAuthorResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + async def suspend_async( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + duration: Optional[float] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.SuspendAuthorResponse: + r"""Suspend author + + Block an author for a limited time with the built-in suspend action. + + :param id: Either external ID or the ID assigned by moderation API. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param duration: How long the suspension lasts, in milliseconds. Defaults to 24 hours. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.SuspendAuthorRequest( + id=id, + project_id=project_id, + body=models.SuspendAuthorRequestBody( + reason=reason, + duration=duration, + ), + ) + + req = self._build_request_async( + method="POST", + path="/authors/{id}/suspend", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.SuspendAuthorRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="suspendAuthor", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Authors"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.SuspendAuthorResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + def unblock( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.UnblockAuthorResponse: + r"""Unblock author + + Unblock a blocked or suspended author with the built-in unblock action, so they can post new content again. + + :param id: Either external ID or the ID assigned by moderation API. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.UnblockAuthorRequest( + id=id, + project_id=project_id, + body=models.UnblockAuthorRequestBody( + reason=reason, + ), + ) + + req = self._build_request( + method="POST", + path="/authors/{id}/unblock", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.UnblockAuthorRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="unblockAuthor", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Authors"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.UnblockAuthorResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + async def unblock_async( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.UnblockAuthorResponse: + r"""Unblock author + + Unblock a blocked or suspended author with the built-in unblock action, so they can post new content again. + + :param id: Either external ID or the ID assigned by moderation API. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.UnblockAuthorRequest( + id=id, + project_id=project_id, + body=models.UnblockAuthorRequestBody( + reason=reason, + ), + ) + + req = self._build_request_async( + method="POST", + path="/authors/{id}/unblock", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.UnblockAuthorRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="unblockAuthor", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Authors"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.UnblockAuthorResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) diff --git a/src/moderation_api/content_sdk.py b/src/moderation_api/content_sdk.py index 2e1a280..10c0d48 100644 --- a/src/moderation_api/content_sdk.py +++ b/src/moderation_api/content_sdk.py @@ -10,6 +10,514 @@ class ContentSDK(BaseSDK): + def reject( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + queue_id: Optional[str] = None, + moderator: Optional[str] = None, + create_casebook_case: Optional[bool] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.RejectContentResponse: + r"""Reject content + + Reject a content item with the built-in reject action, and resolve it in the review queue. + + :param id: The content ID you sent when you submitted the content, or the ID Moderation API assigned. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param queue_id: The queue the content is reviewed in. Defaults to the project's default queue. + :param moderator: The user ID or email of the organization member who made the decision. The action is recorded as theirs. + :param create_casebook_case: Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.RejectContentRequest( + id=id, + project_id=project_id, + body=models.RejectContentRequestBody( + reason=reason, + queue_id=queue_id, + moderator=moderator, + create_casebook_case=create_casebook_case, + ), + ) + + req = self._build_request( + method="POST", + path="/content/{id}/reject", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.RejectContentRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="rejectContent", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Content"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.RejectContentResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + async def reject_async( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + queue_id: Optional[str] = None, + moderator: Optional[str] = None, + create_casebook_case: Optional[bool] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.RejectContentResponse: + r"""Reject content + + Reject a content item with the built-in reject action, and resolve it in the review queue. + + :param id: The content ID you sent when you submitted the content, or the ID Moderation API assigned. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param queue_id: The queue the content is reviewed in. Defaults to the project's default queue. + :param moderator: The user ID or email of the organization member who made the decision. The action is recorded as theirs. + :param create_casebook_case: Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.RejectContentRequest( + id=id, + project_id=project_id, + body=models.RejectContentRequestBody( + reason=reason, + queue_id=queue_id, + moderator=moderator, + create_casebook_case=create_casebook_case, + ), + ) + + req = self._build_request_async( + method="POST", + path="/content/{id}/reject", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.RejectContentRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="rejectContent", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Content"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.RejectContentResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + def allow( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + queue_id: Optional[str] = None, + moderator: Optional[str] = None, + create_casebook_case: Optional[bool] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.AllowContentResponse: + r"""Allow content + + Allow a content item with the built-in allow action, and resolve it in the review queue. + + :param id: The content ID you sent when you submitted the content, or the ID Moderation API assigned. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param queue_id: The queue the content is reviewed in. Defaults to the project's default queue. + :param moderator: The user ID or email of the organization member who made the decision. The action is recorded as theirs. + :param create_casebook_case: Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.AllowContentRequest( + id=id, + project_id=project_id, + body=models.AllowContentRequestBody( + reason=reason, + queue_id=queue_id, + moderator=moderator, + create_casebook_case=create_casebook_case, + ), + ) + + req = self._build_request( + method="POST", + path="/content/{id}/allow", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.AllowContentRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="allowContent", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Content"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.AllowContentResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + + async def allow_async( + self, + *, + id: str, + project_id: Optional[str] = None, + reason: Optional[str] = None, + queue_id: Optional[str] = None, + moderator: Optional[str] = None, + create_casebook_case: Optional[bool] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.AllowContentResponse: + r"""Allow content + + Allow a content item with the built-in allow action, and resolve it in the review queue. + + :param id: The content ID you sent when you submitted the content, or the ID Moderation API assigned. + :param project_id: The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error. + :param reason: Why the action was taken. Saved with the action and sent in the webhook event. + :param queue_id: The queue the content is reviewed in. Defaults to the project's default queue. + :param moderator: The user ID or email of the organization member who made the decision. The action is recorded as theirs. + :param create_casebook_case: Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.AllowContentRequest( + id=id, + project_id=project_id, + body=models.AllowContentRequestBody( + reason=reason, + queue_id=queue_id, + moderator=moderator, + create_casebook_case=create_casebook_case, + ), + ) + + req = self._build_request_async( + method="POST", + path="/content/{id}/allow", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.body, False, False, "json", models.AllowContentRequestBody + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="allowContent", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Content"], + extensions=None, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + response_data: Any = None + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.AllowContentResponse, http_res) + if utils.match_response(http_res, "400", "application/json"): + response_data = unmarshal_json_response( + errors.BadRequestErrorData, http_res + ) + raise errors.BadRequestError(response_data, http_res) + if utils.match_response(http_res, "401", "application/json"): + response_data = unmarshal_json_response( + errors.AuthenticationErrorData, http_res + ) + raise errors.AuthenticationError(response_data, http_res) + if utils.match_response(http_res, "404", "application/json"): + response_data = unmarshal_json_response(errors.NotFoundErrorData, http_res) + raise errors.NotFoundError(response_data, http_res) + if utils.match_response(http_res, "429", "application/json"): + response_data = unmarshal_json_response(errors.RateLimitErrorData, http_res) + raise errors.RateLimitError(response_data, http_res) + if utils.match_response(http_res, "4XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.ModerationAPIDefaultError( + "API error occurred", http_res, http_res_text + ) + + raise errors.ModerationAPIDefaultError("Unexpected response received", http_res) + def submit( self, *, diff --git a/src/moderation_api/models/__init__.py b/src/moderation_api/models/__init__.py index 75cd8d2..468f695 100644 --- a/src/moderation_api/models/__init__.py +++ b/src/moderation_api/models/__init__.py @@ -13,8 +13,24 @@ AddWordlistWordsResponse, AddWordlistWordsResponseTypedDict, ) + from .allowcontentop import ( + AllowContentRequest, + AllowContentRequestBody, + AllowContentRequestBodyTypedDict, + AllowContentRequestTypedDict, + AllowContentResponse, + AllowContentResponseTypedDict, + ) from .authenticationerror import AuthenticationErrorCode from .badrequesterror import BadRequestErrorCode + from .blockauthorop import ( + BlockAuthorRequest, + BlockAuthorRequestBody, + BlockAuthorRequestBodyTypedDict, + BlockAuthorRequestTypedDict, + BlockAuthorResponse, + BlockAuthorResponseTypedDict, + ) from .channel import ( Channel, ChannelTypedDict, @@ -422,6 +438,14 @@ ) from .queuewithcounts import QueueWithCounts, QueueWithCountsTypedDict from .ratelimiterror import RateLimitErrorCode + from .rejectcontentop import ( + RejectContentRequest, + RejectContentRequestBody, + RejectContentRequestBodyTypedDict, + RejectContentRequestTypedDict, + RejectContentResponse, + RejectContentResponseTypedDict, + ) from .removewordlistwordsop import ( RemoveWordlistWordsRequest, RemoveWordlistWordsRequestTypedDict, @@ -643,6 +667,22 @@ Weapons, WeaponsTypedDict, ) + from .suspendauthorop import ( + SuspendAuthorRequest, + SuspendAuthorRequestBody, + SuspendAuthorRequestBodyTypedDict, + SuspendAuthorRequestTypedDict, + SuspendAuthorResponse, + SuspendAuthorResponseTypedDict, + ) + from .unblockauthorop import ( + UnblockAuthorRequest, + UnblockAuthorRequestBody, + UnblockAuthorRequestBodyTypedDict, + UnblockAuthorRequestTypedDict, + UnblockAuthorResponse, + UnblockAuthorResponseTypedDict, + ) from .unresolvequeueitemop import ( UnresolveQueueItemRequest, UnresolveQueueItemRequestTypedDict, @@ -725,6 +765,12 @@ "AdultTypedDict", "Alcohol", "AlcoholTypedDict", + "AllowContentRequest", + "AllowContentRequestBody", + "AllowContentRequestBodyTypedDict", + "AllowContentRequestTypedDict", + "AllowContentResponse", + "AllowContentResponseTypedDict", "AudioRequest", "AudioRequestTypedDict", "AudioResponse", @@ -733,6 +779,12 @@ "AuthorStatus", "BadRequestErrorCode", "Block", + "BlockAuthorRequest", + "BlockAuthorRequestBody", + "BlockAuthorRequestBodyTypedDict", + "BlockAuthorRequestTypedDict", + "BlockAuthorResponse", + "BlockAuthorResponseTypedDict", "BlockTypedDict", "Bucket", "Cannabis", @@ -1153,6 +1205,12 @@ "ReasonCodeTypedDict", "Recommendation", "RecommendationTypedDict", + "RejectContentRequest", + "RejectContentRequestBody", + "RejectContentRequestBodyTypedDict", + "RejectContentRequestTypedDict", + "RejectContentResponse", + "RejectContentResponseTypedDict", "Religion", "ReligionTypedDict", "RemoveWordlistWordsRequest", @@ -1229,6 +1287,12 @@ "SubmitContentResponseTypedDict", "SubmitContentTrustLevel", "SubmitContentTrustLevelTypedDict", + "SuspendAuthorRequest", + "SuspendAuthorRequestBody", + "SuspendAuthorRequestBodyTypedDict", + "SuspendAuthorRequestTypedDict", + "SuspendAuthorResponse", + "SuspendAuthorResponseTypedDict", "TextRequest", "TextRequestTypedDict", "TextResponse", @@ -1254,6 +1318,12 @@ "URLMaskingTypedDict", "URLRisk", "URLRiskTypedDict", + "UnblockAuthorRequest", + "UnblockAuthorRequestBody", + "UnblockAuthorRequestBodyTypedDict", + "UnblockAuthorRequestTypedDict", + "UnblockAuthorResponse", + "UnblockAuthorResponseTypedDict", "UnicodeSpoofing", "UnicodeSpoofingTypedDict", "UnknownContentLeafResponse", @@ -1336,8 +1406,20 @@ "AddWordlistWordsRequestTypedDict": ".addwordlistwordsop", "AddWordlistWordsResponse": ".addwordlistwordsop", "AddWordlistWordsResponseTypedDict": ".addwordlistwordsop", + "AllowContentRequest": ".allowcontentop", + "AllowContentRequestBody": ".allowcontentop", + "AllowContentRequestBodyTypedDict": ".allowcontentop", + "AllowContentRequestTypedDict": ".allowcontentop", + "AllowContentResponse": ".allowcontentop", + "AllowContentResponseTypedDict": ".allowcontentop", "AuthenticationErrorCode": ".authenticationerror", "BadRequestErrorCode": ".badrequesterror", + "BlockAuthorRequest": ".blockauthorop", + "BlockAuthorRequestBody": ".blockauthorop", + "BlockAuthorRequestBodyTypedDict": ".blockauthorop", + "BlockAuthorRequestTypedDict": ".blockauthorop", + "BlockAuthorResponse": ".blockauthorop", + "BlockAuthorResponseTypedDict": ".blockauthorop", "Channel": ".channel", "ChannelTypedDict": ".channel", "ContentType": ".channel", @@ -1676,6 +1758,12 @@ "QueueWithCounts": ".queuewithcounts", "QueueWithCountsTypedDict": ".queuewithcounts", "RateLimitErrorCode": ".ratelimiterror", + "RejectContentRequest": ".rejectcontentop", + "RejectContentRequestBody": ".rejectcontentop", + "RejectContentRequestBodyTypedDict": ".rejectcontentop", + "RejectContentRequestTypedDict": ".rejectcontentop", + "RejectContentResponse": ".rejectcontentop", + "RejectContentResponseTypedDict": ".rejectcontentop", "RemoveWordlistWordsRequest": ".removewordlistwordsop", "RemoveWordlistWordsRequestTypedDict": ".removewordlistwordsop", "RemoveWordlistWordsResponse": ".removewordlistwordsop", @@ -1890,6 +1978,18 @@ "ViolenceTypedDict": ".submitcontentop", "Weapons": ".submitcontentop", "WeaponsTypedDict": ".submitcontentop", + "SuspendAuthorRequest": ".suspendauthorop", + "SuspendAuthorRequestBody": ".suspendauthorop", + "SuspendAuthorRequestBodyTypedDict": ".suspendauthorop", + "SuspendAuthorRequestTypedDict": ".suspendauthorop", + "SuspendAuthorResponse": ".suspendauthorop", + "SuspendAuthorResponseTypedDict": ".suspendauthorop", + "UnblockAuthorRequest": ".unblockauthorop", + "UnblockAuthorRequestBody": ".unblockauthorop", + "UnblockAuthorRequestBodyTypedDict": ".unblockauthorop", + "UnblockAuthorRequestTypedDict": ".unblockauthorop", + "UnblockAuthorResponse": ".unblockauthorop", + "UnblockAuthorResponseTypedDict": ".unblockauthorop", "UnresolveQueueItemRequest": ".unresolvequeueitemop", "UnresolveQueueItemRequestTypedDict": ".unresolvequeueitemop", "UnresolveQueueItemResponse": ".unresolvequeueitemop", diff --git a/src/moderation_api/models/allowcontentop.py b/src/moderation_api/models/allowcontentop.py new file mode 100644 index 0000000..c6addd9 --- /dev/null +++ b/src/moderation_api/models/allowcontentop.py @@ -0,0 +1,120 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from moderation_api.types import BaseModel, UNSET_SENTINEL +from moderation_api.utils import ( + FieldMetadata, + HeaderMetadata, + PathParamMetadata, + RequestMetadata, +) +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class AllowContentRequestBodyTypedDict(TypedDict): + reason: NotRequired[str] + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + queue_id: NotRequired[str] + r"""The queue the content is reviewed in. Defaults to the project's default queue.""" + moderator: NotRequired[str] + r"""The user ID or email of the organization member who made the decision. The action is recorded as theirs.""" + create_casebook_case: NotRequired[bool] + r"""Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.""" + + +class AllowContentRequestBody(BaseModel): + reason: Optional[str] = None + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + + queue_id: Annotated[Optional[str], pydantic.Field(alias="queueId")] = None + r"""The queue the content is reviewed in. Defaults to the project's default queue.""" + + moderator: Optional[str] = None + r"""The user ID or email of the organization member who made the decision. The action is recorded as theirs.""" + + create_casebook_case: Annotated[ + Optional[bool], pydantic.Field(alias="createCasebookCase") + ] = None + r"""Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["reason", "queueId", "moderator", "createCasebookCase"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class AllowContentRequestTypedDict(TypedDict): + id: str + r"""The content ID you sent when you submitted the content, or the ID Moderation API assigned.""" + body: AllowContentRequestBodyTypedDict + project_id: NotRequired[str] + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + +class AllowContentRequest(BaseModel): + id: Annotated[ + str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False)) + ] + r"""The content ID you sent when you submitted the content, or the ID Moderation API assigned.""" + + body: Annotated[ + AllowContentRequestBody, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + + project_id: Annotated[ + Optional[str], + pydantic.Field(alias="Project-Id"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["projectId"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class AllowContentResponseTypedDict(TypedDict): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" + + +class AllowContentResponse(BaseModel): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" + + +try: + AllowContentRequestBody.model_rebuild() +except NameError: + pass diff --git a/src/moderation_api/models/blockauthorop.py b/src/moderation_api/models/blockauthorop.py new file mode 100644 index 0000000..8f5ecc9 --- /dev/null +++ b/src/moderation_api/models/blockauthorop.py @@ -0,0 +1,97 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from moderation_api.types import BaseModel, UNSET_SENTINEL +from moderation_api.utils import ( + FieldMetadata, + HeaderMetadata, + PathParamMetadata, + RequestMetadata, +) +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class BlockAuthorRequestBodyTypedDict(TypedDict): + reason: NotRequired[str] + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + + +class BlockAuthorRequestBody(BaseModel): + reason: Optional[str] = None + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["reason"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class BlockAuthorRequestTypedDict(TypedDict): + id: str + r"""Either external ID or the ID assigned by moderation API.""" + body: BlockAuthorRequestBodyTypedDict + project_id: NotRequired[str] + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + +class BlockAuthorRequest(BaseModel): + id: Annotated[ + str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False)) + ] + r"""Either external ID or the ID assigned by moderation API.""" + + body: Annotated[ + BlockAuthorRequestBody, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + + project_id: Annotated[ + Optional[str], + pydantic.Field(alias="Project-Id"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["projectId"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class BlockAuthorResponseTypedDict(TypedDict): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" + + +class BlockAuthorResponse(BaseModel): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" diff --git a/src/moderation_api/models/executeactionop.py b/src/moderation_api/models/executeactionop.py index feab8d3..30ac0de 100644 --- a/src/moderation_api/models/executeactionop.py +++ b/src/moderation_api/models/executeactionop.py @@ -24,6 +24,10 @@ class ExecuteActionRequestBodyTypedDict(TypedDict): r"""Optional queue ID if the action is queue-specific""" duration: NotRequired[float] r"""Optional duration in milliseconds for actions with timeouts""" + moderator: NotRequired[str] + r"""The user ID or email of the organization member who made the decision. The action is recorded as theirs.""" + create_casebook_case: NotRequired[bool] + r"""Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.""" class ExecuteActionRequestBody(BaseModel): @@ -49,10 +53,26 @@ class ExecuteActionRequestBody(BaseModel): duration: Optional[float] = None r"""Optional duration in milliseconds for actions with timeouts""" + moderator: Optional[str] = None + r"""The user ID or email of the organization member who made the decision. The action is recorded as theirs.""" + + create_casebook_case: Annotated[ + Optional[bool], pydantic.Field(alias="createCasebookCase") + ] = None + r"""Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set( - ["contentIds", "authorIds", "value", "queueId", "duration"] + [ + "contentIds", + "authorIds", + "value", + "queueId", + "duration", + "moderator", + "createCasebookCase", + ] ) serialized = handler(self) m = {} diff --git a/src/moderation_api/models/rejectcontentop.py b/src/moderation_api/models/rejectcontentop.py new file mode 100644 index 0000000..3c4f3e0 --- /dev/null +++ b/src/moderation_api/models/rejectcontentop.py @@ -0,0 +1,120 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from moderation_api.types import BaseModel, UNSET_SENTINEL +from moderation_api.utils import ( + FieldMetadata, + HeaderMetadata, + PathParamMetadata, + RequestMetadata, +) +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class RejectContentRequestBodyTypedDict(TypedDict): + reason: NotRequired[str] + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + queue_id: NotRequired[str] + r"""The queue the content is reviewed in. Defaults to the project's default queue.""" + moderator: NotRequired[str] + r"""The user ID or email of the organization member who made the decision. The action is recorded as theirs.""" + create_casebook_case: NotRequired[bool] + r"""Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.""" + + +class RejectContentRequestBody(BaseModel): + reason: Optional[str] = None + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + + queue_id: Annotated[Optional[str], pydantic.Field(alias="queueId")] = None + r"""The queue the content is reviewed in. Defaults to the project's default queue.""" + + moderator: Optional[str] = None + r"""The user ID or email of the organization member who made the decision. The action is recorded as theirs.""" + + create_casebook_case: Annotated[ + Optional[bool], pydantic.Field(alias="createCasebookCase") + ] = None + r"""Record an allow or reject decision as a casebook case. Defaults to true when `moderator` is set, else false. Without `moderator`, the case is recorded as System.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["reason", "queueId", "moderator", "createCasebookCase"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class RejectContentRequestTypedDict(TypedDict): + id: str + r"""The content ID you sent when you submitted the content, or the ID Moderation API assigned.""" + body: RejectContentRequestBodyTypedDict + project_id: NotRequired[str] + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + +class RejectContentRequest(BaseModel): + id: Annotated[ + str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False)) + ] + r"""The content ID you sent when you submitted the content, or the ID Moderation API assigned.""" + + body: Annotated[ + RejectContentRequestBody, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + + project_id: Annotated[ + Optional[str], + pydantic.Field(alias="Project-Id"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["projectId"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class RejectContentResponseTypedDict(TypedDict): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" + + +class RejectContentResponse(BaseModel): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" + + +try: + RejectContentRequestBody.model_rebuild() +except NameError: + pass diff --git a/src/moderation_api/models/suspendauthorop.py b/src/moderation_api/models/suspendauthorop.py new file mode 100644 index 0000000..c02ebb8 --- /dev/null +++ b/src/moderation_api/models/suspendauthorop.py @@ -0,0 +1,102 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from moderation_api.types import BaseModel, UNSET_SENTINEL +from moderation_api.utils import ( + FieldMetadata, + HeaderMetadata, + PathParamMetadata, + RequestMetadata, +) +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class SuspendAuthorRequestBodyTypedDict(TypedDict): + reason: NotRequired[str] + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + duration: NotRequired[float] + r"""How long the suspension lasts, in milliseconds. Defaults to 24 hours.""" + + +class SuspendAuthorRequestBody(BaseModel): + reason: Optional[str] = None + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + + duration: Optional[float] = None + r"""How long the suspension lasts, in milliseconds. Defaults to 24 hours.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["reason", "duration"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class SuspendAuthorRequestTypedDict(TypedDict): + id: str + r"""Either external ID or the ID assigned by moderation API.""" + body: SuspendAuthorRequestBodyTypedDict + project_id: NotRequired[str] + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + +class SuspendAuthorRequest(BaseModel): + id: Annotated[ + str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False)) + ] + r"""Either external ID or the ID assigned by moderation API.""" + + body: Annotated[ + SuspendAuthorRequestBody, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + + project_id: Annotated[ + Optional[str], + pydantic.Field(alias="Project-Id"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["projectId"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class SuspendAuthorResponseTypedDict(TypedDict): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" + + +class SuspendAuthorResponse(BaseModel): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" diff --git a/src/moderation_api/models/unblockauthorop.py b/src/moderation_api/models/unblockauthorop.py new file mode 100644 index 0000000..7004660 --- /dev/null +++ b/src/moderation_api/models/unblockauthorop.py @@ -0,0 +1,97 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from moderation_api.types import BaseModel, UNSET_SENTINEL +from moderation_api.utils import ( + FieldMetadata, + HeaderMetadata, + PathParamMetadata, + RequestMetadata, +) +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class UnblockAuthorRequestBodyTypedDict(TypedDict): + reason: NotRequired[str] + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + + +class UnblockAuthorRequestBody(BaseModel): + reason: Optional[str] = None + r"""Why the action was taken. Saved with the action and sent in the webhook event.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["reason"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class UnblockAuthorRequestTypedDict(TypedDict): + id: str + r"""Either external ID or the ID assigned by moderation API.""" + body: UnblockAuthorRequestBodyTypedDict + project_id: NotRequired[str] + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + +class UnblockAuthorRequest(BaseModel): + id: Annotated[ + str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False)) + ] + r"""Either external ID or the ID assigned by moderation API.""" + + body: Annotated[ + UnblockAuthorRequestBody, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + + project_id: Annotated[ + Optional[str], + pydantic.Field(alias="Project-Id"), + FieldMetadata(header=HeaderMetadata(style="simple", explode=False)), + ] = None + r"""The project to act on, by ID or name. Required with an organization key unless the key reaches only one project; list projects with GET /projects. A project key acts on its own project and needs no value: naming another one is an error.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["projectId"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +class UnblockAuthorResponseTypedDict(TypedDict): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" + + +class UnblockAuthorResponse(BaseModel): + r"""Execution result""" + + success: bool + r"""Whether the action was executed successfully""" diff --git a/src/moderation_api/sdk.py b/src/moderation_api/sdk.py index 0cf00f6..8376ad2 100644 --- a/src/moderation_api/sdk.py +++ b/src/moderation_api/sdk.py @@ -39,11 +39,11 @@ class ModerationAPI(BaseSDK): feedback: "Feedback" queue: "QueueSDK" actions: "Actions" + content: "ContentSDK" webhooks: "Webhooks" webhook_secret: "WebhookSecret" account: "Account" wordlist: "Wordlist" - content: "ContentSDK" projects: "Projects" channels: "Channels" _sub_sdk_map = { @@ -52,11 +52,11 @@ class ModerationAPI(BaseSDK): "feedback": ("moderation_api.feedback", "Feedback"), "queue": ("moderation_api.queue_sdk", "QueueSDK"), "actions": ("moderation_api.actions", "Actions"), + "content": ("moderation_api.content_sdk", "ContentSDK"), "webhooks": ("moderation_api.webhooks", "Webhooks"), "webhook_secret": ("moderation_api.webhooksecret", "WebhookSecret"), "account": ("moderation_api.account", "Account"), "wordlist": ("moderation_api.wordlist", "Wordlist"), - "content": ("moderation_api.content_sdk", "ContentSDK"), "projects": ("moderation_api.projects", "Projects"), "channels": ("moderation_api.channels", "Channels"), }