# Meemo

A Python library for interacting with the Meemo External API, providing access to meeting data including details, transcripts, summaries, participants, and recordings.

## Prerequisites

- **Python** >=3.11, <3.13

## Installation

```bash
pip install meemo
```

Or with uv:

```bash
uv add meemo
```

## Quick Start

```python
from meemo import MeemoClient

# Initialize the client
client = MeemoClient(
    client_id="your-client-id",
    client_secret="your-client-secret",
    base_url="https://api-meemo.glair.ai",
)

# List meetings
meetings = client.meetings.list_meetings()
for meeting in meetings.results:
    print(f"{meeting.id}: {meeting.title} ({meeting.status})")

# Get meeting details
detail = client.meetings.get_meeting(123)
print(f"Host: {detail.host.name}")
print(f"Duration: {detail.duration_seconds}s")

# Get transcript
transcript = client.meetings.get_transcript(123)
for segment in transcript.transcripts:
    print(f"[{segment.speaker}] {segment.text}")

# Get summary
summary = client.meetings.get_summary(123)
print(summary.summary)
```

## Async Usage

For use in async frameworks (FastAPI, Django async views, async workers), use `AsyncMeemoClient`:

```python
import asyncio
from meemo import AsyncMeemoClient

async def main():
    client = AsyncMeemoClient(
        client_id="your-client-id",
        client_secret="your-client-secret",
        base_url="https://api-meemo.glair.ai",
    )

    # All methods are async — same API surface as MeemoClient
    meetings = await client.meetings.list_meetings()
    for meeting in meetings.results:
        print(f"{meeting.id}: {meeting.title}")

    detail = await client.meetings.get_meeting(123)
    transcript = await client.meetings.get_transcript(123)
    summary = await client.meetings.get_summary(123)

    # Revoke token when done
    await client.revoke_token()

asyncio.run(main())
```

## Configuration

### Environment Variables

The library supports the following environment variables:

- `MEEMO_CLIENT_ID`: OAuth2 client ID for authentication
- `MEEMO_CLIENT_SECRET`: OAuth2 client secret for authentication
- `MEEMO_BASE_URL`: Base URL of the Meemo instance

### Client Initialization

```python
from meemo import MeemoClient

# Using explicit parameters
client = MeemoClient(
    client_id="your-client-id",
    client_secret="your-client-secret",
    base_url="https://api-meemo.glair.ai",
    timeout=60.0,
    default_headers={"X-Custom-Header": "value"},
)

# Using environment variables
import os
os.environ["MEEMO_CLIENT_ID"] = "your-client-id"
os.environ["MEEMO_CLIENT_SECRET"] = "your-client-secret"
os.environ["MEEMO_BASE_URL"] = "https://api-meemo.glair.ai"
client = MeemoClient()
```

## Authentication

The library uses **OAuth2 Client Credentials** flow. Tokens are automatically obtained and refreshed when they expire (default: 3 hours).

```python
# Token management is automatic, but you can also manage it manually:

# Revoke the current token
client.revoke_token()
```

## Meetings API

### List Meetings

```python
# Get all meetings
meetings = client.meetings.list_meetings()
print(f"Total: {meetings.count}")

# Filter by organization
meetings = client.meetings.list_meetings(organization_id=5)

# Filter by title and date
meetings = client.meetings.list_meetings(
    title="standup",
    created_after="2024-01-01",
    created_before="2024-12-31",
    summary_complete=True,
)

# Pagination
meetings = client.meetings.list_meetings(page=2, size=20)
```

### Get Meeting Details

```python
detail = client.meetings.get_meeting(123)
print(f"Title: {detail.title}")
print(f"Host: {detail.host.name} ({detail.host.email})")
print(f"Location: {detail.location}")
print(f"Language: {detail.language}")
print(f"Keywords: {', '.join(detail.keywords)}")
print(f"Participants: {detail.participant_count}")
print(f"Duration: {detail.duration_seconds}s")

# Calendar event info (if from calendar integration)
if detail.calendar_event:
    print(f"Calendar: {detail.calendar_event.summary}")
    print(f"Meeting Link: {detail.calendar_event.meeting_link}")
```

### Get Meeting Transcript

```python
transcript = client.meetings.get_transcript(123)
print(f"Total segments: {transcript.total_segments}")

for segment in transcript.transcripts:
    minutes = int(segment.start_time // 60)
    seconds = int(segment.start_time % 60)
    print(f"[{minutes:02d}:{seconds:02d}] {segment.speaker}: {segment.text}")
```

### Get Meeting Summary

```python
summary = client.meetings.get_summary(123)
print(summary.summary)  # Markdown or legacy JSON
print(f"Notes: {summary.notes}")
print(f"Keywords: {', '.join(summary.keywords)}")

# Handle both new Markdown and legacy JSON formats
if isinstance(summary.summary, str):
    # New Markdown format
    print(summary.summary)
elif isinstance(summary.summary, dict):
    # Legacy JSON format
    print(summary.summary.get("ringkasan", ""))
```

### Get Meeting Participants

```python
participants = client.meetings.get_participants(123)
print(f"Total: {participants.total_participants}")

for p in participants.participants:
    if p.id:
        print(f"  {p.name} ({p.email}) - {p.position}, {p.department}")
    else:
        print(f"  {p.name} (external guest)")
```

### Get Meeting Recording

```python
recording = client.meetings.get_recording(123)
if recording.recording_url:
    print(f"URL: {recording.recording_url}")
    print(f"Duration: {recording.duration}s")
    print(f"Format: {recording.format}")
else:
    print("No recording available")
```

## Multi-Organization Support

External applications can access meetings from multiple organizations with a single set of credentials.

```python
# Get meetings from all accessible organizations
all_meetings = client.meetings.list_meetings()

# Filter to a specific organization
org_meetings = client.meetings.list_meetings(organization_id=5)
```

## Error Handling

```python
import httpx
from meemo import MeemoClient

client = MeemoClient(
    client_id="your-client-id",
    client_secret="your-client-secret",
    base_url="https://api-meemo.glair.ai",
)

try:
    detail = client.meetings.get_meeting(999)
except httpx.HTTPStatusError as e:
    if e.response.status_code == 401:
        print("Authentication failed - check your credentials")
    elif e.response.status_code == 404:
        print("Meeting not found")
    else:
        print(f"HTTP Error: {e.response.status_code}")
        print(f"Response: {e.response.text}")
except ValueError as e:
    print(f"Validation Error: {e}")
```

## API Reference

- [Meemo External API Documentation](https://gdplabs.gitbook.io/meemo/resources/external-api-documentation)

## License

MIT License.
