{"record":{"id":"c01e1d61d1eb6ee5","repo":"jackwener/OpenCLI","slug":"raw-does-not-look-like-a-dianping-shop-id","errorCode":null,"errorMessage":"${raw}' does not look like a dianping shop id","messagePattern":"(.+?)' does not look like a dianping shop id","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"warning","filePath":"clis/dianping/utils.js","lineNumber":83,"sourceCode":"}\n\nexport function requireSearchLimit(value) {\n    const raw = value == null || value === '' ? 15 : value;\n    const limit = typeof raw === 'number' ? raw : Number(String(raw).trim());\n    if (!Number.isInteger(limit) || limit < 1 || limit > 15) {\n        throw new ArgumentError('limit must be an integer between 1 and 15 (dianping single page)');\n    }\n    return limit;\n}\n\nexport function normalizeShopId(rawInput) {\n    const raw = String(rawInput || '').trim();\n    if (!raw) throw new ArgumentError('shop_id must be a non-empty string');\n\n    const idMatch = raw.match(/\\/shop\\/([^?#/]+)/);\n    const shopId = idMatch ? idMatch[1] : raw;\n    if (!/^[A-Za-z0-9_-]+$/.test(shopId)) {\n        throw new ArgumentError(`'${raw}' does not look like a dianping shop id`);\n    }\n    return shopId;\n}\n\nexport function wrapDianpingStep(label, fn) {\n    return Promise.resolve()\n        .then(fn)\n        .catch((err) => {\n            if (err?.code) throw err;\n            const message = err?.message || String(err);\n            throw new CommandExecutionError(`dianping ${label} failed: ${message}`);\n        });\n}\n\n/**\n * Throw the right typed error for a dianping page that didn't render data.\n * The site short-circuits HTML when bot/login checks trip — typically\n * redirects to verify.meituan.com (Yoda icon-tap captcha) or to a login","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/dianping/utils.js#L65-L101","documentation":"normalizeShopId validates the shop_id argument passed to dianping shop commands. It accepts either a bare shop id (letters, digits, underscore, dash) or a full dianping URL containing /shop/<id>, and throws ArgumentError when the resolved id fails the /^[A-Za-z0-9_-]+$/ check. This guard exists because an invalid id would silently produce garbage requests against www.dianping.com.","triggerScenarios":"Calling shopId (and any shop-detail command that funnels through normalizeShopId) with input whose extracted id contains characters outside [A-Za-z0-9_-] — e.g. pasted text with spaces, CJK characters, trailing punctuation, or a URL not matching /shop/<id> such as m.dianping.com or a short link.","commonSituations":"Pasting a shop URL from the mobile app share sheet (different path shape), copying the shop name instead of its id, extra whitespace/quotes around the id from shell quoting, or passing a dianping search URL rather than a shop page URL.","solutions":["Pass the numeric shop id from a www.dianping.com/shop/<id> URL, e.g. '1234567'.","If passing a URL, make sure it contains /shop/<id>; strip query strings, trailing slashes, and surrounding whitespace/quotes first.","If you have a mobile/share URL, open it and take the canonical www.dianping.com/shop/<id> id.","Pre-validate the id with /^[A-Za-z0-9_-]+$/ (or extract via /\\/shop\\/([^?#\\/]+)/) before calling."],"exampleFix":"// before\nawait shopId('https://m.dianping.com/shoppage/xiaoguoxianyuluo/20083463/');\n// after\nawait shopId('20083463'); // or a www.dianping.com/shop/20083463 URL","handlingStrategy":"validation","validationCode":"function looksLikeShopId(input) {\n  const raw = String(input || '').trim();\n  const m = raw.match(/\\/shop\\/([^?#\\/]+)/);\n  return Boolean((m ? m[1] : raw) && /^[A-Za-z0-9_-]+$/.test(m ? m[1] : raw));\n}\nif (!looksLikeShopId(input)) throw new Error('pass a dianping shop id or a www.dianping.com/shop/<id> URL');","typeGuard":"function isDianpingShopId(v) {\n  return typeof v === 'string' && /^[A-Za-z0-9_-]+$/.test(v.trim());\n}","tryCatchPattern":"try {\n  await shopId(input);\n} catch (err) {\n  if (err.code === 'ARGUMENT_ERROR') {\n    console.error(`Invalid shop id '${input}': use the numeric id from a www.dianping.com/shop/<id> URL`);\n  } else throw err;\n}","preventionTips":["Extract the id from the canonical www.dianping.com/shop/<id> URL, not mobile/share links.","Trim whitespace and strip surrounding quotes before passing ids from shell args or files.","Pre-validate with /^[A-Za-z0-9_-]+$/ in scripts that batch-process shop ids."],"tags":["argument-validation","input-parsing","dianping"],"backgroundTag":"invalid-argument-format","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}