Skip to main content

Python SDK for Dooray.com with Socket Mode support

Project description

Dooray SDK - Python

Python Dooray SDK의 주요 클래스, 데코레이터 및 사용법을 설명합니다.


설치

pip으로 설치

pip install dooray-sdk

aiohttp 포함 설치 (권장)

pip install dooray-sdk[aiohttp]

가상환경 사용 (권장)

# 가상환경 생성
python3 -m venv .venv

# 활성화 (Linux/macOS)
source .venv/bin/activate

# 활성화 (Windows)
.venv\Scripts\activate

# 설치
pip install dooray-sdk[aiohttp]

필수 의존성

패키지 버전 설명
aiohttp >= 3.8.0 비동기 HTTP/WebSocket 클라이언트
requests >= 2.28.0 동기 HTTP 클라이언트

환경변수

SDK는 다음 환경변수를 사용합니다:

환경변수 필수 설명 예시
DOORAY_AGENT_TOKEN 에이전트 인증 토큰 your_agent_token
DOORAY_DOMAIN Dooray 도메인 company.dooray.com

클래스

Agent

Dooray 에이전트를 만들기 위한 핵심 클래스입니다. 메시지 수신, 자동 응답, 이벤트 처리 등을 지원합니다.

class Agent:
    def __init__(
        self,
        token: str = None,
        domain: str = None,
        services: List[str] = None,
        **kwargs
    )

생성자 매개변수

매개변수 타입 기본값 설명
token str | None None 에이전트 토큰 (환경변수 DOORAY_AGENT_TOKEN 대체)
domain str | None None Dooray 도메인 (환경변수 DOORAY_DOMAIN 대체)
services List[str] | None ["messenger"] 연결할 서비스 목록

속성

속성 타입 설명
token str 에이전트 인증 토큰
domain str Dooray 도메인
services List[str] 연결된 서비스 목록
base_url str API 기본 URL
is_connected bool 연결 상태

메서드

메서드 설명
run() 에이전트 실행 (블로킹)
on(event_type, action, service) 이벤트 핸들러 데코레이터
add_handler(event_type, handler, action, service) 핸들러 등록 (비데코레이터)
reply_to(trigger, response) 단순 응답 매핑
send_message(channel, text) 메시지 전송

예제 - 기본 사용

from dooray_sdk import Agent

agent = Agent()

@agent.messenger
def handle_message(req):
    """메신저 메시지 처리."""
    if req.text:
        req.reply(f"받은 메시지: {req.text}")

agent.run()

예제 - 멀티 서비스

from dooray_sdk import Agent

agent = Agent(services=["messenger", "task", "wiki"])

@agent.messenger
def handle_messenger(req):
    req.reply("메신저 메시지입니다")

@agent.task
def handle_task(req):
    print(f"업무 이벤트: {req.action}")

@agent.wiki
def handle_wiki(req):
    print(f"위키 이벤트: {req.action}")

agent.run()

SocketModeRequest

WebSocket으로 수신된 요청을 나타내는 클래스입니다.

@dataclass
class SocketModeRequest:
    envelope_id: str
    type: str
    payload: Dict[str, Any]
    service: str = ""
    action: str = ""
    entity: EntityWrapper = None
    actor: ActorWrapper = None
    action_data: ActionWrapper = None

속성

속성 타입 설명
envelope_id str 메시지 고유 ID
type str 이벤트 타입 (message, task, page 등)
payload Dict[str, Any] 원본 페이로드 데이터
service str 서비스 이름 (messenger, task, wiki)
action str 액션 타입 (create, update, delete)
entity EntityWrapper 엔티티 정보 래퍼
actor ActorWrapper 액터 정보 래퍼
action_data ActionWrapper 액션 데이터 래퍼

편의 속성

속성 타입 설명
is_message bool 메시지 타입 여부
text str | None 메시지 텍스트
channel str | None 채널 ID
data Dict[str, Any] 원본 데이터 (payload 별칭)

메서드

메서드 설명
reply(text) 동기/비동기 응답 전송
is_type(types) 타입 확인
is_action(actions) 액션 확인
is_service(services) 서비스 확인
to_dict() 딕셔너리 변환
from_dict(data, default_service) 딕셔너리에서 생성 (클래스 메서드)

예제 - 요청 처리

@agent.messenger
def handle(req):
    # 메시지 타입 확인
    if req.is_message:
        print(f"텍스트: {req.text}")
        print(f"채널: {req.channel}")

    # 액션 확인
    if req.is_action("create"):
        print("새 메시지입니다")

    # 서비스 확인
    if req.is_service("messenger"):
        req.reply("메신저에서 응답합니다")

WebClient

동기 REST API 클라이언트입니다.

class WebClient:
    def __init__(
        self,
        token: str,
        base_url: str = "https://api.dooray.com/",
        timeout: int = 30
    )

메서드

메서드 반환 타입 설명
send_message(channel, text, **kwargs) Dict 메시지 전송
get_member(member_id) Dict 조직 멤버 정보 조회

AsyncWebClient

비동기 REST API 클라이언트입니다.

class AsyncWebClient:
    def __init__(
        self,
        token: str,
        base_url: str = "https://api.dooray.com/"
    )

메서드

메서드 반환 타입 설명
send_message(channel, text, **kwargs) Dict 메시지 전송
get_member(member_id) Dict 조직 멤버 정보 조회

데코레이터

서비스별 데코레이터

각 서비스에 대한 이벤트 핸들러를 등록합니다.

@agent.messenger   # 메신저 서비스 전체 이벤트
@agent.task        # 업무 서비스 전체 이벤트
@agent.wiki        # 위키 서비스 전체 이벤트

@agent.on() 데코레이터

통합 이벤트 핸들러 데코레이터입니다.

def on(
    event_type: Union[str, List[str]] = "all",
    action: Union[str, List[str]] = None,
    service: Union[str, List[str]] = None
) -> Callable

매개변수

매개변수 타입 기본값 설명
event_type str | List[str] "all" 이벤트 타입 필터
action str | List[str] | None None 액션 필터
service str | List[str] | None None 서비스 필터

예제

# 메시지 이벤트만 처리
@agent.on("message")
def handle_message(req):
    pass

# 특정 액션만 처리
@agent.on("message", action="create")
def handle_new_message(req):
    pass

# 복수 타입 처리
@agent.on(["task", "page"])
def handle_task_or_page(req):
    pass

# 서비스 + 액션 조합
@agent.on(service="wiki", action=["create", "update"])
def handle_wiki_changes(req):
    pass

요청 데이터 구조

SDK는 딕셔너리 데이터를 점 표기법(dot notation)으로 접근할 수 있게 해주는 래퍼 타입을 제공합니다.

타입 구조 개요

SocketModeRequest
├── entity: EntityWrapper      # 엔티티 정보 (task, page 등)
│   ├── type: str              # 엔티티 타입
│   └── data: DataWrapper      # 엔티티 데이터
├── actor: ActorWrapper        # 액션 수행자 정보
│   ├── type: str              # 액터 타입
│   └── data: DataWrapper      # 액터 데이터
└── action_data: ActionWrapper # 액션 상세 정보
    ├── type: str              # 액션 타입
    └── data: DataWrapper      # 액션 데이터

DataWrapper

모든 래퍼 타입의 기반이 되는 클래스입니다. 딕셔너리 데이터를 점 표기법으로 접근할 수 있게 합니다.

class DataWrapper:
    def __getattr__(self, name: str) -> Any   # 점 표기법 접근
    def __getitem__(self, key: str) -> Any    # 딕셔너리 접근
    def get(self, key: str, default=None)     # 안전한 접근
    def to_dict(self) -> Dict[str, Any]       # 원본 딕셔너리 반환

사용 예시:

# 점 표기법 접근
data.id
data.subject
data.nested.value

# 딕셔너리 접근
data["id"]
data.get("subject", "기본값")

# 원본 딕셔너리
data.to_dict()

EntityWrapper

엔티티(업무, 페이지 등) 정보를 래핑합니다.

속성 타입 설명
type str 엔티티 타입 (예: "task", "page")
data DataWrapper 엔티티 상세 데이터

사용 예시:

@agent.on("task")
def handle_task(req):
    print(req.entity.type)           # "task"
    print(req.entity.data.id)        # 업무 ID
    print(req.entity.data.subject)   # 업무 제목

메시지 데이터

메신저 메시지의 경우 entity.type"message"입니다.

속성 타입 설명
id str 메시지 ID
channelId str 채널 ID
senderId str 보낸 사람 멤버 ID
text str 메시지 텍스트
sentAt int 보낸 시간 (timestamp ms)
seq int 메시지 시퀀스 번호
directMemberId str DM 상대방 멤버 ID
parentChannelId str 부모 채널 ID (스레드)
@agent.messenger
def handle(req):
    print(req.entity.message.text)
    print(req.entity.message.channelId)
    print(req.entity.message.senderId)
    print(req.entity.message.sentAt)

ActorWrapper

액션을 수행한 사용자 정보를 래핑합니다.

속성 타입 설명
type str 액터 타입 (예: "organizationMember")
data DataWrapper 액터 상세 데이터
organizationMember LazyMemberData | None 조직 멤버 정보 (lazy loading 지원)

사용 예시:

@agent.on("message")
def handle(req):
    if req.actor:
        print(req.actor.type)         # "organizationMember"

        # organizationMember로 접근 (권장)
        member = req.actor.organizationMember
        print(member.id)              # 멤버 ID (로컬 데이터)
        print(member.name)            # 멤버 이름 (lazy loading)

organizationMember 필드

속성 타입 설명
id str 멤버 ID
name str 멤버 이름
externalEmailAddress str 이메일 주소
nickname str 닉네임
englishName str 영문 이름
nativeName str 현지 이름
userCode str 사용자 코드
locale str 로케일
timezoneName str 타임존

Lazy Loading

organizationMember는 WebSocket 메시지에 포함된 데이터는 즉시 반환하고, 없는 필드는 API를 호출하여 가져옵니다.

@agent.messenger
async def handle(req):
    member = req.actor.organizationMember

    # 로컬 데이터 (API 호출 없음)
    member_id = member.id

    # Async 접근 - 필요시 API 호출
    name = await member.name
    email = await member.externalEmailAddress

    # Sync 접근 (print, 비교 등)
    print(member.name)
    if member.name == "홍길동":
        await req.reply("안녕하세요!")

    # 전체 데이터 조회
    full_data = await member

ActionWrapper

액션의 상세 정보를 래핑합니다.

속성 타입 설명
type str 액션 타입 (예: "create", "update")
data DataWrapper 액션 상세 데이터

사용 예시

에코 에이전트

from dooray_sdk import Agent

agent = Agent()

@agent.messenger
def echo(req):
    if req.text:
        req.reply(f"에코: {req.text}")

agent.run()

자동 응답 에이전트

from dooray_sdk import Agent

agent = Agent()

# 단순 매핑
agent.reply_to("ping", "pong")
agent.reply_to("hello", "안녕하세요!")

# 커스텀 핸들러
@agent.messenger
def handle(req):
    text = req.text or ""
    if text.startswith("help"):
        req.reply("사용 가능한 명령: ping, hello, help")

agent.run()

멀티 서비스 에이전트

from dooray_sdk import Agent

agent = Agent(services=["messenger", "task", "wiki"])

@agent.messenger
def on_message(req):
    print(f"[메신저] {req.text}")
    req.reply("메시지 받음!")

@agent.task
def on_task(req):
    print(f"[업무] {req.action}: {req.entity.data.subject}")

@agent.wiki
def on_wiki(req):
    print(f"[위키] {req.action}: {req.entity.data.title}")

@agent.on("all")
def on_any(req):
    print(f"[전체] {req.service}/{req.type}/{req.action}")

agent.run()

오류 처리

일반적인 예외

예외 원인 해결 방법
ValueError 환경변수 미설정 DOORAY_AGENT_TOKEN, DOORAY_DOMAIN 설정
ConnectionError WebSocket 연결 실패 네트워크 및 토큰 확인
RuntimeError 에이전트 미실행 상태에서 reply 호출 agent.run() 후 사용

예외 처리 예시

from dooray_sdk import Agent

try:
    agent = Agent()
except ValueError as e:
    print(f"설정 오류: {e}")
    print("DOORAY_AGENT_TOKEN과 DOORAY_DOMAIN을 설정하세요")
    exit(1)

@agent.messenger
def handle(req):
    try:
        # 비즈니스 로직
        process_message(req)
    except Exception as e:
        # 에러 로깅 (사용자에게 에러 노출 방지)
        logger.error(f"처리 오류: {e}")

agent.run()

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dooray_sdk-0.0.1a1.tar.gz (56.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dooray_sdk-0.0.1a1-py3-none-any.whl (44.3 kB view details)

Uploaded Python 3

File details

Details for the file dooray_sdk-0.0.1a1.tar.gz.

File metadata

  • Download URL: dooray_sdk-0.0.1a1.tar.gz
  • Upload date:
  • Size: 56.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for dooray_sdk-0.0.1a1.tar.gz
Algorithm Hash digest
SHA256 303b5b536681f6e91d19aa2efc311de3cc5b59a1dfa2462a7be60827d948571f
MD5 40957b364920ab4df75255b5bcaf4d42
BLAKE2b-256 2160ff3ebe448f4c80aa4b51825dd87548d916e064818fb29eb1bb3536642795

See more details on using hashes here.

File details

Details for the file dooray_sdk-0.0.1a1-py3-none-any.whl.

File metadata

  • Download URL: dooray_sdk-0.0.1a1-py3-none-any.whl
  • Upload date:
  • Size: 44.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for dooray_sdk-0.0.1a1-py3-none-any.whl
Algorithm Hash digest
SHA256 e342edf3fd403587f46d6c49967e956cd61353fbfff9bea3f79e8b9845cb1ba9
MD5 0528a632fa80cc6652a92ed9454a298b
BLAKE2b-256 30f386ca3fb9c504bfe37c9f54791c346c56bfdb82dfd9600e219565e1a32fb3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page