---
title: Feishu ja Lark
description: Saadab Feishu ja Larki kanalitesse sõnumeid ja interaktiivseid kaarte.
category: Marketing
sublabel: SEO
author: OpenClaudia
tags: 
license: MIT
source: https://github.com/OpenClaudia/openclaudia-skills
---

# Feishu / Lark sõnumside oskus

Oled sõnumside spetsialist Feishu (飞书, ByteDance'i Hiina töökohaplatvorm) ja Lark (rahvusvaheline versioon) jaoks. Sinu ülesanne on saata sõnumeid, interaktiivseid kaarte ja turundussisu Feishu/Lark grupivestlustesse Custom Bot veebihaakide või App Bot API kaudu.

## Eeltingimused

Kontrolli, millised mandaadid on saadaval:

```bash
echo "FEISHU_WEBHOOK_URL is ${FEISHU_WEBHOOK_URL:+set}"
echo "FEISHU_WEBHOOK_SECRET is ${FEISHU_WEBHOOK_SECRET:+set}"
echo "FEISHU_APP_ID is ${FEISHU_APP_ID:+set}"
echo "FEISHU_APP_SECRET is ${FEISHU_APP_SECRET:+set}"
```

### Kaks integratsiooniviisi

| Viis | Vajalikud mandaadid | Võimalused |
|------|---------------------|--------------|
| **Custom Bot Webhook** (lihtne) | `FEISHU_WEBHOOK_URL` (+ valikuline `FEISHU_WEBHOOK_SECRET`) | Saada ühte gruppi teksti, vormindatud teksti ja interaktiivseid kaarte |
| **App Bot API** (täisfunktsionaalne) | `FEISHU_APP_ID` + `FEISHU_APP_SECRET` | Saada mis tahes vestlusesse, laadi üles pilte, maini kasutajaid, halda kaarte, võta vastu sündmusi |

Kui mandaate pole määratud, juhenda kasutajat:

> **Custom Bot Webhook (kiireim seadistus):**
> 1. Ava Feishu/Lark grupivestlus
> 2. Klõpsa ülal grupi nimel, et avada grupi seaded (Group Settings)
> 3. Mine **Bots** > **Add Bot** > **Custom Bot**
> 4. Anna botile nimi ja soovi korral määra allkirja kontrollimise (Signature Verification) saladus
> 5. Kopeeri veebihaagi URL ja lisa see faili `.env`:
>    ```
>    FEISHU_WEBHOOK_URL=https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}
>    FEISHU_WEBHOOK_SECRET=your_secret_here  # optional, for signed webhooks
>    ```
>
> **App Bot API (edasijõudnud kasutuseks):**
> 1. Mine [Feishu Open Platformile](https://open.feishu.cn/app) või [Lark Developer Console'i](https://open.larksuite.com/app)
> 2. Loo uus rakendus ja lülita sisse boti võimekus (Bot)
> 3. Lisa vajalikud õigused: `im:message:send_as_bot`, `im:chat:readonly`
> 4. Avalda rakendus ja kinnita see, seejärel lisa faili `.env`:
>    ```
>    FEISHU_APP_ID=cli_xxxxx
>    FEISHU_APP_SECRET=xxxxx
>    ```

### Veebihaagi URL-i vormingud

- **Feishu (Hiina):** `https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`
- **Lark (rahvusvaheline):** `https://open.larksuite.com/open-apis/bot/v2/hook/{webhook_id}`

### API baas-URL-id

- **Feishu (Hiina):** `https://open.feishu.cn/open-apis`
- **Lark (rahvusvaheline):** `https://open.larksuite.com/open-apis`

---

## 1. Custom Bot veebihaagi sõnumid

### 1.1 Lihttekstiga sõnum

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "text",
    "content": {
      "text": "Hello from OpenClaudia! This is a test message."
    }
  }'
```

**Maini kõiki grupi liikmeid:**

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "text",
    "content": {
      "text": "<at user_id=\"all\">Everyone</at> Important announcement: new release is live!"
    }
  }'
```

### 1.2 Vormindatud tekstiga sõnum (post)

Vormindatud tekst toetab struktureeritud kujul paksu kirja, linke, mainimisi ja pilte.

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "post",
    "content": {
      "post": {
        "zh_cn": {
          "title": "产品更新公告",
          "content": [
            [
              {"tag": "text", "text": "我们很高兴地宣布 "},
              {"tag": "a", "text": "v2.0 版本", "href": "https://example.com/changelog"},
              {"tag": "text", "text": " 已正式发布！"}
            ],
            [
              {"tag": "text", "text": "主要更新："}
            ],
            [
              {"tag": "text", "text": "1. 全新用户界面\n2. 性能提升 50%\n3. 支持暗色模式"}
            ],
            [
              {"tag": "at", "user_id": "all", "user_name": "所有人"}
            ]
          ]
        }
      }
    }
  }'
```

**Ingliskeelne versioon (Larki jaoks):**

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "post",
    "content": {
      "post": {
        "en_us": {
          "title": "Product Update Announcement",
          "content": [
            [
              {"tag": "text", "text": "We are excited to announce that "},
              {"tag": "a", "text": "v2.0", "href": "https://example.com/changelog"},
              {"tag": "text", "text": " is now live!"}
            ],
            [
              {"tag": "text", "text": "Key updates:"}
            ],
            [
              {"tag": "text", "text": "1. Brand new UI\n2. 50% performance improvement\n3. Dark mode support"}
            ],
            [
              {"tag": "at", "user_id": "all", "user_name": "Everyone"}
            ]
          ]
        }
      }
    }
  }'
```

### Vormindatud teksti siltide teatmik

| Silt | Eesmärk | Atribuudid |
|-----|---------|------------|
| `text` | Lihttekst | `text`, `un_escape` (tõeväärtus, tõlgendab `\n` jms) |
| `a` | Hüperlink | `text`, `href` |
| `at` | Mainimine | `user_id` (kõigi jaoks kasuta `"all"`), `user_name` |
| `img` | Pilt (ainult App Bot) | `image_key` (pilt tuleb enne üles laadida) |
| `media` | Video/fail (ainult App Bot) | `file_key`, `image_key` |

### 1.3 Allkirjastatud veebihaagi päringud

Kui `FEISHU_WEBHOOK_SECRET` on määratud, nõuab veebihaak kontrollimiseks allkirja.

**Loo allkirjastatud päring:**

```bash
# Calculate timestamp and signature
TIMESTAMP=$(date +%s)
STRING_TO_SIGN="${TIMESTAMP}\n${FEISHU_WEBHOOK_SECRET}"
SIGN=$(printf '%b' "${STRING_TO_SIGN}" | openssl dgst -sha256 -hmac "" -binary | openssl base64)

# For proper HMAC-SHA256 signing:
SIGN=$(echo -ne "${TIMESTAMP}\n${FEISHU_WEBHOOK_SECRET}" | openssl dgst -sha256 -hmac "" -binary | base64)

curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d "{
    \"timestamp\": \"${TIMESTAMP}\",
    \"sign\": \"${SIGN}\",
    \"msg_type\": \"text\",
    \"content\": {
      \"text\": \"Signed message from OpenClaudia.\"
    }
  }"
```

**Feishu allkirjaalgoritmi üksikasjad:**
1. Liida allkirjastatavaks stringiks `timestamp + "\n" + secret`
2. Arvuta sellest stringist tühja võtmega HMAC-SHA256
3. Kodeeri tulemus Base64-ks
4. Lisa päringu JSON-kehasse nii `timestamp` kui ka `sign`

---

## 2. Interaktiivsed kaardisõnumid

Interaktiivsed kaardid on kõige võimekam sõnumivorming. Need toetavad päiseid, sisuplokke, pilte, tegevusnuppe ja struktureeritud paigutusi.

### 2.1 Kaardi põhistruktuur

```json
{
  "msg_type": "interactive",
  "card": {
    "header": {
      "title": {
        "tag": "plain_text",
        "content": "Card Title Here"
      },
      "template": "blue"
    },
    "elements": []
  }
}
```

### Päise värvimallid

| Mall | Värv | Sobib kõige paremini |
|----------|-------|----------|
| `blue` | Sinine | Üldinfo, uuendused |
| `green` | Roheline | Edu, positiivsed uudised |
| `red` | Punane | Kiireloomuline, hoiatused, vead |
| `orange` | Oranž | Ettevaatusmärkused, vaja tegutseda |
| `purple` | Lilla | Sündmused, loominguline |
| `indigo` | Indigo | Tehniline, arendus |
| `turquoise` | Sinakasroheline | Kasv, turundus |
| `yellow` | Kollane | Esiletõstmised, nõuanded |
| `grey` | Hall | Neutraalne, madal prioriteet |
| `wathet` | Helesinine | Vaikimisi, puhas |

### 2.2 Kaardi elementide teatmik

**Markdowni sisuplokk:**

```json
{
  "tag": "markdown",
  "content": "**Bold text** and *italic text*\n[Link text](https://example.com)\nList:\n- Item 1\n- Item 2"
}
```

**Eraldusjoon:**

```json
{
  "tag": "hr"
}
```

**Märkus (väike hall jaluse tekst):**

```json
{
  "tag": "note",
  "elements": [
    {"tag": "plain_text", "content": "Sent via OpenClaudia Marketing Toolkit"}
  ]
}
```

**Pildiplokk:**

```json
{
  "tag": "img",
  "img_key": "img_v2_xxx",
  "alt": {"tag": "plain_text", "content": "Image description"},
  "title": {"tag": "plain_text", "content": "Image Title"}
}
```

**Tegevusnupud:**

```json
{
  "tag": "action",
  "actions": [
    {
      "tag": "button",
      "text": {"tag": "plain_text", "content": "View Details"},
      "type": "primary",
      "url": "https://example.com/details"
    },
    {
      "tag": "button",
      "text": {"tag": "plain_text", "content": "Dismiss"},
      "type": "default"
    }
  ]
}
```

**Nupu tüübid:** `primary` (sinine), `danger` (punane), `default` (hall)

**Mitmeveeruline paigutus:**

```json
{
  "tag": "column_set",
  "flex_mode": "bisect",
  "columns": [
    {
      "tag": "column",
      "width": "weighted",
      "weight": 1,
      "elements": [
        {"tag": "markdown", "content": "**Left Column**\nContent here"}
      ]
    },
    {
      "tag": "column",
      "width": "weighted",
      "weight": 1,
      "elements": [
        {"tag": "markdown", "content": "**Right Column**\nContent here"}
      ]
    }
  ]
}
```

### 2.3 Täielik kaardinäide: tooteteadaanne

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "interactive",
    "card": {
      "header": {
        "title": {
          "tag": "plain_text",
          "content": "New Feature Launch: AI-Powered Analytics"
        },
        "template": "turquoise"
      },
      "elements": [
        {
          "tag": "markdown",
          "content": "We are thrilled to announce our latest feature!\n\n**AI-Powered Analytics** is now available to all Pro and Enterprise users.\n\nKey highlights:\n- **Smart Insights**: Automatic trend detection and anomaly alerts\n- **Natural Language Queries**: Ask questions in plain English\n- **Predictive Forecasting**: 90-day revenue and growth projections\n- **Custom Dashboards**: Drag-and-drop report builder"
        },
        {
          "tag": "hr"
        },
        {
          "tag": "markdown",
          "content": "**Availability:** Rolling out now, fully live by end of week\n**Documentation:** [View the guide](https://example.com/docs/analytics)\n**Feedback:** Reply in this thread or submit via [feedback form](https://example.com/feedback)"
        },
        {
          "tag": "action",
          "actions": [
            {
              "tag": "button",
              "text": {"tag": "plain_text", "content": "Try It Now"},
              "type": "primary",
              "url": "https://example.com/analytics"
            },
            {
              "tag": "button",
              "text": {"tag": "plain_text", "content": "Read Docs"},
              "type": "default",
              "url": "https://example.com/docs/analytics"
            }
          ]
        },
        {
          "tag": "note",
          "elements": [
            {"tag": "plain_text", "content": "Product Team | Released 2025-01-15"}
          ]
        }
      ]
    }
  }'
```

---

## 3. App Bot API (täisfunktsionaalne)

App Bot API nõuab `FEISHU_APP_ID` ja `FEISHU_APP_SECRET`. See pakub täielikku sõnumside võimekust, sealhulgas saatmist mis tahes vestlusesse, piltide üleslaadimist ja sõnumite haldamist.

### 3.1 Hangi rentniku ligipääsuluba (tenant access token)

Kõik App Bot API väljakutsed nõuavad `tenant_access_token`-it. Load aeguvad 2 tunni pärast.

```bash
# For Feishu (China)
FEISHU_API_BASE="https://open.feishu.cn/open-apis"

# For Lark (International)
# FEISHU_API_BASE="https://open.larksuite.com/open-apis"

TENANT_TOKEN=$(curl -s -X POST "${FEISHU_API_BASE}/auth/v3/tenant_access_token/internal" \
  -H "Content-Type: application/json" \
  -d "{
    \"app_id\": \"${FEISHU_APP_ID}\",
    \"app_secret\": \"${FEISHU_APP_SECRET}\"
  }" | python3 -c "import json,sys; print(json.load(sys.stdin).get('tenant_access_token',''))")

echo "Token: ${TENANT_TOKEN:0:10}..."
```

### 3.2 Loetle vestlused, kuhu bot kuulub

```bash
curl -s "${FEISHU_API_BASE}/im/v1/chats?page_size=20" \
  -H "Authorization: Bearer ${TENANT_TOKEN}" | \
  python3 -c "
import json, sys
data = json.load(sys.stdin)
for chat in data.get('data', {}).get('items', []):
    print(f\"Chat ID: {chat['chat_id']}  |  Name: {chat.get('name', 'N/A')}  |  Type: {chat.get('chat_type', 'N/A')}\")
"
```

### 3.3 Saada sõnum vestlusesse

```bash
CHAT_ID="oc_xxxxx"  # Replace with actual chat_id

# Send a text message
curl -s -X POST "${FEISHU_API_BASE}/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer ${TENANT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"receive_id\": \"${CHAT_ID}\",
    \"msg_type\": \"text\",
    \"content\": \"{\\\"text\\\": \\\"Hello from the App Bot!\\\"}\"
  }"
```

**Saada API kaudu vormindatud tekstiga sõnum:**

```bash
curl -s -X POST "${FEISHU_API_BASE}/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer ${TENANT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"receive_id\": \"${CHAT_ID}\",
    \"msg_type\": \"post\",
    \"content\": $(python3 -c "
import json
content = {
    'zh_cn': {
        'title': 'App Bot 消息',
        'content': [
            [
                {'tag': 'text', 'text': '这是一条通过 App Bot API 发送的 '},
                {'tag': 'a', 'text': '富文本消息', 'href': 'https://example.com'},
                {'tag': 'text', 'text': '。'}
            ]
        ]
    }
}
print(json.dumps(json.dumps(content)))
")
  }"
```

**Saada API kaudu interaktiivne kaart:**

```bash
curl -s -X POST "${FEISHU_API_BASE}/im/v1/messages?receive_id_type=chat_id" \
  -H "Authorization: Bearer ${TENANT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"receive_id\": \"${CHAT_ID}\",
    \"msg_type\": \"interactive\",
    \"content\": $(python3 -c "
import json
card = {
    'header': {
        'title': {'tag': 'plain_text', 'content': 'Marketing Update'},
        'template': 'turquoise'
    },
    'elements': [
        {'tag': 'markdown', 'content': '**Campaign Performance This Week**\n\n- Impressions: **120,450** (+12%)\n- Clicks: **8,320** (+8%)\n- Conversions: **342** (+15%)\n- Cost per Conversion: **\$14.20** (-5%)'},
        {'tag': 'hr'},
        {'tag': 'action', 'actions': [
            {'tag': 'button', 'text': {'tag': 'plain_text', 'content': 'View Full Report'}, 'type': 'primary', 'url': 'https://example.com/report'}
        ]},
        {'tag': 'note', 'elements': [{'tag': 'plain_text', 'content': 'Auto-generated by OpenClaudia Marketing Toolkit'}]}
    ]
}
print(json.dumps(json.dumps(card)))
")
  }"
```

### 3.4 Laadi pilt üles

Laadi pilt üles, et saada `image_key`, mida kasutada kaartides ja vormindatud tekstiga sõnumites.

```bash
IMAGE_KEY=$(curl -s -X POST "${FEISHU_API_BASE}/im/v1/images" \
  -H "Authorization: Bearer ${TENANT_TOKEN}" \
  -F "image_type=message" \
  -F "image=@/path/to/image.png" | python3 -c "import json,sys; print(json.load(sys.stdin).get('data',{}).get('image_key',''))")

echo "Image key: ${IMAGE_KEY}"
```

### 3.5 Saada konkreetsele kasutajale (e-posti või user_id järgi)

```bash
# By email (receive_id_type=email)
curl -s -X POST "${FEISHU_API_BASE}/im/v1/messages?receive_id_type=email" \
  -H "Authorization: Bearer ${TENANT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d "{
    \"receive_id\": \"user@company.com\",
    \"msg_type\": \"text\",
    \"content\": \"{\\\"text\\\": \\\"Direct message from the marketing bot.\\\"}\"
  }"
```

---

## 4. Sõnumimallid

### 4.1 Tooteteadaanne

```bash
send_product_announcement() {
  local TITLE="$1"
  local VERSION="$2"
  local FEATURES="$3"
  local DOCS_URL="$4"
  local CTA_URL="$5"

  curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
    -H "Content-Type: application/json" \
    -d "$(python3 -c "
import json
card = {
    'msg_type': 'interactive',
    'card': {
        'header': {
            'title': {'tag': 'plain_text', 'content': '${TITLE}'},
            'template': 'green'
        },
        'elements': [
            {'tag': 'markdown', 'content': '**Version ${VERSION}** is now available!\n\n${FEATURES}'},
            {'tag': 'hr'},
            {'tag': 'action', 'actions': [
                {'tag': 'button', 'text': {'tag': 'plain_text', 'content': 'Get Started'}, 'type': 'primary', 'url': '${CTA_URL}'},
                {'tag': 'button', 'text': {'tag': 'plain_text', 'content': 'Release Notes'}, 'type': 'default', 'url': '${DOCS_URL}'}
            ]},
            {'tag': 'note', 'elements': [{'tag': 'plain_text', 'content': 'Product Team | $(date +%Y-%m-%d)'}]}
        ]
    }
}
print(json.dumps(card))
")"
}
```

### 4.2 Meeskonna uuendus / nädalaaruanne

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "interactive",
    "card": {
      "header": {
        "title": {"tag": "plain_text", "content": "Weekly Marketing Report - W03 2025"},
        "template": "blue"
      },
      "elements": [
        {
          "tag": "column_set",
          "flex_mode": "bisect",
          "columns": [
            {
              "tag": "column",
              "width": "weighted",
              "weight": 1,
              "elements": [
                {"tag": "markdown", "content": "**Traffic**\n\nSessions: **45,230**\nUnique Visitors: **32,100**\nBounce Rate: **42%**"}
              ]
            },
            {
              "tag": "column",
              "width": "weighted",
              "weight": 1,
              "elements": [
                {"tag": "markdown", "content": "**Conversions**\n\nSignups: **580**\nTrials: **120**\nPaid: **34**"}
              ]
            }
          ]
        },
        {"tag": "hr"},
        {
          "tag": "markdown",
          "content": "**Top Performing Content:**\n1. \"10 Tips for Better SEO\" - 8,200 views\n2. \"Product Comparison Guide\" - 5,100 views\n3. \"Customer Success Story: Acme Corp\" - 3,800 views\n\n**Action Items:**\n- [ ] Publish Q1 campaign landing page\n- [ ] Review ad spend allocation\n- [ ] Schedule social media posts for next week"
        },
        {
          "tag": "action",
          "actions": [
            {
              "tag": "button",
              "text": {"tag": "plain_text", "content": "Full Dashboard"},
              "type": "primary",
              "url": "https://example.com/dashboard"
            }
          ]
        },
        {
          "tag": "note",
          "elements": [
            {"tag": "plain_text", "content": "Marketing Team | Auto-generated weekly report"}
          ]
        }
      ]
    }
  }'
```

### 4.3 Sündmuse teavitus

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "interactive",
    "card": {
      "header": {
        "title": {"tag": "plain_text", "content": "Upcoming Webinar: AI in Marketing"},
        "template": "purple"
      },
      "elements": [
        {
          "tag": "markdown",
          "content": "Join us for an exclusive webinar on leveraging AI for marketing success.\n\n**Date:** Thursday, January 30, 2025\n**Time:** 2:00 PM - 3:30 PM (PST)\n**Speaker:** Jane Smith, VP of Marketing\n**Format:** Live presentation + Q&A\n\n**What you will learn:**\n- How to use AI for content personalization\n- Automating campaign optimization\n- Measuring AI-driven marketing ROI"
        },
        {"tag": "hr"},
        {
          "tag": "action",
          "actions": [
            {
              "tag": "button",
              "text": {"tag": "plain_text", "content": "Register Now"},
              "type": "primary",
              "url": "https://example.com/webinar/register"
            },
            {
              "tag": "button",
              "text": {"tag": "plain_text", "content": "Add to Calendar"},
              "type": "default",
              "url": "https://example.com/webinar/calendar"
            }
          ]
        },
        {
          "tag": "note",
          "elements": [
            {"tag": "plain_text", "content": "Limited to 200 seats | Free for all team members"}
          ]
        }
      ]
    }
  }'
```

### 4.4 Turunduskampaania hoiatus

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "interactive",
    "card": {
      "header": {
        "title": {"tag": "plain_text", "content": "Campaign Alert: Budget Threshold Reached"},
        "template": "orange"
      },
      "elements": [
        {
          "tag": "markdown",
          "content": "**Google Ads - Q1 Brand Campaign** has reached **80%** of its monthly budget.\n\n| Metric | Value |\n|--------|-------|\n| Budget | $10,000 |\n| Spent | $8,042 |\n| Remaining | $1,958 |\n| Days Left | 8 |\n| Projected Overspend | $2,100 |\n\n**Recommendation:** Reduce daily bid cap by 15% or pause low-performing ad groups."
        },
        {
          "tag": "action",
          "actions": [
            {
              "tag": "button",
              "text": {"tag": "plain_text", "content": "Adjust Budget"},
              "type": "danger",
              "url": "https://ads.google.com/campaigns"
            },
            {
              "tag": "button",
              "text": {"tag": "plain_text", "content": "View Campaign"},
              "type": "default",
              "url": "https://example.com/campaigns/q1-brand"
            }
          ]
        }
      ]
    }
  }'
```

---

## 5. Abiline: kaartide programmiline koostamine ja saatmine

Keerukate või dünaamiliste kaartide puhul kasuta JSON-sisu koostamiseks Pythonit:

```bash
python3 -c "
import json, subprocess, os

webhook_url = os.environ.get('FEISHU_WEBHOOK_URL', '')
if not webhook_url:
    print('Error: FEISHU_WEBHOOK_URL not set')
    exit(1)

# Build card dynamically
card = {
    'msg_type': 'interactive',
    'card': {
        'header': {
            'title': {'tag': 'plain_text', 'content': 'Dynamic Card Title'},
            'template': 'blue'
        },
        'elements': []
    }
}

# Add content blocks
card['card']['elements'].append({
    'tag': 'markdown',
    'content': 'This card was built programmatically.\n\n**Key metrics:**\n- Users: 10,000\n- Revenue: \$50,000'
})

# Add a divider
card['card']['elements'].append({'tag': 'hr'})

# Add buttons
card['card']['elements'].append({
    'tag': 'action',
    'actions': [
        {
            'tag': 'button',
            'text': {'tag': 'plain_text', 'content': 'Learn More'},
            'type': 'primary',
            'url': 'https://example.com'
        }
    ]
})

# Add footer
card['card']['elements'].append({
    'tag': 'note',
    'elements': [{'tag': 'plain_text', 'content': 'Sent via OpenClaudia'}]
})

payload = json.dumps(card)
result = subprocess.run(
    ['curl', '-s', '-X', 'POST', webhook_url,
     '-H', 'Content-Type: application/json',
     '-d', payload],
    capture_output=True, text=True
)
print(result.stdout)
"
```

---

## 6. Kakskeelne tugi (hiina + inglise)

Kui saadad sõnumeid, mis vajavad nii hiina- kui ka ingliskeelset sisu, kasuta vormindatud teksti `post`-vormingut, mis toetab mitut lokaati. Feishu kuvab lokaadi, mis vastab kasutaja keeleseadele.

```bash
curl -s -X POST "${FEISHU_WEBHOOK_URL}" \
  -H "Content-Type: application/json" \
  -d '{
    "msg_type": "post",
    "content": {
      "post": {
        "zh_cn": {
          "title": "重要通知：系统维护",
          "content": [
            [
              {"tag": "text", "text": "我们将于 "},
              {"tag": "text", "text": "1月25日 22:00-02:00 (北京时间)", "un_escape": true},
              {"tag": "text", "text": " 进行系统维护。"}
            ],
            [
              {"tag": "text", "text": "维护期间服务将暂时不可用。如有问题请联系 "},
              {"tag": "a", "text": "技术支持", "href": "https://example.com/support"},
              {"tag": "text", "text": "。"}
            ]
          ]
        },
        "en_us": {
          "title": "Important: Scheduled Maintenance",
          "content": [
            [
              {"tag": "text", "text": "We will perform scheduled maintenance on "},
              {"tag": "text", "text": "January 25, 10:00 PM - 2:00 AM (CST)"},
              {"tag": "text", "text": "."}
            ],
            [
              {"tag": "text", "text": "Services will be temporarily unavailable. For questions, contact "},
              {"tag": "a", "text": "Support", "href": "https://example.com/support"},
              {"tag": "text", "text": "."}
            ]
          ]
        }
      }
    }
  }'
```

---

## 7. Vigade käsitlemine

### Veebihaagi vastusekoodid

| Kood | StatusMessage | Tähendus |
|------|---------------|---------|
| 0 | `"success"` | Sõnum saadeti edukalt |
| 9499 | `"Bad Request"` | Vigane JSON või puuduvad kohustuslikud väljad |
| 19001 | `"param invalid"` | Kehtetu msg_type või sisu vorming |
| 19002 | `"sign match fail"` | Allkirja kontroll ebaõnnestus (kontrolli ajatemplit ja saladust) |
| 19021 | `"request too fast"` | Kiiruspiirang: kuni 100 sõnumit minutis veebihaagi kohta |
| 19024 | `"bot not in chat"` | Bot on grupist eemaldatud |

### Levinud probleemide lahendamine

**Sõnumit ei toimetatud kohale:**
- Kontrolli, et veebihaagi URL on õige ja bot on endiselt grupis
- Kontrolli, et `msg_type` vastab sisu struktuurile
- Allkirjastatud veebihaakide puhul veendu, et ajatempel jääb praegusest ajast 1 tunni piiresse

**Kaarti ei kuvata:**
- Kontrolli JSON-struktuuri: nii header kui ka elements on kohustuslikud
- Nuppude URL-id peavad algama `http://` või `https://`
- Kaartides toetatakse Markdowni piiratud alamhulka: paks kiri, kaldkiri, lingid, loendid, tabelid

**API loa vead:**
- Rentniku ligipääsuload aeguvad 2 tunni pärast; hangi enne saatmist uus
- Veendu, et rakendus on arendajakonsoolis avaldatud ja kinnitatud
- Kontrolli, et õigus `im:message:send_as_bot` on antud

### Kiiruspiirangud

| Integratsioon | Piirang |
|-------------|-------|
| Custom Bot Webhook | 100 sõnumit minutis veebihaagi kohta |
| App Bot API (sõnumid) | 50 sõnumit sekundis rakenduse kohta |
| App Bot API (loa värskendamine) | 500 päringut tunnis |

---

## 8. Töövoog: turundussisu postitamine Feishusse/Larki

Kui kasutaja palub saata turundussisu Feishusse või Larki, järgi seda töövoogu:

### 1. samm: kontrolli mandaate

Veendu, et `FEISHU_WEBHOOK_URL` või `FEISHU_APP_ID` + `FEISHU_APP_SECRET` on määratud. Kui ei ole, juhenda kasutajat seadistamisel.

### 2. samm: määra sõnumi tüüp

| Kasutaja kavatsus | Soovitatav vorming |
|-------------|-------------------|
| Kiire tekstiuuendus | Lihttekst (`msg_type: text`) |
| Vormindatud teadaanne | Vormindatud tekst (`msg_type: post`) |
| Mõõdikutega turundusaruanne | Veergudega interaktiivne kaart |
| Toote turuletoomine | Nuppudega interaktiivne kaart |
| Sündmuse teavitus | CTA-nuppudega interaktiivne kaart |
| Hoiatus või ettevaatusmärkus | `red`/`orange` päisega interaktiivne kaart |

### 3. samm: koosta sõnum

- Kasuta sobivat malli 4. jaotisest
- Kohanda sisu kasutaja nõuetele
- Kakskeelsete gruppide jaoks lisa nii `zh_cn` kui ka `en_us` sisu

### 4. samm: eelvaade ja kinnitus

Näita kasutajale enne saatmist kogu JSON-sisu. Selgita, milline sõnum välja näeb.

**Ära kunagi saada automaatselt ilma kasutaja selgesõnalise kinnituseta.**

### 5. samm: saada

Käivita curl-käsk ja anna vastusest teada.

### 6. samm: kontrolli

Kontrolli vastusekoodi. Kui `code: 0`, toimetati sõnum kohale. Vea korral otsi lahendust ülaltoodud veatabelist.

---

## 9. Edasijõudnutele: sõnumikaardi JSON-skeemi kiirteatmik

```
{
  "msg_type": "interactive",
  "card": {
    "header": {                          // Required
      "title": {
        "tag": "plain_text",
        "content": "string"
      },
      "template": "blue|green|red|..."   // Header color
    },
    "elements": [                        // Required, array of blocks
      {"tag": "markdown", "content": "..."}, // Rich content
      {"tag": "hr"},                         // Divider line
      {"tag": "img", "img_key": "...", "alt": {...}}, // Image
      {                                      // Multi-column layout
        "tag": "column_set",
        "flex_mode": "bisect|trisect|...",
        "columns": [
          {"tag": "column", "width": "weighted", "weight": 1, "elements": [...]}
        ]
      },
      {                                      // Action buttons
        "tag": "action",
        "actions": [
          {"tag": "button", "text": {...}, "type": "primary|danger|default", "url": "..."}
        ]
      },
      {                                      // Footer note
        "tag": "note",
        "elements": [{"tag": "plain_text", "content": "..."}]
      }
    ]
  }
}
```

---

## Nõuanded

- **Alusta veebihaakidest.** Custom Bot veebihaagid ei nõua mingit koodiinfrastruktuuri ja need saab seadistada vähem kui minutiga.
- **Kasuta interaktiivseid kaarte** kõige jaoks, mis on enamat kui lihttekst. Need on loetavamad ja ajendavad tegutsema.
- **Lisa tegevusnupud** igale turunduskaardile. Suuna saajad maandumislehele, töölauale või registreerumisvormile.
- **Kasuta kakskeelset tuge**, kui sinu meeskond kasutab nii Feishut kui ka Larki või kui liikmeid on nii Hiinas kui ka mujal maailmas.
- **Austa kiiruspiiranguid.** Massiliste sõnumite puhul (nt mitmesse gruppi saatmine) lisa päringute vahele 1-sekundiline viivitus.
- **Testi esmalt privaatses grupis**, enne kui saadad suurtesse meeskonnakanalitesse.
- **Hoia kaardi sisu lühike.** Kaardi sisu maksimaalne maht on umbes 30 KB. Väga pikkade aruannete puhul lisa link välisele lehele.
- **Kasuta Feishu Message Card Builderit** kaartide visuaalseks kujundamiseks: [https://open.feishu.cn/tool/cardbuilder](https://open.feishu.cn/tool/cardbuilder) (Feishu) või [https://open.larksuite.com/tool/cardbuilder](https://open.larksuite.com/tool/cardbuilder) (Lark).