← Back to Skills Marketplace
longbai

未来清晨

by Bai Loong · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
70
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install futuremorning
Description
查询未来清晨的活动信息。当用户询问未来清晨的活动、近期活动、活动安排、某个活动详情时使用。支持列出所有活动和根据活动ID获取详情。默认输出JSON,用户要求时可输出Markdown格式。
README (SKILL.md)

概述

未来清晨活动查询工具。

使用时机

  • 用户问未来清晨有什么活动、近期活动列表
  • 用户想了解某个具体活动的详情
  • 用户提到"未来清晨"

通用参数

CLUB_ID = 018ce711-aeab-f611-7900-486c089013e4
API_BASE = https://api.cumen.fun/api/xx.cumen.v1.CumenService

功能一:列出所有活动

node -e "
const https = require('https');
const API = 'https://api.cumen.fun/api/xx.cumen.v1.CumenService/ListCampaignsOfClub';
const CLUB_ID = '018ce711-aeab-f611-7900-486c089013e4';

function post(url, body) {
  return new Promise((resolve, reject) => {
    const data = JSON.stringify(body);
    const req = https.request(url, { method: 'POST', headers: { 'Content-Type': 'application/json' } }, (res) => {
      let buf = '';
      res.on('data', (c) => (buf += c));
      res.on('end', () => { try { resolve(JSON.parse(buf)); } catch { reject(new Error(buf)); } });
    });
    req.on('error', reject);
    req.write(data);
    req.end();
  });
}

function toUTC8(ts) {
  if (!ts || ts.startsWith('1970')) return null;
  const d = new Date(ts);
  return new Date(d.getTime() + 8 * 3600000).toISOString().replace('Z', '+08:00');
}

const STATUS = { CAMPAIGN_STATUS_ONGOING: 'ONGOING', CAMPAIGN_STATUS_ENDED: 'ENDED', CAMPAIGN_STATUS_BLOCKED: 'BLOCKED' };

post(API, { clubId: CLUB_ID }).then((resp) => {
  const items = resp.items || [];
  const result = items.map((item) => {
    const c = item.campaign || {};
    return {
      id: c.id || '',
      title: c.title || '',
      price: (c.price || {}).value || '0',
      address: item.address || '',
      start_time: toUTC8(c.start_time),
      end_time: toUTC8(c.end_time),
      join_deadline: toUTC8(c.join_deadline),
      capacity: c.person_number_of_team || 0,
      status: STATUS[c.status] || c.status || '',
      finished: c.finish || false,
    };
  });
  console.log(JSON.stringify(result, null, 2));
}).catch((e) => { console.error(e.message); process.exit(1); });
"

Markdown 输出格式

用户要求 Markdown 时,将结果渲染为表格:

## 未来清晨 活动列表 (14个)

| # | 标题 | 价格 | 地址 | 开始时间 | 结束时间 | 名额 | 已结束 |
|---|------|------|------|----------|----------|------|--------|
| 1 | 示例活动|未来清晨 | ¥39 | ... | 04-12 14:00 | 04-12 16:00 | 20 | 否 |

时间格式 MM-DD HH:mm,标题中 | 替换为

功能二:获取活动详情

CAMPAIGN_ID 替换为实际活动 ID:

node -e "
const https = require('https');
const API = 'https://api.cumen.fun/api/xx.cumen.v1.CumenService/GetCampaign';
const CAMPAIGN_ID = 'CAMPAIGN_ID';

function post(url, body) {
  return new Promise((resolve, reject) => {
    const data = JSON.stringify(body);
    const req = https.request(url, { method: 'POST', headers: { 'Content-Type': 'application/json' } }, (res) => {
      let buf = '';
      res.on('data', (c) => (buf += c));
      res.on('end', () => { try { resolve(JSON.parse(buf)); } catch { reject(new Error(buf)); } });
    });
    req.on('error', reject);
    req.write(data);
    req.end();
  });
}

function toUTC8(ts) {
  if (!ts || ts.startsWith('1970')) return null;
  const d = new Date(ts);
  return new Date(d.getTime() + 8 * 3600000).toISOString().replace('Z', '+08:00');
}

const STATUS = { CAMPAIGN_STATUS_ONGOING: 'ONGOING', CAMPAIGN_STATUS_ENDED: 'ENDED' };
const KIND = { 1: 'CREATE_TEAM', 2: 'GROUP_PURCHASE', 3: 'LEAGUES' };

post(API, { campaignId: CAMPAIGN_ID }).then((data) => {
  const c = data.campaign || {};
  const p = data.post || {};
  const priceVal = (typeof data.price === 'object' ? data.price.value : data.price) || (c.price || {}).value || '0';
  const poi = p.poi || {};
  const loc = poi.location_gcj02 || {};
  const result = {
    id: c.id,
    title: c.title,
    status: STATUS[c.status] || c.status,
    kind: KIND[c.kind] || c.kind,
    price: priceVal,
    start_time: toUTC8(c.start_time),
    end_time: toUTC8(c.end_time),
    join_deadline: toUTC8(c.join_deadline),
    quit_deadline: toUTC8(c.quit_deadline),
    capacity: c.person_number_of_team || 0,
    address: { name: poi.name || '', detail: poi.address || '', latitude: loc.latitude, longitude: loc.longitude },
    summary: p.summary || '',
    description: p.content || '',
    images: (p.images || []).map((img) => img.url),
    share_count: data.share_count || 0,
    comment_count: data.comment_count || 0,
    finished: c.finish || false,
  };
  console.log(JSON.stringify(result, null, 2));
}).catch((e) => { console.error(e.message); process.exit(1); });
"

Markdown 输出格式

用户要求 Markdown 时:

## 示例活动|未来清晨

- **状态**: 进行中
- **类型**: 组团
- **价格**: ¥39
- **时间**: 2026-04-12 14:00 ~ 16:00
- **报名截止**: 2026-04-12 14:00
- **名额**: 20人
- **地点**: 活动地点
- **地址**: 详细地址
- **分享**: 6 | **评论**: 3

> 活动描述内容...
> ...

字段映射规则

  • price: 优先取顶层 price.value(可能为 string 或 object),否则取 campaign.price.value
  • address: 列表接口取 item.address,详情接口从 post.poi 提取 name/address/location
  • description: 取 post.content
  • summary: 取 post.summary
  • images: 取 post.images[].url
  • 时间:UTC → UTC+8 ISO 格式
  • status 映射:CAMPAIGN_STATUS_ONGOINGONGOINGCAMPAIGN_STATUS_ENDEDENDEDCAMPAIGN_STATUS_BLOCKEDBLOCKED
  • kind 映射:1CREATE_TEAM2GROUP_PURCHASE3LEAGUES

注意事项

  • ListCampaignsOfClub 返回的活动不保证按时间排序
  • 活动描述 (post.content) 可能包含 emoji 和富文本格式
  • 时间均为 UTC,需转为 UTC+8 展示
Usage Guidance
这个技能看起来确实是为查询“未来清晨”俱乐部的活动而写,但在决定安装/使用前请注意: - SKILL.md 使用 node -e 直接执行 JavaScript,但技能元数据没有声明 node 为必需二进制;如果您允许技能在运行时执行脚本,请确保运行环境中 Node.js 的版本与安全策略符合要求。 - 脚本会向外部主机 api.cumen.fun 发送请求——源码/主页未知,建议先确认该域名的可信度、隐私政策和是否需要认证。若担心数据外泄,请在受控网络或沙箱中测试。 - 技能会处理并展示地点坐标与富文本(可能含 emoji 或 HTML),请注意在呈现到终端/网页时的 XSS 或隐私风险。 - 建议索要技能来源或主页、让发布者在元数据中声明“需要 node”以及说明 api.cumen.fun 的用途/是否需要凭证;在缺乏这些信息前,将其视为有风险并谨慎使用。
Capability Analysis
Type: OpenClaw Skill Name: futuremorning Version: 1.0.0 The skill uses `node -e` to execute JavaScript code that performs network requests to `api.cumen.fun`. While the functionality is aligned with the stated purpose of querying club activities, the implementation in `SKILL.md` is vulnerable to command injection because it uses simple string substitution for the `CAMPAIGN_ID` parameter within a shell command. This allows a potentially malicious input to break out of the script context and execute arbitrary code on the host system.
Capability Assessment
Purpose & Capability
技能描述为“查询未来清晨的活动”,SKILL.md 的实际行为正是通过两个 HTTP POST 接口列出活动和查询活动详情,功能上与描述一致。但 SKILL.md 通过 node -e 直接运行 JavaScript,这要求运行环境中有 Node.js;技能元数据未列出任何必需二进制(如 node),这是元数据与实际需求的不一致。同时 SKILL.md 使用了硬编码的 CLUB_ID 和 api.cumen.fun 域,元数据中没有解释这些来源或必要性。
Instruction Scope
运行指令只做网络 POST 请求到 https://api.cumen.fun 的两个端点、处理响应并输出 JSON/Markdown,不读取本地文件或其他环境变量,也不要求用户凭据。范围总体限于活动查询,但会向一个外部主机发送请求并解析返回的地点/坐标/文本,可能获取或显示位置相关信息或富文本。
Install Mechanism
无安装说明、无代码文件、仅为说明性脚本;因此没有在安装阶段下载或写入第三方代码的风险。
Credentials
技能不请求任何环境变量或凭证(元数据中也未声明),这与当前脚本一致。但脚本会向外部 API 发送请求:如果该 API 实际需要认证或返回敏感信息,技能未说明如何安全处理这些凭证或数据。硬编码的 CLUB_ID 存在但并不显得敏感。
Persistence & Privilege
技能未请求常驻(always)或修改系统/其他技能配置,允许代理自主调用为默认行为,未发现额外特权请求。
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install futuremorning
  3. After installation, invoke the skill by name or use /futuremorning
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial publication
Metadata
Slug futuremorning
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is 未来清晨?

查询未来清晨的活动信息。当用户询问未来清晨的活动、近期活动、活动安排、某个活动详情时使用。支持列出所有活动和根据活动ID获取详情。默认输出JSON,用户要求时可输出Markdown格式。 It is an AI Agent Skill for Claude Code / OpenClaw, with 70 downloads so far.

How do I install 未来清晨?

Run "/install futuremorning" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is 未来清晨 free?

Yes, 未来清晨 is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does 未来清晨 support?

未来清晨 is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created 未来清晨?

It is built and maintained by Bai Loong (@longbai); the current version is v1.0.0.

💬 Comments