xhs-kit 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,350 @@
1
+ ---
2
+ name: post-to-xhs
3
+ description: 小红书内容发布与管理助手。当用户要求登录、发小红书、搜索小红书、评论点赞收藏等任何小红书相关操作时使用。
4
+ metadata: {"openclaw": {"emoji": "📕", "requires": {"bins": ["convert"]}}}
5
+ ---
6
+
7
+ # xhs-kit 使用方式
8
+
9
+ ## 安装
10
+
11
+ 首次使用需要确认环境中有 Python 解释器。
12
+
13
+ ```bash
14
+ # 使用 pip 安装
15
+ pip install -U xhs-kit
16
+
17
+ # 安装 Playwright 浏览器(必需)
18
+ playwright install chromium
19
+ ```
20
+
21
+ ## ⚠️ 重要:所有操作必须先登录
22
+
23
+ **小红书所有功能(发布、搜索、点赞、评论等)都需要先登录。**
24
+
25
+ ### 1. 检查登录状态
26
+
27
+ 执行任何操作前,先检查是否已登录:
28
+
29
+ ```bash
30
+ xhs-kit status
31
+ ```
32
+
33
+ - 输出 `✅ 已登录`:表示检测到 cookies 文件(quick 模式),通常可以继续操作
34
+ - 输出 `❌ 未登录`:表示未检测到 cookies 文件,必须先执行登录步骤
35
+
36
+ 如果出现发布或者评论无结果等错误,说明 cookies 可能已过期或不可用,此时使用 verify 模式做真实校验:
37
+
38
+ ```bash
39
+ xhs-kit status --verify
40
+ ```
41
+
42
+ - 输出 `✅ 已登录(verify)`:cookies 仍可用,失败原因更可能是内容不可见或参数问题
43
+ - 输出 `❌ 未登录(verify)`:cookies 可能过期或被风控,需要重新登录
44
+
45
+ ### 2. 登录方式(带 fallback 逻辑)
46
+
47
+ **推荐按以下顺序尝试登录:**
48
+
49
+ **方式一:终端二维码(Claude Code / Open Code 推荐)**
50
+ ```bash
51
+ xhs-kit login-qrcode --terminal
52
+ ```
53
+ - ⚠️ 需要安装 zbar 库才能解析二维码:
54
+ - macOS: `brew install zbar`
55
+ - Ubuntu: `apt install libzbar0`
56
+ - 如果未安装 zbar,会自动保存二维码图片并提示路径
57
+ - 用户扫码后按回车完成登录
58
+ - 如果终端显示失败,fallback 到方式二
59
+
60
+ **方式二:浏览器扫码登录(有图形界面的环境)**
61
+ ```bash
62
+ xhs-kit login-browser
63
+ ```
64
+ - 会弹出浏览器窗口供用户扫码
65
+ - 如果无法弹出浏览器(如远程服务器无图形界面),会提示使用二维码方式
66
+
67
+ **方式三:保存二维码图片(OpenClaw 推荐)**
68
+ ```bash
69
+ xhs-kit login-qrcode --save /tmp/qrcode.png
70
+ ```
71
+ - 将二维码图片发送给用户扫码
72
+ - 用户扫码后按回车完成登录
73
+
74
+ **如果以上方式都失败:**
75
+ - 提醒用户需要安装浏览器环境(Playwright + Chromium)
76
+ - 或需要图形界面环境
77
+
78
+ ### 3. 登录参数说明
79
+
80
+ `login-qrcode` 参数:
81
+
82
+ | 参数 | 类型 | 必需 | 说明 |
83
+ |------|------|------|------|
84
+ | `-s/--save` | string | ❌ | 保存二维码图片到指定路径 |
85
+ | `--terminal/--no-terminal` | flag | ❌ | 是否在终端显示二维码(默认 terminal) |
86
+
87
+ 登录成功后,cookies 会保存到本地文件,后续操作自动复用(有效期约 7-30 天)。
88
+
89
+ ## ⚠️ Agent 运行建议(Claude Code / OpenClaw / MCP)
90
+
91
+ - **不要在每次调用前都执行 `status --verify`**,这会频繁打开页面,增加开销和风控风险。
92
+ - 默认使用 `xhs-kit status`(quick)即可。
93
+ - **仅当出现如下错误时**再执行 `xhs-kit status --verify`:
94
+ - `未找到笔记详情(可能 xsec_token 失效、未登录或触发风控)`
95
+ - 发布/点赞/评论失败且多次重试无效
96
+ - 如果 `status --verify` 判定未登录,再让用户执行 `xhs-kit login-browser`(需要人工扫码)。
97
+
98
+ ## 发布操作
99
+
100
+ ### 发布图文内容
101
+
102
+ 命令:`xhs-kit publish`
103
+
104
+ **参数:**(`-i/--image`、`--tag` 可多次指定)
105
+
106
+ | 参数 | 类型 | 必需 | 说明 |
107
+ |------|------|------|------|
108
+ | `-t/--title` | string | ✅ | 文字标题 |
109
+ | `-c/--content` | string | ✅ | 文字正文内容 |
110
+ | `-i/--image` | string | ✅ | 图片路径(可多次指定) |
111
+ | `--tag` | string | ❌ | 话题标签(可多次指定) |
112
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
113
+
114
+ 示例:
115
+
116
+ ```bash
117
+ xhs-kit publish -t "标题" -c "正文" -i /abs/1.jpg -i /abs/2.jpg --tag 旅行 --tag 美食
118
+ ```
119
+
120
+ ### 发布视频内容
121
+
122
+ 命令:`xhs-kit publish-video`
123
+
124
+ **参数:**
125
+
126
+ | 参数 | 类型 | 必需 | 说明 |
127
+ |------|------|------|------|
128
+ | `-t/--title` | string | ✅ | 文字标题 |
129
+ | `-c/--content` | string | ✅ | 文字正文内容 |
130
+ | `-v/--video` | string | ✅ | 视频路径 |
131
+ | `--tag` | string | ❌ | 话题标签(可多次指定) |
132
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
133
+
134
+ 示例:
135
+
136
+ ```bash
137
+ xhs-kit publish-video -t "标题" -c "正文" -v /abs/video.mp4
138
+ ```
139
+
140
+ ### 发布文字配图(文字卡片)
141
+
142
+ 命令:`xhs-kit publish-text-card`
143
+
144
+ **参数:**(`-p/--page`、`--tag` 可多次指定)
145
+
146
+ | 参数 | 类型 | 必需 | 说明 |
147
+ |------|------|------|------|
148
+ | `-c/--cover` | string | ✅ | 封面文字 |
149
+ | `-p/--page` | string | ❌ | 正文页文字(可多次指定,最多17页) |
150
+ | `-s/--style` | string | ❌ | 卡片样式:基础\|边框\|备忘\|手写\|便签\|涂写\|简约\|光影\|几何 |
151
+ | `-t/--title` | string | ❌ | 文字标题 |
152
+ | `--content` | string | ❌ | 文字正文内容 |
153
+ | `--tag` | string | ❌ | 话题标签(可多次指定) |
154
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
155
+
156
+ 示例:
157
+
158
+ ```bash
159
+ xhs-kit publish-text-card -c "封面" -p "第一页" -p "第二页" -s "基础" -t "笔记标题"
160
+ ```
161
+
162
+ ## 浏览/搜索
163
+
164
+ ### 搜索内容
165
+
166
+ 命令:`xhs-kit search`
167
+
168
+ **参数:**
169
+
170
+ | 参数 | 类型 | 必需 | 说明 |
171
+ |------|------|------|------|
172
+ | `-k/--keyword` | string | ✅ | 搜索关键词 |
173
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
174
+
175
+ **输出:**
176
+
177
+ 命令会打印搜索到的笔记列表。每条结果会包含:
178
+
179
+ - `ID`:对应后续命令里的 `--feed-id`
180
+ - `xsec_token`:对应后续命令里的 `--xsec-token`
181
+
182
+ 示例(截断):
183
+
184
+ ```text
185
+ 1. 标题...
186
+ 作者: xxx | 点赞: 123
187
+ ID: 1234567890abcdef
188
+ xsec_token: xsec_xxx
189
+ ```
190
+
191
+ ### 获取首页推荐列表
192
+
193
+ 命令:`xhs-kit list-feeds`
194
+
195
+ **参数:**
196
+
197
+ | 参数 | 类型 | 必需 | 说明 |
198
+ |------|------|------|------|
199
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
200
+
201
+ **输出:** JSON 格式的推荐笔记列表
202
+
203
+ 示例:
204
+
205
+ ```bash
206
+ xhs-kit list-feeds
207
+ ```
208
+
209
+ ### 获取笔记详情
210
+
211
+ 命令:`xhs-kit detail`
212
+
213
+ **参数:**
214
+
215
+ | 参数 | 类型 | 必需 | 说明 |
216
+ |------|------|------|------|
217
+ | `--feed-id` | string | ✅ | 笔记 ID |
218
+ | `--xsec-token` | string | ✅ | 访问令牌 |
219
+ | `--load-comments` | flag | ❌ | 是否加载评论(默认 false) |
220
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
221
+
222
+ **输出:** JSON 格式的笔记详情(包括标题、内容、图片、互动数据等)
223
+
224
+ 示例:
225
+
226
+ ```bash
227
+ xhs-kit detail --feed-id FEED_ID --xsec-token XSEC_TOKEN
228
+ xhs-kit detail --feed-id FEED_ID --xsec-token XSEC_TOKEN --load-comments
229
+ ```
230
+
231
+ ### 获取用户主页
232
+
233
+ 命令:`xhs-kit user-profile`
234
+
235
+ **参数:**
236
+
237
+ | 参数 | 类型 | 必需 | 说明 |
238
+ |------|------|------|------|
239
+ | `--user-id` | string | ✅ | 用户 ID |
240
+ | `--xsec-token` | string | ✅ | 访问令牌 |
241
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
242
+
243
+ **输出:** JSON 格式的用户主页信息
244
+
245
+ 示例:
246
+
247
+ ```bash
248
+ xhs-kit user-profile --user-id USER_ID --xsec-token XSEC_TOKEN
249
+ ```
250
+
251
+ ## 互动(点赞/收藏/评论)
252
+
253
+ 以下命令需要你先从搜索结果或笔记链接中拿到 `feed_id` 和 `xsec_token`。
254
+
255
+ ### 点赞/取消点赞
256
+
257
+ 命令:`xhs-kit like`
258
+
259
+ **参数:**
260
+
261
+ | 参数 | 类型 | 必需 | 说明 |
262
+ |------|------|------|------|
263
+ | `--feed-id` | string | ✅ | 笔记 ID |
264
+ | `--xsec-token` | string | ✅ | 访问令牌 |
265
+ | `--unlike` | flag | ❌ | 取消点赞(默认 false 为点赞) |
266
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
267
+
268
+ 示例:
269
+
270
+ ```bash
271
+ xhs-kit like --feed-id FEED_ID --xsec-token XSEC_TOKEN
272
+ xhs-kit like --feed-id FEED_ID --xsec-token XSEC_TOKEN --unlike
273
+ ```
274
+
275
+ ### 收藏/取消收藏
276
+
277
+ 命令:`xhs-kit favorite`
278
+
279
+ **参数:**
280
+
281
+ | 参数 | 类型 | 必需 | 说明 |
282
+ |------|------|------|------|
283
+ | `--feed-id` | string | ✅ | 笔记 ID |
284
+ | `--xsec-token` | string | ✅ | 访问令牌 |
285
+ | `--unfavorite` | flag | ❌ | 取消收藏(默认 false 为收藏) |
286
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
287
+
288
+ 示例:
289
+
290
+ ```bash
291
+ xhs-kit favorite --feed-id FEED_ID --xsec-token XSEC_TOKEN
292
+ xhs-kit favorite --feed-id FEED_ID --xsec-token XSEC_TOKEN --unfavorite
293
+ ```
294
+
295
+ ### 发表评论
296
+
297
+ 命令:`xhs-kit comment`
298
+
299
+ **参数:**
300
+
301
+ | 参数 | 类型 | 必需 | 说明 |
302
+ |------|------|------|------|
303
+ | `--feed-id` | string | ✅ | 笔记 ID |
304
+ | `--xsec-token` | string | ✅ | 访问令牌 |
305
+ | `-c/--content` | string | ✅ | 评论内容 |
306
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
307
+
308
+ 示例:
309
+
310
+ ```bash
311
+ xhs-kit comment --feed-id FEED_ID --xsec-token XSEC_TOKEN -c "评论内容"
312
+ ```
313
+
314
+ ### 回复评论
315
+
316
+ 命令:`xhs-kit reply-comment`
317
+
318
+ **参数:**
319
+
320
+ | 参数 | 类型 | 必需 | 说明 |
321
+ |------|------|------|------|
322
+ | `--feed-id` | string | ✅ | 笔记 ID |
323
+ | `--xsec-token` | string | ✅ | 访问令牌 |
324
+ | `-c/--content` | string | ✅ | 回复内容 |
325
+ | `--comment-id` | string | ❌ | 目标评论 ID |
326
+ | `--user-id` | string | ❌ | 目标用户 ID |
327
+ | `--headless/--no-headless` | flag | ❌ | 是否无头模式(默认 headless) |
328
+
329
+ `--comment-id` 和 `--user-id` 至少需要提供一个。
330
+
331
+ 示例:
332
+
333
+ ```bash
334
+ xhs-kit reply-comment --feed-id FEED_ID --xsec-token XSEC_TOKEN -c "回复内容" --comment-id COMMENT_ID
335
+ ```
336
+
337
+
338
+ ## 退出登录
339
+
340
+ 命令:`xhs-kit logout`
341
+
342
+ 会删除本地 cookies。
343
+
344
+ ## (可选)MCP 模式
345
+
346
+ 如果你的运行环境支持 MCP(例如 Claude Desktop / Cursor),可以启动 MCP:
347
+
348
+ ```bash
349
+ xhs-kit serve
350
+ ```
@@ -0,0 +1,55 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Set up Python
16
+ uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.11"
19
+
20
+ - name: Install build dependencies
21
+ run: |
22
+ python -m pip install --upgrade pip
23
+ pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
27
+
28
+ - name: Upload artifacts
29
+ uses: actions/upload-artifact@v4
30
+ with:
31
+ name: dist
32
+ path: dist/
33
+
34
+ publish:
35
+ needs: build
36
+ runs-on: ubuntu-latest
37
+ environment: pypi
38
+ permissions:
39
+ id-token: write
40
+ contents: write
41
+ steps:
42
+ - name: Download artifacts
43
+ uses: actions/download-artifact@v4
44
+ with:
45
+ name: dist
46
+ path: dist/
47
+
48
+ - name: Publish to PyPI
49
+ uses: pypa/gh-action-pypi-publish@release/v1
50
+
51
+ - name: Create GitHub Release
52
+ uses: softprops/action-gh-release@v1
53
+ with:
54
+ generate_release_notes: true
55
+ files: dist/*
@@ -0,0 +1,34 @@
1
+ name: Test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Python 3.12
17
+ uses: actions/setup-python@v5
18
+ with:
19
+ python-version: "3.12"
20
+
21
+ - name: Install dependencies
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ pip install -e ".[dev]"
25
+ pip install pytest-asyncio
26
+ playwright install chromium
27
+
28
+ - name: Run unit tests
29
+ run: |
30
+ pytest tests/test_cookies.py tests/test_cli.py tests/test_mcp_server.py -v
31
+
32
+ - name: Run login tests (without browser)
33
+ run: |
34
+ pytest tests/test_login.py -v --ignore-glob="*browser*" || true
@@ -0,0 +1,38 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ *.egg
11
+
12
+ # Virtual environments
13
+ venv/
14
+ .venv/
15
+ env/
16
+
17
+ # IDE
18
+ .idea/
19
+ .vscode/
20
+ *.swp
21
+ *.swo
22
+
23
+ # Testing
24
+ .pytest_cache/
25
+ .coverage
26
+ htmlcov/
27
+
28
+ # Logs
29
+ *.log
30
+
31
+ # Local config
32
+ .env
33
+ cookies.json
34
+ settings.local.json
35
+
36
+ # OS
37
+ .DS_Store
38
+ Thumbs.db
@@ -0,0 +1,139 @@
1
+ # xhs-kit 项目说明
2
+
3
+ ## 项目概述
4
+
5
+ xhs-kit 是一个小红书自动化工具,基于 Playwright 浏览器自动化框架实现,支持通过 MCP 协议与 AI 助手集成。
6
+
7
+ **核心功能:**
8
+ - 扫码登录(浏览器/二维码两种模式)
9
+ - 发布图文、视频、文字配卡笔记
10
+ - 搜索内容、获取推荐流
11
+ - 点赞、收藏、评论、回复
12
+ - 获取笔记详情、用户主页
13
+ ---
14
+
15
+ ## 实现思路
16
+
17
+ ### 1. 浏览器自动化核心
18
+
19
+ 基于 **Playwright** 模拟真实浏览器行为:
20
+
21
+ - 创建持久化浏览器上下文(Persistent Context)
22
+ - 复用用户数据目录和 cookies,避免重复登录
23
+ - 模拟真实用户操作(点击、输入、滚动等)
24
+ - 拦截和分析网络请求,获取 API 数据
25
+
26
+ 核心文件:`src/xhs_kit.po/browser.py`
27
+
28
+ ### 2. 登录机制
29
+
30
+ 小红书需要登录才能使用,实现了两种登录方式:
31
+
32
+ **浏览器扫码登录:**
33
+ - 弹出浏览器窗口访问小红书登录页
34
+ - 用户扫码后自动保存 cookies
35
+
36
+ **二维码登录(CLI 模式):**
37
+ - 通过截取登录页的二维码获取登录二维码
38
+ - 支持终端显示二维码(需安装 zbar)
39
+ - 支持保存二维码图片
40
+ - 轮询检测登录状态
41
+
42
+ 核心文件:`src/xhs_kit.po/login.py`、`src/xhs_kit.po/cookies.py`
43
+
44
+ ### 3. 内容发布
45
+
46
+ **图文发布:**
47
+ - 访问创作者发布页面
48
+ - 上传图片、填写标题和正文
49
+ - 支持添加话题标签
50
+ - 支持定时发布
51
+
52
+ **文字配卡发布:**
53
+ - 使用小红书自带的文字生图将文字渲染为卡片
54
+ - 支持多页、多种样式(基础、边框、手写等)
55
+
56
+ 核心文件:`src/xhs_kit.po/publish.py`、`src/xhs_kit.po/text_card.py`
57
+
58
+ ### 4. 数据获取
59
+
60
+ **搜索与推荐:**
61
+ - 访问搜索页面,模拟用户输入关键词
62
+ - 监听网络请求拦截搜索结果 API 响应
63
+ - 解析返回的 JSON 数据
64
+
65
+ **笔记详情、用户主页:**
66
+ - 直接访问笔记/用户页面 URL
67
+ - 监听 API 响应获取结构化数据
68
+
69
+ 核心文件:`src/xhs_kit.po/search.py`、`src/xhs_kit.po/feeds.py`、`src/xhs_kit.po/feed_detail.py`
70
+
71
+ ### 5. MCP 协议集成
72
+
73
+ 将上述功能封装为 MCP 工具:
74
+
75
+ ```
76
+ MCP Server (stdio 模式)
77
+ ├── login_with_browser
78
+ ├── check_login_status
79
+ ├── get_login_qrcode
80
+ ├── publish_content
81
+ ├── publish_text_card
82
+ ├── publish_with_video
83
+ ├── search_feeds
84
+ ├── list_feeds
85
+ ├── get_feed_detail
86
+ ├── get_user_profile
87
+ ├── like_feed / favorite_feed
88
+ └── post_comment / reply_comment
89
+ ```
90
+
91
+ 核心文件:`src/xhs_kit.po/mcp_server.py`
92
+
93
+ ### 6. CLI 封装
94
+
95
+ 提供命令行接口 `xhs-kit`,支持所有 MCP 工具的对应命令:
96
+
97
+ 核心文件:`src/xhs_kit.po/cli.py`
98
+
99
+ ---
100
+
101
+ ## 开发规范
102
+
103
+ ### 不修改已有功能
104
+
105
+ **本项目遵循「只修 bug,不改功能」原则:**
106
+
107
+ - ✅ 可以修复现有 bug
108
+ - ✅ 可以优化错误提示和日志
109
+ - ✅ 可以改进代码结构和注释
110
+ - ❌ 不要修改现有功能的业务逻辑
111
+ - ❌ 不要添加未经讨论的新功能
112
+ - ❌ 不要删除或重命名现有接口
113
+
114
+ ### 添加新功能的流程
115
+
116
+ 如果需要添加新功能:
117
+
118
+ 1. 先与项目维护者讨论需求和设计
119
+ 2. 确认后再进行实现
120
+ 3. 新功能应通过 MCP 工具和 CLI 双暴露
121
+
122
+ ### 代码结构
123
+
124
+ ```
125
+ src/xhs_kit.po/
126
+ ├── browser.py # Playwright 浏览器封装
127
+ ├── cookies.py # Cookies 管理
128
+ ├── login.py # 登录逻辑(浏览器/二维码)
129
+ ├── publish.py # 发布图文/视频
130
+ ├── text_card.py # 文字生图生成
131
+ ├── search.py # 搜索功能
132
+ ├── feeds.py # 推荐流获取
133
+ ├── feed_detail.py # 笔记详情
134
+ ├── user_profile.py # 用户主页
135
+ ├── interact.py # 点赞/收藏/评论
136
+ ├── models.py # Pydantic 数据模型
137
+ ├── mcp_server.py # MCP 服务入口
138
+ └── cli.py # 命令行入口
139
+ ```
xhs_kit-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.