{"url_pattern":"^https?://xueqiu\\.com(/.*)?$","site_name":"xueqiu","allowed_domains":["example.com","stock.xueqiu.com","xueqiu.com"],"tools":[{"name":"xueqiu_earnings_date","description":"获取股票预计财报发布日期（公司大事）","inputSchema":{"type":"object","properties":{"symbol":{"type":"string","description":"股票代码，如 SH600519、SZ000858、00700"},"next":{"type":"boolean","description":"仅返回最近一次未发布的财报日期","default":false},"limit":{"type":"number","description":"返回数量，默认 10","default":10}},"required":["symbol"]},"handler":"(params) => {\n  const args = Object.assign({\"next\": false, \"limit\": 10}, params || {});\n  let data = null;\n  let __wbContextUrl = globalThis.location?.href || '';\n  let __wbContextDocument = globalThis.document || null;\n    const __wbDefault = (value, fallback) => (value === undefined || value === null || value === '' ? fallback : value);\n    const __wbJoin = (value, separator) => Array.isArray(value) ? value.join(separator) : (value ?? '');\n    const __wbGet = (value, path) => {\n      if (!path) return value;\n      return String(path).split('.').reduce((acc, part) => (acc == null ? undefined : acc[part]), value);\n    };\n    const __wbBaseUrl = () => (__wbContextUrl || globalThis.location?.href || 'https://example.com/');\n    const __wbResolve = (target, base) => {\n      if (target == null) return '';\n      const text = String(target);\n      try {\n        return /^https?:/i.test(text) ? text : new URL(text, base || __wbBaseUrl()).toString();\n      } catch (_error) {\n        return text;\n      }\n    };\n    const __wbFetch = async (target, options) => {\n      const url = __wbResolve(target, __wbBaseUrl());\n      const resp = await globalThis.fetch(url, Object.assign({ credentials: 'include' }, options || {}));\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} for ${url}`);\n      }\n      const text = await resp.text();\n      try {\n        return { url, text, data: JSON.parse(text) };\n      } catch (_error) {\n        return { url, text, data: text };\n      }\n    };\n  return (async () => {\n    {\n      const __wbResp = await __wbFetch(\"https://xueqiu.com\");\n      __wbContextUrl = __wbResp.url;\n      __wbContextDocument = new DOMParser().parseFromString(__wbResp.text, 'text/html');\n      data = __wbContextDocument;\n    }\n    {\n      const document = __wbContextDocument || globalThis.document;\n      const location = new URL(__wbBaseUrl());\n      const window = { document, location };\n      const fetch = (target, options) => globalThis.fetch(__wbResolve(target, __wbBaseUrl()), Object.assign({ credentials: 'include' }, options || {}));\n      data = await (((async () => {\n  const symbol = (((args.symbol)) || '').toUpperCase();\n  const onlyNext = (args.next);\n  if (!symbol) throw new Error('Missing argument: symbol');\n  const resp = await fetch(\n    `https://stock.xueqiu.com/v5/stock/screener/event/list.json?symbol=${encodeURIComponent(symbol)}&page=1&size=100`,\n    { credentials: 'include' }\n  );\n  if (!resp.ok) throw new Error('HTTP ' + resp.status + ' Hint: Not logged in?');\n  const d = await resp.json();\n  if (!d.data || !d.data.items) throw new Error('获取失败: ' + JSON.stringify(d));\n\n  // subtype 2 = 预计财报发布\n  let items = d.data.items.filter(item => item.subtype === 2);\n\n  const now = Date.now();\n  let results = items.map(item => {\n    const ts = item.timestamp;\n    const dateStr = ts ? new Date(ts).toISOString().split('T')[0] : null;\n    const isFuture = ts && ts > now;\n    return {\n      date: dateStr,\n      report: item.message,\n      status: isFuture ? '⏳ 未发布' : '✅ 已发布',\n      _ts: ts,\n      _future: isFuture\n    };\n  });\n\n  if (onlyNext) {\n    const future = results.filter(r => r._future).sort((a, b) => a._ts - b._ts);\n    results = future.length ? [future[0]] : [];\n  }\n\n  return results;\n})())());\n    }\n    {\n      const source = Array.isArray(data) ? data : (data == null ? [] : [data]);\n      data = source.map((item, index) => ({\n        \"date\": item.date,\n        \"report\": item.report,\n        \"status\": item.status,\n      }));\n    }\n    if (Array.isArray(data)) data = data.slice(0, Number(args.limit) || 0);\n    return data;\n  })();\n}"},{"name":"xueqiu_feed","description":"获取雪球首页时间线（关注用户的动态）","inputSchema":{"type":"object","properties":{"page":{"type":"string","description":"页码，默认 1"},"count":{"type":"string","description":"每页数量，默认 20"}},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      var page = parseInt(args.page) || 1;\n      var count = Math.min(parseInt(args.count) || 20, 50);\n      var resp = await fetch('https://xueqiu.com/v4/statuses/home_timeline.json?page=' + page + '&count=' + count, {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      var d = await resp.json();\n\n      var strip = function(html) {\n        return (html || '').replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').trim();\n      };\n\n      var list = d.home_timeline || d.list || [];\n      var items = list.slice(0, count).map(function(item) {\n        var user = item.user || {};\n        return {\n          id: item.id,\n          text: strip(item.description).substring(0, 200),\n          url: 'https://xueqiu.com/' + user.id + '/' + item.id,\n          author: user.screen_name,\n          author_id: user.id,\n          verified: user.verified_description || null,\n          likes: item.fav_count,\n          retweets: item.retweet_count,\n          replies: item.reply_count,\n          created_at: item.created_at ? new Date(item.created_at).toISOString() : null\n        };\n      });\n\n      return {page: page, count: items.length, items: items};\n  };\n  return run(params || {});\n}"},{"name":"xueqiu_hot","description":"获取雪球热门动态","inputSchema":{"type":"object","properties":{"count":{"type":"string","description":"返回数量，默认 20，最大 50"}},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      var count = Math.min(parseInt(args.count) || 20, 50);\n      var resp = await fetch('https://xueqiu.com/statuses/hot/listV3.json?source=hot&page=1', {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      var d = await resp.json();\n      var list = (d.list || []).slice(0, count);\n\n      var strip = function(html) {\n        return (html || '').replace(/<[^>]+>/g, '').replace(/&nbsp;/g, ' ').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>').trim();\n      };\n\n      var items = list.map(function(item, i) {\n        var user = item.user || {};\n        return {\n          rank: i + 1,\n          id: item.id,\n          text: strip(item.description).substring(0, 200),\n          url: 'https://xueqiu.com/' + user.id + '/' + item.id,\n          author: user.screen_name,\n          author_id: user.id,\n          likes: item.fav_count,\n          retweets: item.retweet_count,\n          replies: item.reply_count,\n          created_at: item.created_at ? new Date(item.created_at).toISOString() : null\n        };\n      });\n\n      return {count: items.length, items: items};\n  };\n  return run(params || {});\n}"},{"name":"xueqiu_hot_stock","description":"获取雪球热门股票榜","inputSchema":{"type":"object","properties":{"count":{"type":"string","description":"返回数量，默认 20，最大 50"},"type":{"type":"string","description":"榜单类型：10=人气榜(默认) 12=关注榜"}},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      var count = Math.min(parseInt(args.count) || 20, 50);\n      var type = args.type || '10';\n      var resp = await fetch('https://stock.xueqiu.com/v5/stock/hot_stock/list.json?size=' + count + '&type=' + type, {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      var d = await resp.json();\n      if (!d.data || !d.data.items) return {error: '获取失败', raw: d};\n\n      var items = d.data.items.map(function(s, i) {\n        return {\n          rank: i + 1,\n          symbol: s.symbol,\n          name: s.name,\n          price: s.current,\n          changePercent: s.percent != null ? s.percent.toFixed(2) + '%' : null,\n          heat: s.value,\n          rank_change: s.rank_change,\n          url: 'https://xueqiu.com/S/' + s.symbol\n        };\n      });\n\n      return {type: type === '12' ? '关注榜' : '人气榜', count: items.length, items: items};\n  };\n  return run(params || {});\n}"},{"name":"xueqiu_search","description":"搜索雪球股票（代码或名称）","inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"搜索关键词，如 茅台、AAPL、腾讯"},"count":{"type":"string","description":"返回数量，默认 10"}},"required":["query"]},"handler":"(params) => {\n  const run = async function(args) {\n\n      if (!args.query) return {error: 'Missing argument: query'};\n      var count = Math.min(parseInt(args.count) || 10, 20);\n      var resp = await fetch('https://xueqiu.com/stock/search.json?code=' + encodeURIComponent(args.query) + '&size=' + count, {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      var d = await resp.json();\n      var stocks = (d.stocks || []).map(function(s) {\n        var symbol = '';\n        if (s.exchange === 'SH' || s.exchange === 'SZ' || s.exchange === 'BJ') {\n          symbol = s.code.startsWith(s.exchange) ? s.code : s.exchange + s.code;\n        } else {\n          symbol = s.code;\n        }\n        return {\n          symbol: symbol,\n          name: s.name,\n          exchange: s.exchange,\n          price: s.current,\n          changePercent: s.percentage != null ? s.percentage.toFixed(2) + '%' : null,\n          url: 'https://xueqiu.com/S/' + symbol\n        };\n      });\n      return {keyword: args.query, count: stocks.length, results: stocks};\n  };\n  return run(params || {});\n}"},{"name":"xueqiu_stock","description":"获取雪球股票实时行情","inputSchema":{"type":"object","properties":{"symbol":{"type":"string","description":"股票代码，如 SH600519、SZ000858、AAPL、00700"}},"required":["symbol"]},"handler":"(params) => {\n  const run = async function(args) {\n\n      if (!args.symbol) return {error: 'Missing argument: symbol', hint: '请输入股票代码，如 SH600519'};\n\n      var symbol = args.symbol.toUpperCase();\n      var resp = await fetch('https://stock.xueqiu.com/v5/stock/batch/quote.json?symbol=' + encodeURIComponent(symbol), {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      var d = await resp.json();\n\n      if (!d.data || !d.data.items || d.data.items.length === 0) return {error: '未找到股票: ' + symbol};\n\n      function fmtAmount(v) {\n        if (v == null) return null;\n        if (Math.abs(v) >= 1e12) return (v / 1e12).toFixed(2) + '万亿';\n        if (Math.abs(v) >= 1e8) return (v / 1e8).toFixed(2) + '亿';\n        if (Math.abs(v) >= 1e4) return (v / 1e4).toFixed(2) + '万';\n        return v.toString();\n      }\n\n      var item = d.data.items[0];\n      var q = item.quote || {};\n      var m = item.market || {};\n\n      return {\n        name: q.name,\n        symbol: q.symbol,\n        exchange: q.exchange,\n        currency: q.currency,\n        price: q.current,\n        change: q.chg,\n        changePercent: q.percent != null ? q.percent.toFixed(2) + '%' : null,\n        open: q.open,\n        high: q.high,\n        low: q.low,\n        prevClose: q.last_close,\n        amplitude: q.amplitude != null ? q.amplitude.toFixed(2) + '%' : null,\n        volume: q.volume,\n        amount: fmtAmount(q.amount),\n        turnover_rate: q.turnover_rate != null ? q.turnover_rate.toFixed(2) + '%' : null,\n        marketCap: fmtAmount(q.market_capital),\n        floatMarketCap: fmtAmount(q.float_market_capital),\n        ytdPercent: q.current_year_percent != null ? q.current_year_percent.toFixed(2) + '%' : null,\n        market_status: m.status || null,\n        time: q.timestamp ? new Date(q.timestamp).toISOString() : null,\n        url: 'https://xueqiu.com/S/' + q.symbol\n      };\n  };\n  return run(params || {});\n}"},{"name":"xueqiu_watchlist","description":"获取雪球自选股列表","inputSchema":{"type":"object","properties":{"category":{"type":"string","description":"分类：1=自选(默认) 2=持仓 3=关注"}},"required":null},"handler":"(params) => {\n  const run = async function(args) {\n\n      var category = parseInt(args.category) || 1;\n      var resp = await fetch('https://stock.xueqiu.com/v5/stock/portfolio/stock/list.json?size=100&category=' + category + '&pid=-1', {credentials: 'include'});\n      if (!resp.ok) return {error: 'HTTP ' + resp.status, hint: 'Not logged in?'};\n      var d = await resp.json();\n      if (!d.data || !d.data.stocks) return {error: '获取失败，可能未登录', raw: d};\n\n      var items = d.data.stocks.map(function(s) {\n        return {\n          symbol: s.symbol,\n          name: s.name,\n          price: s.current,\n          change: s.chg,\n          changePercent: s.percent != null ? s.percent.toFixed(2) + '%' : null,\n          volume: s.volume,\n          url: 'https://xueqiu.com/S/' + s.symbol\n        };\n      });\n\n      var labels = {1: '自选股', 2: '持仓', 3: '关注'};\n      return {category: labels[category] || category, count: items.length, items: items};\n  };\n  return run(params || {});\n}"}]}