Skip to main content

# SLARK Simple LARK(Feishu) SDK

Project description

Slark

PyPI version

Simple LARK(Feishu) SDK

Usage

pip install slark
from slark import AsyncLark

lark = AsyncLark(
    app_id=xxx, app_secret=xxx, webhook=xxx
)

Spreadsheets

Read table

await lark.sheets.read(
    url: str,
    *,
    start_row: int = 0,
    start_col: int = 0,
    rows: Union[int, None] = None,
    cols: Union[int, None] = None,
    has_header: bool = True,
    dropna: bool = True,
    valueRenderOption: Union[
        Literal["ToString", "Formula", "FormattedValue", "UnformattedValue"], None
    ] = None,
    dateTimeRenderOption: Union[Literal["FormattedString"], None] = None,
    user_id_type: Union[Literal["open_id", "union_id"], None] = None,
    return_raw: bool = False,
    timeout: Union[httpx.Timeout, None] = None,
)
    """从电子表格读取数据,该接口返回数据的最大限制为 10 MB。该接口不支持获取跨表引用和数组公式的计算结果。

    Args:
        url (str): 电子表格的 URL 链接
        start_row (int, optional): 起始行数. Defaults to 0.
        start_col (int, optional): 起始列数. Defaults to 0.
        rows (Union[int, None], optional): 读取行数. Defaults to None.
        cols (Union[int, None], optional): 读取列数. Defaults to None.
        has_header (bool, optional): 是否包括标题. Defaults to True.
        dropna (bool, optional): 是否去除全为空的行/列. Defaults to True.
        valueRenderOption (Literal[ "ToString", "Formula", "FormattedValue", "UnformattedValue" ], None, optional): \
            指定单元格数据的格式。可选值如下所示。\
            当参数缺省时,默认不进行公式计算,返回公式本身,且单元格为数值格式。\
            ToString:返回纯文本的值(数值类型除外)。\
            Formula:单元格中含有公式时,返回公式本身。\
            FormattedValue:计算并格式化单元格。\
            UnformattedValue:计算但不对单元格进行格式化. Defaults to None.
        dateTimeRenderOption (Literal["FormattedString"], None, optional):\
            指定数据类型为日期、时间、或时间日期的单元格数据的格式。\
            若不传值,默认返回浮点数值,整数部分为自 1899 年 12 月 30 日以来的天数;\
            小数部分为该时间占 24 小时的份额。\
            例如:若时间为 1900 年 1 月 1 日中午 12 点,则默认返回 2.5。\
            其中,2 表示 1900 年 1 月 1 日为 1899 年12 月 30 日之后的 2 天;\
            0.5 表示 12 点占 24 小时的二分之一,即 12/24=0.5。\
            可选值为 FormattedString,此时接口将计算并对日期、时间、或时间日期类型的数据格式化并返回格式化后的字符串,但不会对数字进行格式化。. Defaults to None.
        user_id_type (Literal["open_id", "union_id"], None, optional):\
            当单元格中包含@用户等涉及用户信息的元素时,该参数可指定返回的用户 ID 类型。\
            默认为 lark_id,建议选择 open_id 或 union_id. Defaults to None.
        timeout (Union[httpx.Timeout, None], optional): _description_. Defaults to None.

    Returns:
        Union[pd.DataFrame, List[List[CellTypes]]]: 读取的数据,\
            如果 return_raw 为 True 则返回 List[List[CellTypes]],否则返回 pd.DataFrame
    """

Write table

await lark.sheets.write(url, data=df, start_row=0, start_col=2)
await lark.sheets.append(url, data=df, start_row=0, start_col=2)
await lark.sheets.prepend(url, data=df, start_row=0, start_col=2)

Webhook

Send webhook message

await lark.webhook.post_error_card(
    self,
    msg: str,
    traceback: str,
    title,
    subtitle: Union[str, None] = None,
    timeout: Union[httpx.Timeout, None] = None,
)

await lark.webhook.post_success_card(
    self,
    msg: str,
    title,
    subtitle: Union[str, None] = None,
    timeout: Union[httpx.Timeout, None] = None,
)

Bitables

  1. Read
await lark.bitables.read(
    url: str,
    *,
    rows: Union[int, None] = None,
    field_names: Union[List[str], None] = None,
    return_raw: bool = False,
    timezone: Union[str, None] = "Asia/Shanghai",
    timeout: Union[httpx.Timeout, None] = None,
)
    """从多维表格中读取数据

    Args:
        url (str): 多维表格分享链接
        rows (Union[int, None], optional): 读取的行数. Defaults to None.
        field_names (Union[List[str], None], optional): 读取的列名. Defaults to None.
        raw (bool, optional): 是否返回原始数据. Defaults to False.
        timezone (Union[str, None], optional): 时区,仅在raw=False时有效. Defaults to "Asia/Shanghai".

    Returns:
        Union[dict, pd.DataFrame]: 当raw=True时返回原始数据,否则返回DataFrame\
            返回的 dataframe 的 index 为对应记录的 record id
    """
  1. Append
await lark.bitables.append(
    url: str,
    *,
    data: pd.DataFrame,
    timezone: Union[str, None] = "Asia/Shanghai",
    timeout: Union[httpx.Timeout, None] = None,
)
    """向多维表格中追加数据

    Args:
        url (str): 多维表格分享链接
        data (pd.DataFrame): 要追加的数据
        timezone (Union[str, None], optional): 时区. Defaults to "Asia/Shanghai".
        timeout (Union[httpx.Timeout, None], optional): Timeout. Defaults to None.

    Returns:
        List[RecordResponseData]: 追加的数据
    """
  1. Update
await lark.bitables.update(
    url: str,
    *,
    data: pd.DataFrame,
    timezone: Union[str, None] = "Asia/Shanghai",
    timeout: Union[httpx.Timeout, None] = None,
)
    """更新多维表格中的数据

    Args:
        url (str): 多维表格分享链接
        data (pd.DataFrame): 要更新的数据,index 为更新记录的 record id
        timezone (Union[str, None], optional): 时区. Defaults to "Asia/Shanghai".
        timeout (Union[httpx.Timeout, None], optional): Timeout. Defaults to None.

    Returns:
        List[RecordResponseData]: 更新的数据
    """
  1. Delete
await lark.bitables.delete(
    url: str, *, record_ids: List[str], timeout: Union[httpx.Timeout, None] = None
)
    """删除多维表格中的数据

    Args:
        url (str): 多维表格分享链接
        record_ids (List[str]): 要删除的记录ID
        timeout (Union[httpx.Timeout, None], optional): Timeout. Defaults to None.
    """

Document

  1. Read to Markdown
await lark.docs.read_markdown(
    url: str,
    *,
    assets_path: str = "./assets/",
    timeout: Union[httpx.Timeout, None] = None,
)
    """从文档中读取 markdown 内容

    Args:
        url (str): 文档分享链接。
        assets_path (str, optional): 保存图片的目录. Defaults to "./assets/".
        timeout (Union[httpx.Timeout, None], optional): 超时时间. Defaults to None.

    Returns:
        str: markdown 内容
    """

目前支持的文档元素:

  1. 文本,格式包括超链接、粗体、斜体、下划线、删除线,不支持字体颜色、背景颜色
  2. 标题,支持 1-9 级标题
  3. 有序列表
  4. 无序列表
  5. 代码块
  6. 引用
  7. 公式
  8. 待办事项,支持勾选和未勾选状态,不支持用户
  9. 高亮块
  10. 分割线
  11. 图片
  12. 表格
  13. 画板(导出为图片)

暂不支持的元素:

  1. 指定@用户
  2. 评论
  3. 文件
  4. 多维表格
  5. 群聊卡片
  6. 链接卡片(官方不支持)
  7. 分栏布局
  8. iframe
  9. 三方应用
  10. 任务
  11. OKR
  12. Jira问题
  13. 议程

Event Callback

from dotenv import find_dotenv, load_dotenv

from slark import AsyncLark, EventManager
from slark.types.event.common import EventType, LarkEvent

load_dotenv(find_dotenv())
lark = AsyncLark()
em = EventManager(lark)


@em.register(EventType.IM_MESSAGE_RECEIVE_V1)
async def test_event(lark: AsyncLark, ev: LarkEvent):
    message = ev.event.message
    if message.message_type == "image":
        await lark.messages.get_resource(
            message.message_id, message.content.image_key, "image", "uploads"
        )
    else:
        await lark.messages.send_markdown(
            ev.event.tenant_key,
            ev.event.sender_open_id,
            f"你发送了一条消息:{message.content}",
        )


em.listen(port=54467)

Card Callback

from typing import Optional
from typing_extensions import Literal

import slark.types.card as card


def build_docdb_save_card(
    stage: Literal["ask", "saving", "fail", "success"],
    input_value: Optional[str] = None,
    value: Optional[dict] = {},
) -> card.InteractiveCard:
    if stage == "ask" or stage == "fail":
        disabled = False
    else:
        disabled = True
    msg = {
        "ask": "是否保存至文档库",
        "saving": "保存中, 请稍后",
        "fail": "保存失败, 请重试",
        "success": "保存成功",
    }
    color = {
        "ask": card.CardTemplate.BLUE,
        "saving": card.CardTemplate.ORANGE,
        "fail": card.CardTemplate.RED,
        "success": card.CardTemplate.GREEN,
    }
    return card.InteractiveCard(
        config=card.CardConfig(update_multi=True),
        i18n_elements=card.I18nBody(
            zh_cn=[
                card.FormElement(
                    tag="form",
                    name="form_save_to_docdb",
                    elements=[
                        card.InputBoxElement(
                            name="input_save_to_docdb",
                            required=False,
                            disabled=disabled,
                            default_value=input_value,
                            placeholder=card.PlainText(tag="plain_text", content="请输入文档描述"),
                        ),
                        card.ColumnSetElement(
                            margin="10px 0px 10px 0px",
                            columns=[
                                card.ColumnElement(
                                    elements=[
                                        card.ButtonElement(
                                            type="primary",
                                            disabled=disabled,
                                            text=card.PlainText(tag="plain_text", content="保存"),
                                            form_action_type="submit",
                                            name="button_save_to_docdb",
                                            behaviors=[
                                                card.CallbackBehavior(
                                                    value={
                                                        "event": "save_to_docdb",
                                                        **value,
                                                    }
                                                )
                                            ],
                                        )
                                    ],
                                ),
                            ],
                        ),
                    ],
                )
            ],
        ),
        i18n_header=card.I18nHeader(
            zh_cn=card.I18nHeaderElement(
                title=card.PlainTextElement(content=msg[stage]),
                template=color[stage],
                ud_icon=card.IconElement(token=card.UDIconToken.FILE_LINK_DOCX_OUTLINED),
            ),
        ),
    )

server.py

import anyio
from dotenv import find_dotenv, load_dotenv
from fastapi import BackgroundTasks
from fastapi.responses import JSONResponse

from card_docdb import build_docdb_save_card
from slark import AsyncLark, EventManager
from slark.types.event import CallbackResponse, CallbackToast, EventType, LarkEvent

load_dotenv(find_dotenv())
lark = AsyncLark()
em = EventManager(lark)


@em.register(EventType.IM_MESSAGE_RECEIVE_V1)
async def test_event(lark: AsyncLark, ev: LarkEvent):
    value = {"file_key": ev.event.message.content, "file_type": "message"}
    card = build_docdb_save_card(stage="ask", value=value)
    return await lark.messages.reply_card(ev.event.message.message_id, card=card)


@em.register(EventType.CARD_ACTION_TRIGGER, run_in_thread=False)
async def card_action_trigger(lark: AsyncLark, ev: LarkEvent):
    value = ev.event.action.value
    from pprint import pprint
    pprint(value)
    if value["event"] != "save_to_docdb":
        return JSONResponse(
            content=CallbackResponse(
                toast=CallbackToast(type="info", content="未知事件"),
            ).model_dump(),
        )

    async def reply():
        input_value = ev.event.action.form_value.get("input_save_to_docdb")
        card = build_docdb_save_card(stage="saving", input_value=input_value, value=value)
        await lark.messages.edit_card(ev.event.context.open_message_id, card)
        await anyio.sleep(1)
        card = build_docdb_save_card(stage="success", input_value=input_value, value=value)
        await lark.messages.edit_card(ev.event.context.open_message_id, card)
        await anyio.sleep(1)
        card = build_docdb_save_card(stage="fail", input_value=input_value, value=value)
        await lark.messages.edit_card(ev.event.context.open_message_id, card)

    tasks = BackgroundTasks()
    tasks.add_task(reply)
    return JSONResponse(
        content=CallbackResponse(
            toast=CallbackToast(type="info", content="保存中"),
        ).model_dump(),
        background=tasks,
    )


em.listen(port=54467)

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

slark-0.1.19.tar.gz (103.4 kB view details)

Uploaded Source

Built Distribution

slark-0.1.19-py3-none-any.whl (147.3 kB view details)

Uploaded Python 3

File details

Details for the file slark-0.1.19.tar.gz.

File metadata

  • Download URL: slark-0.1.19.tar.gz
  • Upload date:
  • Size: 103.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.4 Darwin/23.6.0

File hashes

Hashes for slark-0.1.19.tar.gz
Algorithm Hash digest
SHA256 0de75c680f3276ff9a068f727bdec3814a9375e873396a4c19e9a477ce83ea73
MD5 66cb9f26f46a5cd27fcd3bfcfaf0f24f
BLAKE2b-256 da72326f10c7f94652f08b2ad0337e630e95c7321d802be7a8238c2ab6694509

See more details on using hashes here.

File details

Details for the file slark-0.1.19-py3-none-any.whl.

File metadata

  • Download URL: slark-0.1.19-py3-none-any.whl
  • Upload date:
  • Size: 147.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.4 Darwin/23.6.0

File hashes

Hashes for slark-0.1.19-py3-none-any.whl
Algorithm Hash digest
SHA256 1fbf60091bc66ad6a95e99f260e27b1ec04c43c08f0a6cbb91e2b86924d1bbc3
MD5 fad7666738f2d96fc6635316e401668d
BLAKE2b-256 f399fde4acafa9124ce77b78c40020d563dc8e23b94473c1a4093051aad69962

See more details on using hashes here.

Supported by

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