@ttmg/cli 0.3.1-unity.15 → 0.3.1-unity.17

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.
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ var cheerio = require('cheerio');
13
13
  var os = require('os');
14
14
  var worker_threads = require('worker_threads');
15
15
  var axios = require('axios');
16
+ var qs = require('qs');
16
17
  var handlebars = require('handlebars');
17
18
  var esbuild = require('esbuild');
18
19
  var archiver = require('archiver');
@@ -21,8 +22,9 @@ var WebSocket = require('ws');
21
22
  var glob = require('glob');
22
23
  var got = require('got');
23
24
  var FormData$1 = require('form-data');
24
- var http = require('http');
25
+ var stream = require('stream');
25
26
  var ttmgPack = require('ttmg-pack');
27
+ var http = require('http');
26
28
  var fs$1 = require('node:fs');
27
29
  var path$1 = require('node:path');
28
30
  var zlib = require('zlib');
@@ -276,7 +278,7 @@ const LOGIN_TT4D = 'https://developers.tiktok.com/passport/web/email/login';
276
278
  const params = {
277
279
  aid: '2471',
278
280
  account_sdk_source: 'web',
279
- sdk_version: '2.1.1',
281
+ sdk_version: '2.1.6-tiktok',
280
282
  };
281
283
  const prompt = inquirer.createPromptModule();
282
284
  async function login() {
@@ -318,8 +320,11 @@ async function login() {
318
320
  const url = LOGIN_TT4D + '?' + new URLSearchParams(params);
319
321
  const headers = {
320
322
  'Content-Type': 'application/x-www-form-urlencoded',
321
- 'User-Agent': 'curl/8.5.0',
322
323
  Accept: '*/*',
324
+ 'Accept-Encoding': 'gzip, deflate, br',
325
+ Origin: 'https://developers.tiktok.com',
326
+ Referer: 'https://developers.tiktok.com/passport/web/email/login',
327
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0 Safari/537.36',
323
328
  };
324
329
  const ora = await import('ora');
325
330
  spinner$1 = ora.default({
@@ -327,12 +332,32 @@ async function login() {
327
332
  spinner: 'dots',
328
333
  });
329
334
  spinner$1.start();
335
+ const data = qs.stringify({
336
+ email,
337
+ password,
338
+ mix_mode: '1',
339
+ fixed_mix_mode: '1',
340
+ });
330
341
  try {
331
- const response = await axios.post(url, {
332
- email,
333
- password,
334
- }, { headers, maxRedirects: 20, timeout: 30000 });
335
- if (response?.data?.data?.user_id) {
342
+ const response = await axios.post(url, data, {
343
+ headers,
344
+ maxRedirects: 20,
345
+ timeout: 30000,
346
+ });
347
+ if (!response?.data?.data?.user_id) {
348
+ const errCode = response.data?.data?.error_code;
349
+ const errMsg = response.data?.data?.description;
350
+ if (errCode || errMsg) {
351
+ spinner$1.fail(chalk.red(`login failed: ${errMsg}${errCode ? `, error_code: ${errCode}` : ''}`));
352
+ }
353
+ else {
354
+ spinner$1.fail(chalk.red(`login failed`));
355
+ console.log(response.data);
356
+ }
357
+ spinner$1.stop();
358
+ process.exit(1);
359
+ }
360
+ else {
336
361
  const data = {
337
362
  email,
338
363
  user_id: response?.data?.data?.user_id,
@@ -342,15 +367,15 @@ async function login() {
342
367
  spinner$1.succeed(chalk.bold.green('login successfully!'));
343
368
  process.exit(0);
344
369
  }
345
- else {
346
- spinner$1.fail(chalk.red(`login failed: ${response.data?.data?.description || response.data?.data?.error_code}`));
347
- spinner$1.stop();
348
- process.exit(1);
349
- }
350
370
  }
351
371
  catch (error) {
352
- spinner$1.fail(chalk.red(`❌:${error.message}, please check your network, make sure your Shell can access TikTok Developer Platform, you can try by run command 'curl https://developers.tiktok.com' to check if it's accessible;\n`));
353
- console.log(chalk.yellow('🔔 You can follow this doc to modify your terminal network settings:'), chalk.underline.yellow('https://bytedance.larkoffice.com/wiki/ZblJwT0ZNil9jJkS8EgcFlcQnFc'));
372
+ // 1. Error Title: Red and bold
373
+ spinner$1.fail(chalk.red.bold('Failed to connect to login service'));
374
+ // 2. Description: Normal text with bold keywords
375
+ console.log(" Detected that the current terminal's " +
376
+ chalk.bold('network proxy settings') +
377
+ ' are preventing external network access.', chalk.yellow('Please check your local terminal proxy configuration.'));
378
+ console.log(chalk.yellow('You can follow this doc to modify your terminal network settings:'), chalk.underline.yellow('https://bytedance.larkoffice.com/wiki/ZblJwT0ZNil9jJkS8EgcFlcQnFc'));
354
379
  process.exit(1);
355
380
  }
356
381
  }
@@ -366,8 +391,8 @@ async function request({ url, method, data, headers, params, }) {
366
391
  data,
367
392
  params,
368
393
  headers: {
369
- ...(headers || {}),
370
394
  Cookie: cookie,
395
+ ...(headers || {}),
371
396
  },
372
397
  });
373
398
  // @ts-ignore
@@ -495,7 +520,7 @@ async function fetchGameInfo(clientKey) {
495
520
  params: {
496
521
  client_key: clientKey,
497
522
  // version_type: 1,
498
- },
523
+ }
499
524
  // headers: {
500
525
  // 'x-use-ppe': '1',
501
526
  // 'x-tt-env': 'ppe_mg_revamp',
@@ -1795,6 +1820,50 @@ function showTips(context) {
1795
1820
  console.log(chalk.gray('─────────────────────────────────────────────'));
1796
1821
  }
1797
1822
 
1823
+ /**
1824
+ * 辅助函数:将当前工作目录打包为 Buffer
1825
+ * @param customIgnores - 可选的自定义忽略规则数组 (支持 glob 模式,如 ['dist/**', '*.log'])
1826
+ */
1827
+ const zipCwdToBuffer = (customIgnores = []) => {
1828
+ return new Promise((resolve, reject) => {
1829
+ const chunks = [];
1830
+ const output = new stream.Writable({
1831
+ write(chunk, encoding, next) {
1832
+ chunks.push(chunk);
1833
+ next();
1834
+ },
1835
+ });
1836
+ const archive = archiver('zip', { zlib: { level: 9 } });
1837
+ output.on('finish', () => {
1838
+ resolve(Buffer.concat(chunks));
1839
+ });
1840
+ archive.on('error', err => {
1841
+ reject(err);
1842
+ });
1843
+ archive.pipe(output);
1844
+ const cwd = process.cwd();
1845
+ // 1. 基础忽略列表 (建议保留这些基础规则,防止包过大)
1846
+ const defaultIgnores = [
1847
+ 'node_modules/**',
1848
+ '.git/**',
1849
+ '.DS_Store',
1850
+ ttmgPack.TTMG_TEMP_DIR,
1851
+ '*.zip', // 忽略自身生成的 zip
1852
+ ];
1853
+ // 2. 合并自定义规则
1854
+ // Set 去重,防止重复添加
1855
+ const finalIgnores = Array.from(new Set([...defaultIgnores, ...customIgnores]));
1856
+ // 3. 执行打包
1857
+ // 注意:ignore 规则必须使用正斜杠 /,即使在 Windows 下
1858
+ archive.glob('**/*', {
1859
+ cwd: cwd,
1860
+ ignore: finalIgnores,
1861
+ dot: true, // 包含 .env 等点文件
1862
+ });
1863
+ archive.finalize();
1864
+ });
1865
+ };
1866
+
1798
1867
  const BASE_URL = 'https://developers.tiktok.com';
1799
1868
  const DEV_HEADERS = {
1800
1869
  // 'x-use-ppe': '1',
@@ -1880,6 +1949,23 @@ async function startPrepare(params) {
1880
1949
  if (!fs$1.existsSync(symbolFilePath)) {
1881
1950
  symbolFilePath = path$1.join(process.cwd(), WASM_SYMBOL_FILE_NAME);
1882
1951
  }
1952
+ /**
1953
+ * 判断是否有 symbol 文件,有则上传,没有直接接口报错
1954
+ */
1955
+ if (!fs$1.existsSync(symbolFilePath)) {
1956
+ return {
1957
+ error: {
1958
+ code: 400,
1959
+ message: `${WASM_SYMBOL_FILE_NAME} not found at ${path$1.join(process.cwd())},use unity plugin to rebuild`,
1960
+ client_key: params.client_key,
1961
+ },
1962
+ data: null,
1963
+ ctx: {
1964
+ logid: '',
1965
+ httpStatusCode: 400,
1966
+ },
1967
+ };
1968
+ }
1883
1969
  form.append('wasm_symbol_file', fs$1.createReadStream(symbolFilePath), {
1884
1970
  filename: WASM_SYMBOL_FILE_NAME,
1885
1971
  contentType: 'application/octet-stream',
@@ -2750,22 +2836,57 @@ async function start() {
2750
2836
  /**
2751
2837
  * @description 上传游戏代码到服务器
2752
2838
  */
2839
+ // app.post('/game/upload', async (req, res) => {
2840
+ // /**
2841
+ // * 我要新版本不做开发者选择,直接当前 cwd 作为 entryDir,压缩成 game.zip 进行上传
2842
+ // */
2843
+ // const fileKeys = Object.keys(req.files);
2844
+ // const uploadedFile = req.files[fileKeys[0]];
2845
+ // if (!uploadedFile) {
2846
+ // res.status(400).send({ code: errorCode, data: 'No file uploaded' }); // 使用正确的 HTTP 状态码
2847
+ // return;
2848
+ // }
2849
+ // try {
2850
+ // // 通过 header 获取 desc
2851
+ // const desc = req.headers['ttmg-game-desc'];
2852
+ // // 需要做 decodeURIComponent 处理
2853
+ // const decodedDesc = decodeURIComponent(desc || '--');
2854
+ // // 直接传递需要的信息
2855
+ // const { data, error } = await uploadGameToPlatform({
2856
+ // data: uploadedFile.data, // 这是 Buffer
2857
+ // name: uploadedFile.name, // 这是文件名
2858
+ // clientKey: getClientKey().clientKey,
2859
+ // note: decodedDesc,
2860
+ // appId: store.getState().appId,
2861
+ // sandboxId: store.getState().sandboxId,
2862
+ // });
2863
+ // if (error) {
2864
+ // res.send({ code: errorCode, error });
2865
+ // } else {
2866
+ // res.send({ code: successCode, data });
2867
+ // }
2868
+ // } catch (error) {
2869
+ // // 错误处理可以更具体
2870
+ // let errorMessage = 'An unknown error occurred.';
2871
+ // if (error instanceof Error) {
2872
+ // errorMessage = error.message;
2873
+ // }
2874
+ // // 打印详细错误到服务器日志,方便排查
2875
+ // res.status(500).send({ code: errorCode, data: errorMessage }); // 使用正确的 HTTP 状态码
2876
+ // }
2877
+ // });
2753
2878
  app.post('/game/upload', async (req, res) => {
2754
- const fileKeys = Object.keys(req.files);
2755
- const uploadedFile = req.files[fileKeys[0]];
2756
- if (!uploadedFile) {
2757
- res.status(400).send({ code: errorCode, data: 'No file uploaded' }); // 使用正确的 HTTP 状态码
2758
- return;
2759
- }
2760
2879
  try {
2761
- // 通过 header 获取 desc
2880
+ console.log(`正在打包当前目录: ${process.cwd()} ...`);
2881
+ const gameZipBuffer = await zipCwdToBuffer();
2882
+ // 变成 MB
2883
+ console.log(`打包完成,大小: ${(gameZipBuffer.length / 1024 / 1024).toFixed(2)} MB`);
2762
2884
  const desc = req.headers['ttmg-game-desc'];
2763
- // 需要做 decodeURIComponent 处理
2764
2885
  const decodedDesc = decodeURIComponent(desc || '--');
2765
- // 直接传递需要的信息
2766
2886
  const { data, error } = await uploadGameToPlatform({
2767
- data: uploadedFile.data, // 这是 Buffer
2768
- name: uploadedFile.name, // 这是文件名
2887
+ // @ts-ignore
2888
+ data: gameZipBuffer,
2889
+ name: 'game.zip',
2769
2890
  clientKey: getClientKey().clientKey,
2770
2891
  note: decodedDesc,
2771
2892
  appId: store.getState().appId,
@@ -2779,13 +2900,12 @@ async function start() {
2779
2900
  }
2780
2901
  }
2781
2902
  catch (error) {
2782
- // 错误处理可以更具体
2783
2903
  let errorMessage = 'An unknown error occurred.';
2784
2904
  if (error instanceof Error) {
2785
2905
  errorMessage = error.message;
2786
2906
  }
2787
- // 打印详细错误到服务器日志,方便排查
2788
- res.status(500).send({ code: errorCode, data: errorMessage }); // 使用正确的 HTTP 状态码
2907
+ console.error('Upload failed:', errorMessage);
2908
+ res.status(500).send({ code: errorCode, data: errorMessage });
2789
2909
  }
2790
2910
  });
2791
2911
  app.get('/game/wasm-split-config', (req, res) => {
@@ -3229,7 +3349,7 @@ async function dev() {
3229
3349
  watch();
3230
3350
  }
3231
3351
 
3232
- var version = "0.3.1-unity.15";
3352
+ var version = "0.3.1-unity.17";
3233
3353
  var pkg = {
3234
3354
  version: version};
3235
3355