Integration guides

Python

A moderation module for Python 3 with the requests library.

This guide uses requests. Install it with pip install requests.

Set the key

Put the key in the environment of your server, never in the code:

export OPENMOD_API_KEY="om_live_..."

The module

moderation.py
import os

import requests

BASE = "https://api.openshield.dev"
SESSION = requests.Session()


class ModerationError(Exception):
    def __init__(self, status, error_type, message, retry_after=None):
        super().__init__(message)
        self.status = status
        self.type = error_type
        self.retry_after = retry_after


def _send(path, **kwargs):
    headers = {"Authorization": f"Bearer {os.environ['OPENMOD_API_KEY']}"}
    response = SESSION.post(BASE + path, headers=headers, timeout=10, **kwargs)
    body = response.json()
    if not response.ok:
        error = body.get("error", {})
        raise ModerationError(
            response.status_code,
            error.get("type", "unknown"),
            error.get("message", response.reason),
            response.headers.get("Retry-After"),
        )
    summary = body["summary"]
    return {
        "action": summary["action"],
        "reasons": summary["reject_reason"] + summary["review_reason"],
        "request_id": body["request_id"],
    }


def check_text(text, ref=None):
    return _send("/v1/text", json={"text": text, "ref": ref})


def check_image(data, ref=None):
    return _send("/v1/image", params={"ref": ref} if ref else None, data=data)

Use it, and fail closed

import requests

from moderation import ModerationError, check_text


def moderate_comment(text, comment_id):
    """Returns "publish", "hold" or "refuse"."""
    try:
        decision = check_text(text, comment_id)
    except ModerationError as error:
        # The content cannot be accepted as it is: refuse it.
        if error.status in (400, 413, 415):
            return "refuse"
        return "hold"
    except requests.RequestException:
        # A timeout or a network error: keep it hidden until someone looks at it.
        return "hold"

    if decision["action"] == "accept":
        return "publish"
    if decision["action"] == "review":
        return "hold"
    return "refuse"

For rejected content, show your user a message chosen from the id of the first reason, in your own words and your own languages. Best practices says more.