com.beanbag.tiktokminigames 1.0.0

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.
Files changed (100) hide show
  1. package/DefaultTemplate/backgroundlandscape.png +0 -0
  2. package/DefaultTemplate/backgroundlandscape.png.meta +159 -0
  3. package/DefaultTemplate/backgroundportrait.png +0 -0
  4. package/DefaultTemplate/backgroundportrait.png.meta +159 -0
  5. package/DefaultTemplate/game.js +151 -0
  6. package/DefaultTemplate/game.js.meta +7 -0
  7. package/DefaultTemplate/images/unity_logo.png +0 -0
  8. package/DefaultTemplate/images/unity_logo.png.meta +159 -0
  9. package/DefaultTemplate/images.meta +8 -0
  10. package/DefaultTemplate/plugin-config.js +23 -0
  11. package/DefaultTemplate/plugin-config.js.meta +7 -0
  12. package/DefaultTemplate/plugin.js +1 -0
  13. package/DefaultTemplate/plugin.js.meta +7 -0
  14. package/DefaultTemplate/unity-namespace.js +11 -0
  15. package/DefaultTemplate/unity-namespace.js.meta +7 -0
  16. package/DefaultTemplate/webgl-wasm-split.js +17 -0
  17. package/DefaultTemplate/webgl-wasm-split.js.meta +7 -0
  18. package/DefaultTemplate.meta +8 -0
  19. package/Editor/Extras/Integration/DouYinMiniGameSettings.cs +30 -0
  20. package/Editor/Extras/Integration/DouYinMiniGameSettings.cs.meta +11 -0
  21. package/Editor/Extras/Integration/DouYinMiniGameSettingsEditor.cs +354 -0
  22. package/Editor/Extras/Integration/DouYinMiniGameSettingsEditor.cs.meta +3 -0
  23. package/Editor/Extras/Integration/DouYinSubplatformInterface.cs +153 -0
  24. package/Editor/Extras/Integration/DouYinSubplatformInterface.cs.meta +3 -0
  25. package/Editor/Extras/Integration.meta +8 -0
  26. package/Editor/Extras/Providers/TTMiniGameSupportProvider.cs +148 -0
  27. package/Editor/Extras/Providers/TTMiniGameSupportProvider.cs.meta +3 -0
  28. package/Editor/Extras/Providers.meta +3 -0
  29. package/Editor/Extras/TTEditorSupportProviderRegister.cs +15 -0
  30. package/Editor/Extras/TTEditorSupportProviderRegister.cs.meta +3 -0
  31. package/Editor/Extras.meta +3 -0
  32. package/Editor/ttsdk_tools.dll +0 -0
  33. package/Editor/ttsdk_tools.dll.meta +33 -0
  34. package/Editor/ttsdk_tools.pdb +0 -0
  35. package/Editor/ttsdk_tools.pdb.meta +7 -0
  36. package/Editor.meta +8 -0
  37. package/LitJson/TTLitJson.dll +0 -0
  38. package/LitJson/TTLitJson.dll.meta +33 -0
  39. package/LitJson/TTLitJson.pdb +0 -0
  40. package/LitJson/TTLitJson.pdb.meta +7 -0
  41. package/LitJson.meta +8 -0
  42. package/TTSDK/ttsdk.dll +0 -0
  43. package/TTSDK/ttsdk.dll.meta +33 -0
  44. package/TTSDK/ttsdk.pdb +0 -0
  45. package/TTSDK/ttsdk.pdb.meta +7 -0
  46. package/TTSDK.meta +8 -0
  47. package/WebGL/AssetBundle/DownloadHandlerTTAssetBundle.cs +85 -0
  48. package/WebGL/AssetBundle/DownloadHandlerTTAssetBundle.cs.meta +3 -0
  49. package/WebGL/AssetBundle/TTAssetBundle.cs +72 -0
  50. package/WebGL/AssetBundle/TTAssetBundle.cs.meta +3 -0
  51. package/WebGL/AssetBundle/TTAssetBundleExtensions.cs +25 -0
  52. package/WebGL/AssetBundle/TTAssetBundleExtensions.cs.meta +3 -0
  53. package/WebGL/AssetBundle/TTAssetBundleProviders.cs.txt +1301 -0
  54. package/WebGL/AssetBundle/TTAssetBundleProviders.cs.txt.meta +3 -0
  55. package/WebGL/AssetBundle/TTAssetBundleRequest.cs +96 -0
  56. package/WebGL/AssetBundle/TTAssetBundleRequest.cs.meta +3 -0
  57. package/WebGL/AssetBundle.meta +8 -0
  58. package/WebGL/Compatibility/UnityCacheCompatibility.cs +49 -0
  59. package/WebGL/Compatibility/UnityCacheCompatibility.cs.meta +3 -0
  60. package/WebGL/Compatibility/UnityWebRequestCompatibility.cs +18 -0
  61. package/WebGL/Compatibility/UnityWebRequestCompatibility.cs.meta +3 -0
  62. package/WebGL/Compatibility.meta +3 -0
  63. package/WebGL/FileSystem/TTFileSystemManager.cs +460 -0
  64. package/WebGL/FileSystem/TTFileSystemManager.cs.meta +11 -0
  65. package/WebGL/FileSystem/TTFileSystemManagerDefault.cs +1039 -0
  66. package/WebGL/FileSystem/TTFileSystemManagerDefault.cs.meta +11 -0
  67. package/WebGL/FileSystem/TTFileSystemManagerWebGL.cs +1278 -0
  68. package/WebGL/FileSystem/TTFileSystemManagerWebGL.cs.meta +11 -0
  69. package/WebGL/FileSystem.meta +3 -0
  70. package/WebGL/Input/Input.cs +230 -0
  71. package/WebGL/Input/Input.cs.meta +3 -0
  72. package/WebGL/Input/TTPCInputHandler.cs +199 -0
  73. package/WebGL/Input/TTPCInputHandler.cs.meta +3 -0
  74. package/WebGL/Input.meta +3 -0
  75. package/WebGL/Network/TTUDPSocketHandler.cs +130 -0
  76. package/WebGL/Network/TTUDPSocketHandler.cs.meta +11 -0
  77. package/WebGL/Network.meta +3 -0
  78. package/WebGL/TTAssetBundle.jslib +33 -0
  79. package/WebGL/TTAssetBundle.jslib.meta +32 -0
  80. package/WebGL/TTCallbackHandler.cs +139 -0
  81. package/WebGL/TTCallbackHandler.cs.meta +3 -0
  82. package/WebGL/TTModel.cs +582 -0
  83. package/WebGL/TTModel.cs.meta +11 -0
  84. package/WebGL/TTSDK.jslib +592 -0
  85. package/WebGL/TTSDK.jslib.meta +32 -0
  86. package/WebGL/TTSDKType.cs +10 -0
  87. package/WebGL/TTSDKType.cs.meta +3 -0
  88. package/WebGL/TTStorageManager.cs +155 -0
  89. package/WebGL/TTStorageManager.cs.meta +11 -0
  90. package/WebGL/TTUNBridge.jslib +117 -0
  91. package/WebGL/TTUNBridge.jslib.meta +32 -0
  92. package/WebGL/TTVersionAttribute.cs +21 -0
  93. package/WebGL/TTVersionAttribute.cs.meta +11 -0
  94. package/WebGL/TTWebGL.asmdef +18 -0
  95. package/WebGL/TTWebGL.asmdef.meta +7 -0
  96. package/WebGL/TTWebGLInterface.cs +63 -0
  97. package/WebGL/TTWebGLInterface.cs.meta +11 -0
  98. package/WebGL.meta +8 -0
  99. package/package.json +13 -0
  100. package/package.json.meta +7 -0
@@ -0,0 +1,1039 @@
1
+ using System;
2
+ using System.Collections.Generic;
3
+ using System.IO;
4
+ using System.IO.Compression;
5
+ using System.Security.Cryptography;
6
+ using System.Text;
7
+ namespace TTSDK
8
+ {
9
+ public class TTFileSystemManagerDefault : TTFileSystemManager
10
+ {
11
+ public static readonly TTFileSystemManagerDefault Instance = new TTFileSystemManagerDefault();
12
+
13
+ /// <summary>
14
+ /// 将字符串写入文件(同步)
15
+ /// </summary>
16
+ /// <param name="filePath">要写入的文件路径</param>
17
+ /// <param name="data">要写入的文本</param>
18
+ /// <param name="encoding">指定写入文件的字符编码</param>
19
+ /// <returns>成功返回空字符串,失败返回错误信息</returns>
20
+ public override string WriteFileSync(string filePath, string data, string encoding = "utf8")
21
+ {
22
+ if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(filePath)))
23
+ {
24
+ return $"{System.IO.Path.GetDirectoryName(filePath)} not exist";
25
+ }
26
+
27
+ try
28
+ {
29
+ System.IO.File.WriteAllText(filePath, data);
30
+ }
31
+ catch (System.Exception exception)
32
+ {
33
+ return exception.Message;
34
+ }
35
+
36
+ return "";
37
+ }
38
+
39
+ /// <summary>
40
+ /// 将二进制写入文件(同步)
41
+ /// </summary>
42
+ /// <param name="filePath">要写入的文件路径</param>
43
+ /// <param name="data">要写入的二进制数据</param>
44
+ /// <returns>成功返回空字符串,失败返回错误信息</returns>
45
+ public override string WriteFileSync(string filePath, byte[] data)
46
+ {
47
+ if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(filePath)))
48
+ {
49
+ return $"{System.IO.Path.GetDirectoryName(filePath)} not exist";
50
+ }
51
+
52
+ try
53
+ {
54
+ System.IO.File.WriteAllBytes(filePath, data);
55
+ }
56
+ catch (System.Exception exception)
57
+ {
58
+ return exception.Message;
59
+ }
60
+
61
+ return "";
62
+ }
63
+
64
+ /// <summary>
65
+ /// 将二进制写入文件(异步)
66
+ /// </summary>
67
+ /// <param name="param"></param>
68
+ public override void WriteFile(WriteFileParam param)
69
+ {
70
+ var errMsg = WriteFileSync(param.filePath, param.data);
71
+ CallbackBaseResponse(errMsg, param.success, param.fail);
72
+ }
73
+
74
+ /// <summary>
75
+ /// 将字符串写入文件(异步)
76
+ /// </summary>
77
+ /// <param name="param"></param>
78
+ public override void WriteFile(WriteFileStringParam param)
79
+ {
80
+ var errMsg = WriteFileSync(param.filePath, param.data);
81
+ CallbackBaseResponse(errMsg, param.success, param.fail);
82
+ }
83
+
84
+ /// <summary>
85
+ /// 读取本地文件内容(异步)
86
+ /// </summary>
87
+ /// <param name="param"></param>
88
+ public override void ReadFile(ReadFileParam param)
89
+ {
90
+ if (!System.IO.File.Exists(param.filePath))
91
+ {
92
+ CallbackReadFileResponse("file not exist", param.success, param.fail);
93
+ return;
94
+ }
95
+
96
+ if (string.IsNullOrEmpty(param.encoding) || param.encoding.Equals("binary"))
97
+ {
98
+ var data = System.IO.File.ReadAllBytes(param.filePath);
99
+ CallbackReadFileResponse("", param.success, param.fail, data);
100
+ }
101
+ else
102
+ {
103
+ var data = System.IO.File.ReadAllText(param.filePath);
104
+ CallbackReadFileResponse("", param.success, param.fail, null, data);
105
+ }
106
+ }
107
+
108
+ /// <summary>
109
+ /// 从本地文件读取二进制数据数据(同步)
110
+ /// </summary>
111
+ /// <param name="filePath"></param>
112
+ /// <returns>字节数据,读取失败返回null</returns>
113
+ public override byte[] ReadFileSync(string filePath)
114
+ {
115
+ try
116
+ {
117
+ return System.IO.File.ReadAllBytes(filePath);
118
+ }
119
+ catch (System.Exception exception)
120
+ {
121
+ UnityEngine.Debug.LogError($"ReadFileSync: {exception.Message}");
122
+ return null;
123
+ }
124
+ }
125
+
126
+ /// <summary>
127
+ /// 从本地文件读取字符串数据(同步)
128
+ /// </summary>
129
+ /// <param name="filePath">要读取的文件的路径</param>
130
+ /// <param name="encoding">指定读取文件的字符编码, 不能为空</param>
131
+ /// <returns>字符串数据,读取失败返回null</returns>
132
+ public override string ReadFileSync(string filePath, string encoding)
133
+ {
134
+ try
135
+ {
136
+ return System.IO.File.ReadAllText(filePath);
137
+ }
138
+ catch (System.Exception exception)
139
+ {
140
+ UnityEngine.Debug.LogError($"ReadFileSync: {exception.Message}");
141
+ return null;
142
+ }
143
+ }
144
+
145
+ /// <summary>
146
+ /// 判断文件/目录是否存在(同步)
147
+ /// </summary>
148
+ /// <param name="path">要判断是否存在的文件/目录路径</param>
149
+ /// <returns>成功返回 true, 失败返回 false</returns>
150
+ public override bool AccessSync(string path)
151
+ {
152
+ return System.IO.File.Exists(path) || System.IO.Directory.Exists(path);
153
+ }
154
+
155
+ /// <summary>
156
+ /// 判断文件/目录是否存在(异步)
157
+ /// </summary>
158
+ /// <param name="param"></param>
159
+ public override void Access(AccessParam param)
160
+ {
161
+ var exist = AccessSync(param.path);
162
+ CallbackBaseResponse(exist ? "" : "no such file or directory", param.success, param.fail);
163
+ }
164
+
165
+ /// <summary>
166
+ /// 复制文件(同步)
167
+ /// </summary>
168
+ /// <param name="srcPath">源文件路径</param>
169
+ /// <param name="destPath">目标文件路径</param>
170
+ /// <returns>成功返回空字符串,失败返回错误信息</returns>
171
+ public override string CopyFileSync(string srcPath, string destPath)
172
+ {
173
+ if (System.IO.File.Exists(srcPath))
174
+ {
175
+ try
176
+ {
177
+ System.IO.File.Copy(srcPath, destPath, true);
178
+ }
179
+ catch (System.Exception exception)
180
+ {
181
+ return exception.Message;
182
+ }
183
+
184
+ return "";
185
+ }
186
+ else
187
+ {
188
+ return "source file not exist";
189
+ }
190
+ }
191
+
192
+ /// <summary>
193
+ /// 复制文件(异步)
194
+ /// </summary>
195
+ /// <param name="param"></param>
196
+ public override void CopyFile(CopyFileParam param)
197
+ {
198
+ var errMsg = CopyFileSync(param.srcPath, param.destPath);
199
+ CallbackBaseResponse(errMsg, param.success, param.fail);
200
+ }
201
+
202
+ /// <summary>
203
+ /// 重命名文件(异步)
204
+ /// </summary>
205
+ /// <param name="param"></param>
206
+ public override void RenameFile(RenameFileParam param)
207
+ {
208
+ var errMsg = RenameFileSync(param.srcPath, param.destPath);
209
+ CallbackBaseResponse(errMsg, param.success, param.fail);
210
+ }
211
+
212
+ /// <summary>
213
+ /// 重命名文件(同步)
214
+ /// </summary>
215
+ /// <param name="srcPath">源文件路径</param>
216
+ /// <param name="destPath">目标文件路径</param>
217
+ /// <returns>成功返回空字符串,失败返回错误信息</returns>
218
+ public override string RenameFileSync(string srcPath, string destPath)
219
+ {
220
+ if (System.IO.File.Exists(srcPath))
221
+ {
222
+ try
223
+ {
224
+ if (System.IO.File.Exists(destPath))
225
+ {
226
+ System.IO.File.Delete(destPath);
227
+ }
228
+
229
+ System.IO.File.Move(srcPath, destPath);
230
+ }
231
+ catch (System.Exception exception)
232
+ {
233
+ return exception.Message;
234
+ }
235
+
236
+ return "";
237
+ }
238
+
239
+ return "source file not exist";
240
+ }
241
+
242
+ /// <summary>
243
+ /// 删除文件(同步)
244
+ /// </summary>
245
+ /// <param name="filePath">源文件路径,支持本地路径</param>
246
+ /// <returns>成功返回空字符串,失败返回错误信息</returns>
247
+ public override string UnlinkSync(string filePath)
248
+ {
249
+ if (System.IO.File.Exists(filePath))
250
+ {
251
+ try
252
+ {
253
+ System.IO.File.Delete(filePath);
254
+ }
255
+ catch (System.Exception exception)
256
+ {
257
+ return exception.Message;
258
+ }
259
+
260
+ return "";
261
+ }
262
+
263
+ return "file not exist";
264
+ }
265
+
266
+ /// <summary>
267
+ /// 删除文件(异步)
268
+ /// </summary>
269
+ /// <param name="param"></param>
270
+ public override void Unlink(UnlinkParam param)
271
+ {
272
+ var errMsg = UnlinkSync(param.filePath);
273
+ CallbackBaseResponse(errMsg, param.success, param.fail);
274
+ }
275
+
276
+ /// <summary>
277
+ /// 创建目录(异步)
278
+ /// </summary>
279
+ /// <param name="param"></param>
280
+ public override void Mkdir(MkdirParam param)
281
+ {
282
+ var errMsg = MkdirSync(param.dirPath, param.recursive);
283
+ CallbackBaseResponse(errMsg, param.success, param.fail);
284
+ }
285
+
286
+ /// <summary>
287
+ /// 创建目录(同步)
288
+ /// </summary>
289
+ /// <param name="dirPath">创建的目录路径</param>
290
+ /// <param name="recursive">是否在递归创建该目录的上级目录后再创建该目录。如果对应的上级目录已经存在,则不创建该上级目录。如 dirPath 为 a/b/c/d 且 recursive 为 true,将创建 a 目录,再在 a 目录下创建 b 目录,以此类推直至创建 a/b/c 目录下的 d 目录。</param>
291
+ /// <returns>成功返回空字符串,失败返回错误信息</returns>
292
+ public override string MkdirSync(string dirPath, bool recursive = false)
293
+ {
294
+ if (!System.IO.Directory.Exists(dirPath))
295
+ {
296
+ try
297
+ {
298
+ System.IO.Directory.CreateDirectory(dirPath);
299
+ }
300
+ catch (System.Exception exception)
301
+ {
302
+ return exception.Message;
303
+ }
304
+ }
305
+
306
+ return "";
307
+ }
308
+
309
+ /// <summary>
310
+ /// 删除目录(异步)
311
+ /// </summary>
312
+ /// <param name="param"></param>
313
+ public override void Rmdir(RmdirParam param)
314
+ {
315
+ var errMsg = RmdirSync(param.dirPath, param.recursive);
316
+ CallbackBaseResponse(errMsg, param.success, param.fail);
317
+ }
318
+
319
+ /// <summary>
320
+ /// 删除目录(同步)
321
+ /// </summary>
322
+ /// <param name="dirPath">创建的目录路径</param>
323
+ /// <param name="recursive">是否递归删除目录。如果为 true,则删除该目录和该目录下的所有子目录以及文件 。</param>
324
+ /// <returns>成功返回空字符串,失败返回错误信息</returns>
325
+ public override string RmdirSync(string dirPath, bool recursive = false)
326
+ {
327
+ if (System.IO.Directory.Exists(dirPath))
328
+ {
329
+ try
330
+ {
331
+ System.IO.Directory.Delete(dirPath, recursive);
332
+ }
333
+ catch (System.Exception exception)
334
+ {
335
+ return exception.Message;
336
+ }
337
+
338
+ return "";
339
+ }
340
+ else
341
+ {
342
+ return "directory not exist";
343
+ }
344
+ }
345
+
346
+ /// <summary>
347
+ /// 读取文件描述信息(同步)
348
+ /// </summary>
349
+ /// <param name="path">文件/目录路径</param>
350
+ /// <param name="recursive">是否递归获取目录下的每个文件的 Stat 信息 </param>
351
+ /// <param name="throwException">是否抛出错误信息,如果抛出错误信息,当文件不存在时则会抛出异常,错误信息从异常中获取。</param>
352
+ /// <returns>返回文件信息,如果访问失败则返回null</returns>
353
+ public override TTStatInfo StatSync(string path, bool throwException = false)
354
+ {
355
+ if (System.IO.File.Exists(path))
356
+ {
357
+ var fileInfo = new System.IO.FileInfo(path);
358
+ return new TTStatInfo()
359
+ {
360
+ size = fileInfo.Length,
361
+ mode = 33060,
362
+ lastAccessedTime = GetUnixTime(fileInfo.LastAccessTime.Ticks),
363
+ lastModifiedTime = GetUnixTime(fileInfo.LastWriteTime.Ticks)
364
+ };
365
+ }
366
+ else if (System.IO.Directory.Exists(path))
367
+ {
368
+ var dirInfo = new System.IO.DirectoryInfo(path);
369
+ return new TTStatInfo()
370
+ {
371
+ size = 0,
372
+ mode = 16676,
373
+ lastAccessedTime = GetUnixTime(dirInfo.LastAccessTime.Ticks),
374
+ lastModifiedTime = GetUnixTime(dirInfo.LastWriteTime.Ticks)
375
+ };
376
+ }
377
+ else
378
+ {
379
+ return null;
380
+ }
381
+ }
382
+
383
+ /// <summary>
384
+ /// 读取文件描述信息(异步)
385
+ /// </summary>
386
+ /// <param name="param"></param>
387
+ public override void Stat(StatParam param)
388
+ {
389
+ var info = StatSync(param.path);
390
+ if (info != null)
391
+ {
392
+ param.success?.Invoke(new TTStatResponse()
393
+ {
394
+ stat = info
395
+ });
396
+ }
397
+ else
398
+ {
399
+ param.fail?.Invoke(new TTStatResponse()
400
+ {
401
+ errCode = -1,
402
+ errMsg = "No such file or directory"
403
+ });
404
+ }
405
+ }
406
+
407
+ private void GetFilesRecursively(string path, System.Collections.Generic.List<TTFileInfo> fileInfos)
408
+ {
409
+ System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path);
410
+ if (dir.Exists)
411
+ {
412
+ System.IO.FileInfo[] files = dir.GetFiles();
413
+ if (files != null && files.Length > 0)
414
+ {
415
+ System.DateTime unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
416
+ foreach (System.IO.FileInfo file in files)
417
+ {
418
+ long unixTimeStampInTicks = (file.CreationTime.ToUniversalTime() - unixEpoch).Ticks;
419
+ long unixTimeStampInSeconds = unixTimeStampInTicks / System.TimeSpan.TicksPerSecond;
420
+ fileInfos.Add(new TTFileInfo()
421
+ {
422
+ mode = 33060,
423
+ size = file.Length,
424
+ createTime = unixTimeStampInSeconds,
425
+ filePath = file.FullName
426
+ });
427
+ }
428
+ }
429
+
430
+ System.IO.DirectoryInfo[] subDirs = dir.GetDirectories();
431
+ if (subDirs != null && subDirs.Length > 0)
432
+ {
433
+ System.DateTime unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
434
+ foreach (var subDir in subDirs)
435
+ {
436
+ long unixTimeStampInTicks = (subDir.CreationTime.ToUniversalTime() - unixEpoch).Ticks;
437
+ long unixTimeStampInSeconds = unixTimeStampInTicks / System.TimeSpan.TicksPerSecond;
438
+ fileInfos.Add(new TTFileInfo()
439
+ {
440
+ mode = 16676,
441
+ size = 0,
442
+ createTime = unixTimeStampInSeconds,
443
+ filePath = subDir.FullName
444
+ });
445
+ GetFilesRecursively(subDir.FullName, fileInfos);
446
+ }
447
+ }
448
+ }
449
+ }
450
+
451
+ /// <summary>
452
+ /// 获取保存的用户目录文件列表
453
+ /// </summary>
454
+ public override void GetSavedFileList(GetSavedFileListParam param)
455
+ {
456
+ System.Collections.Generic.List<TTFileInfo> fileInfos =
457
+ new System.Collections.Generic.List<TTFileInfo>();
458
+ GetFilesRecursively(UnityEngine.Application.persistentDataPath, fileInfos);
459
+ param.success?.Invoke(new TTGetSavedFileListResponse()
460
+ {
461
+ fileList = fileInfos.ToArray()
462
+ });
463
+ }
464
+
465
+ /// <summary>
466
+ /// 根据url链接获取本地缓存文件路径
467
+ /// </summary>
468
+ /// <param name="url">输入文件下载链接url</param>
469
+ /// <returns>返回本地缓存文件路径,以scfile://user开头的路径,可以直接用这个路径访问该文件</returns>
470
+ public override string GetLocalCachedPathForUrl(string url)
471
+ {
472
+ return "";
473
+ }
474
+
475
+ /// <summary>
476
+ /// 判断该url是否有本地缓存文件
477
+ /// </summary>
478
+ /// <param name="url">输入文件下载链接url</param>
479
+ /// <returns>如果存在缓存文件则返回true,不存在缓存文件则返回false</returns>
480
+ public override bool IsUrlCached(string url)
481
+ {
482
+ return false;
483
+ }
484
+
485
+ public override string AppendFileSync(string filePath, string data, string encoding = "utf8")
486
+ {
487
+ try
488
+ {
489
+ File.AppendAllText(filePath, data);
490
+ }
491
+ catch (Exception e)
492
+ {
493
+ return e.Message;
494
+ }
495
+
496
+ return "";
497
+ }
498
+
499
+ public override string AppendFileSync(string filePath, byte[] data)
500
+ {
501
+ try
502
+ {
503
+ using FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write);
504
+ fs.Write(data, 0, data.Length);
505
+ }
506
+ catch (Exception e)
507
+ {
508
+ return e.Message;
509
+ }
510
+
511
+ return "";
512
+
513
+ }
514
+
515
+ public override void AppendFile(AppendFileParam param)
516
+ {
517
+ var errMsg = AppendFileSync(param.FilePath, param.Data);
518
+ CallbackBaseResponse(errMsg, param.success, param.fail);
519
+ }
520
+
521
+ public override void AppendFile(AppendFileStringParam param)
522
+ {
523
+ var errMsg = AppendFileSync(param.FilePath, param.Data, param.Encoding);
524
+ CallbackBaseResponse(errMsg, param.success, param.fail);
525
+ }
526
+
527
+ public override void ReadDir(ReadDirParam param)
528
+ {
529
+ var fileList = ReadDirSync(param.DirPath);
530
+ param.success?.Invoke(new TTReadDirResponse{files = fileList});
531
+ }
532
+
533
+ public override string[] ReadDirSync(string dirPath)
534
+ {
535
+ try
536
+ {
537
+ if (Directory.Exists(dirPath))
538
+ {
539
+ return Directory.GetFiles(dirPath);
540
+ }
541
+ else
542
+ {
543
+ return new string[] { "Directory not exist" };
544
+ }
545
+ }
546
+ catch (Exception e)
547
+ {
548
+ return new string[] { e.Message };
549
+ }
550
+ }
551
+
552
+ public override void Truncate(TruncateParam param)
553
+ {
554
+ var errMsg = TruncateSync(param.FilePath, param.Length);
555
+ CallbackBaseResponse(errMsg, param.success, param.fail);
556
+ }
557
+
558
+ public override string TruncateSync(string filePath, int length)
559
+ {
560
+ try
561
+ {
562
+ using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Write))
563
+ {
564
+ fs.SetLength(length);
565
+ }
566
+ }
567
+ catch (Exception e)
568
+ {
569
+ return e.Message;
570
+ }
571
+
572
+ return "";
573
+ }
574
+
575
+ private static void CallbackReadFileResponse(string errMsg,
576
+ System.Action<TTReadFileResponse> success,
577
+ System.Action<TTReadFileResponse> fail,
578
+ byte[] binData = null,
579
+ string stringData = null)
580
+ {
581
+ if (string.IsNullOrEmpty(errMsg))
582
+ {
583
+ success?.Invoke(new TTReadFileResponse()
584
+ {
585
+ binData = binData,
586
+ stringData = stringData
587
+ });
588
+ }
589
+ else
590
+ {
591
+ fail?.Invoke(new TTReadFileResponse()
592
+ {
593
+ errCode = -1,
594
+ errMsg = errMsg
595
+ });
596
+ }
597
+ }
598
+
599
+ private static void CallbackBaseResponse(string errMsg, System.Action<TTBaseResponse> success,
600
+ System.Action<TTBaseResponse> fail)
601
+ {
602
+ if (string.IsNullOrEmpty(errMsg))
603
+ {
604
+ success?.Invoke(new TTBaseResponse());
605
+ }
606
+ else
607
+ {
608
+ fail?.Invoke(new TTBaseResponse()
609
+ {
610
+ errCode = -1,
611
+ errMsg = errMsg
612
+ });
613
+ }
614
+ }
615
+
616
+ private static long GetUnixTime(long ticks)
617
+ {
618
+ var epochTicks = new System.DateTime(1970, 1, 1).Ticks;
619
+ var unixTime = ((ticks - epochTicks) / System.TimeSpan.TicksPerSecond);
620
+ return unixTime;
621
+ }
622
+
623
+ //文件流式读写
624
+ /// <summary>
625
+ /// (FileStream, string, bool, string)
626
+ /// 文件流对象,打开参数,是否首次操作,路径
627
+ /// </summary>
628
+ private Dictionary<string, (FileStream, string, bool, string)> _openFiles = new();
629
+ private int _fdCounter = 0;
630
+
631
+ /// <summary>
632
+ /// 生成唯一标识符
633
+ /// </summary>
634
+ /// <returns></returns>
635
+ private string GenerateFd()
636
+ {
637
+ using var sha256 = SHA256.Create();
638
+ var input = Encoding.UTF8.GetBytes(Guid.NewGuid().ToString() + _fdCounter++);
639
+ var hash = sha256.ComputeHash(input);
640
+ return Convert.ToBase64String(hash).Replace("/", "_").Replace("+", "-").Substring(0, 16);
641
+ }
642
+
643
+ /// <summary>
644
+ /// 打开文件
645
+ /// </summary>
646
+ /// <param name="param"></param>
647
+ public override void Open(OpenParam param)
648
+ {
649
+ string err = "";
650
+ string fd = null;
651
+ FileMode mode = FileMode.Open;
652
+ FileAccess access = FileAccess.Read;
653
+ try
654
+ {
655
+ switch (param.flag)
656
+ {
657
+ case "a":
658
+ mode = FileMode.OpenOrCreate;
659
+ access = FileAccess.Write;
660
+ break;
661
+ case "ax":
662
+ mode = FileMode.CreateNew;
663
+ access = FileAccess.Write;
664
+ break;
665
+ case "a+":
666
+ mode = FileMode.OpenOrCreate;
667
+ access = FileAccess.ReadWrite;
668
+ break;
669
+ case "ax+":
670
+ mode = FileMode.CreateNew;
671
+ access = FileAccess.ReadWrite;
672
+ break;
673
+ case "as":
674
+ mode = FileMode.OpenOrCreate;
675
+ access = FileAccess.Write;
676
+ break;
677
+ case "as+":
678
+ mode = FileMode.OpenOrCreate;
679
+ access = FileAccess.ReadWrite;
680
+ break;
681
+ case "r":
682
+ mode = FileMode.Open;
683
+ access = FileAccess.Read;
684
+ break;
685
+ case "r+":
686
+ mode = FileMode.Open;
687
+ access = FileAccess.ReadWrite;
688
+ break;
689
+ case "w":
690
+ mode = FileMode.Create;
691
+ access = FileAccess.Write;
692
+ break;
693
+ case "wx":
694
+ mode = FileMode.CreateNew;
695
+ access = FileAccess.Write;
696
+ break;
697
+ case "w+":
698
+ mode = FileMode.Create;
699
+ access = FileAccess.ReadWrite;
700
+ break;
701
+ case "wx+":
702
+ mode = FileMode.CreateNew;
703
+ access = FileAccess.ReadWrite;
704
+ break;
705
+ default:
706
+ throw new Exception("invalid flag");
707
+ }
708
+ var fs = new FileStream(param.filePath, mode, access);
709
+ fd = GenerateFd();
710
+ _openFiles[fd] = (fs, param.flag, true, param.filePath);
711
+ }
712
+ catch (Exception e)
713
+ {
714
+ err = e.Message;
715
+ }
716
+
717
+ if (string.IsNullOrEmpty(err))
718
+ {
719
+ param.success?.Invoke(new TTOpenResponse { fd = fd });
720
+ }
721
+ else
722
+ {
723
+ param.fail?.Invoke(new TTOpenResponse { errCode = -1, errMsg = err });
724
+ }
725
+ }
726
+
727
+ public override string OpenSync(OpenSyncParam param)
728
+ {
729
+ FileMode mode = FileMode.Open;
730
+ FileAccess access = FileAccess.Read;
731
+ switch (param.flag)
732
+ {
733
+ case "a":
734
+ mode = FileMode.OpenOrCreate;
735
+ access = FileAccess.Write;
736
+ break;
737
+ case "a+":
738
+ mode = FileMode.OpenOrCreate;
739
+ access = FileAccess.ReadWrite;
740
+ break;
741
+ case "as":
742
+ mode = FileMode.OpenOrCreate;
743
+ access = FileAccess.Write;
744
+ break;
745
+ case "as+":
746
+ mode = FileMode.OpenOrCreate;
747
+ access = FileAccess.ReadWrite;
748
+ break;
749
+ case "ax":
750
+ mode = FileMode.CreateNew;
751
+ access = FileAccess.Write;
752
+ break;
753
+ case "ax+":
754
+ mode = FileMode.CreateNew;
755
+ access = FileAccess.ReadWrite;
756
+ break;
757
+ case "r":
758
+ mode = FileMode.Open;
759
+ access = FileAccess.Read;
760
+ break;
761
+ case "r+":
762
+ mode = FileMode.Open;
763
+ access = FileAccess.ReadWrite;
764
+ break;
765
+ case "w":
766
+ mode = FileMode.Create;
767
+ access = FileAccess.Write;
768
+ break;
769
+ case "wx":
770
+ mode = FileMode.CreateNew;
771
+ access = FileAccess.Write;
772
+ break;
773
+ case "w+":
774
+ mode = FileMode.Create;
775
+ access = FileAccess.ReadWrite;
776
+ break;
777
+ case "wx+":
778
+ mode = FileMode.CreateNew;
779
+ access = FileAccess.ReadWrite;
780
+ break;
781
+ default:
782
+ throw new Exception("invalid flag");
783
+ }
784
+ var fs = new FileStream(param.filePath, mode, access);
785
+ string fd = GenerateFd();
786
+ _openFiles[fd] = (fs, param.flag, true, param.filePath);
787
+ return fd;
788
+ }
789
+
790
+ public override void Close(CloseParam param)
791
+ {
792
+ string err = CloseSyncInternal(param.fd);
793
+ CallbackBaseResponse(err, param.success, param.fail);
794
+ }
795
+
796
+ public override void CloseSync(CloseSyncParam param)
797
+ {
798
+ var errMsg = CloseSyncInternal(param.fd);
799
+ if (!string.IsNullOrEmpty(errMsg))
800
+ {
801
+ throw new Exception(errMsg);
802
+ }
803
+ }
804
+
805
+ private string CloseSyncInternal(string fd)
806
+ {
807
+ if (_openFiles.TryGetValue(fd, out var fs))
808
+ {
809
+ fs.Item1.Close();
810
+ _openFiles.Remove(fd);
811
+ return "";
812
+ }
813
+ return "bad file descriptor";
814
+ }
815
+
816
+ public override void Write(WriteBinParam param)
817
+ {
818
+ var err = WriteInternal(param.fd, param.data, param.offset, param.length ?? (param.data.Length - param.offset));
819
+ if (err == null)
820
+ {
821
+ param.success?.Invoke(new TTWriteResponse { bytesWritten = param.length ?? (param.data.Length - param.offset) });
822
+ }
823
+ else
824
+ {
825
+ param.fail?.Invoke(new TTWriteResponse { errCode = -1, errMsg = err });
826
+ }
827
+ }
828
+
829
+ public override void Write(WriteStringParam param)
830
+ {
831
+ byte[] data = System.Text.Encoding.UTF8.GetBytes(param.data);
832
+ Write(new WriteBinParam
833
+ {
834
+ fd = param.fd,
835
+ data = data,
836
+ offset = param.offset,
837
+ length = param.length,
838
+ success = param.success,
839
+ fail = param.fail
840
+ });
841
+ }
842
+
843
+ public override WriteResult WriteSync(WriteBinSyncParam param)
844
+ {
845
+ var err = WriteInternal(param.fd, param.data, param.offset, param.length ?? (param.data.Length - param.offset));
846
+ if (err == null) return new WriteResult { bytesWritten = param.length ?? (param.data.Length - param.offset)};
847
+ throw new Exception(err);
848
+ }
849
+
850
+ public override WriteResult WriteSync(WriteStringSyncParam param)
851
+ {
852
+ byte[] data = System.Text.Encoding.UTF8.GetBytes(param.data);
853
+ return WriteSync(new WriteBinSyncParam
854
+ {
855
+ fd = param.fd,
856
+ data = data,
857
+ encoding = param.encoding
858
+ });
859
+ }
860
+
861
+ private string WriteInternal(string fd, byte[] data, int offset, int length)
862
+ {
863
+ if (!_openFiles.TryGetValue(fd, out var fs))
864
+ return "bad file descriptor";
865
+ try
866
+ {
867
+ if(fs.Item2.Contains("a")) fs.Item1.Seek(0, SeekOrigin.End);
868
+ fs.Item1.Write(data, offset, length);
869
+ fs.Item1.Flush();
870
+ return null;
871
+ }
872
+ catch (Exception e)
873
+ {
874
+ return e.Message;
875
+ }
876
+ }
877
+
878
+ public override void Read(ReadParam param)
879
+ {
880
+ var (buffer, bytesRead, err) = ReadInternal(param.fd, param.arrayBuffer, param.offset, param.length, param.position);
881
+ if (err == null)
882
+ {
883
+ param.success?.Invoke(new TTReadResponse
884
+ {
885
+ arrayBuffer = buffer,
886
+ bytesRead = bytesRead
887
+ });
888
+ }
889
+ else
890
+ {
891
+ param.fail?.Invoke(new TTReadResponse { errCode = -1, errMsg = err });
892
+ }
893
+ }
894
+
895
+ public override ReadResult ReadSync(ReadSyncParam param)
896
+ {
897
+ var (buffer, bytesRead, err) = ReadInternal(param.fd, param.arrayBuffer, param.offset, param.length, param.position);
898
+ if (err == null) return new ReadResult { arrayBuffer = buffer, bytesRead = bytesRead };
899
+ throw new Exception(err);
900
+ }
901
+
902
+ private (byte[] buffer, int bytesRead, string err) ReadInternal(string fd, byte[] buffer, int offset, int length, int? position)
903
+ {
904
+ if (!_openFiles.TryGetValue(fd, out var fs))
905
+ return (null, 0, "bad file descriptor");
906
+ try
907
+ {
908
+ if (position.HasValue)
909
+ fs.Item1.Seek(position.Value, SeekOrigin.Begin);
910
+
911
+ int read = fs.Item1.Read(buffer, offset, length);
912
+ return (buffer, read, null);
913
+ }
914
+ catch (Exception e)
915
+ {
916
+ return (null, 0, e.Message);
917
+ }
918
+ }
919
+
920
+ public override void ReadCompressedFile(ReadCompressedFileParam param)
921
+ {
922
+ string err = "";
923
+ using MemoryStream ms = new MemoryStream();
924
+ try
925
+ {
926
+ if (param.compressionAlgorithm != "br")
927
+ {
928
+ throw new Exception("brotli decompress fail");
929
+ }
930
+ using FileStream fs = new FileStream(param.filePath, FileMode.Open, FileAccess.Read);
931
+ using BrotliStream brotliStream = new BrotliStream(fs, CompressionMode.Decompress);
932
+ brotliStream.CopyTo(ms);
933
+ }
934
+ catch (Exception e)
935
+ {
936
+ err = e.Message;
937
+ }
938
+
939
+ if (string.IsNullOrEmpty(err))
940
+ {
941
+ param.success?.Invoke(new() { arrayBuffer = ms.ToArray() });
942
+ }
943
+ else
944
+ {
945
+ param.fail?.Invoke(new() { errCode = -1, errMsg = err });
946
+ }
947
+ }
948
+
949
+ public override byte[] ReadCompressedFileSync(ReadCompressedFileSyncParam param)
950
+ {
951
+ if (param.compressionAlgorithm != "br")
952
+ {
953
+ throw new Exception("brotli decompress fail");
954
+ }
955
+ using FileStream fs = new FileStream(param.filePath, FileMode.Open, FileAccess.Read);
956
+ using BrotliStream brotliStream = new BrotliStream(fs, CompressionMode.Decompress);
957
+ using MemoryStream ms = new MemoryStream();
958
+ brotliStream.CopyTo(ms);
959
+ return ms.ToArray();
960
+ }
961
+
962
+ public override void Fstat(FstatParam param)
963
+ {
964
+ if (!_openFiles.TryGetValue(param.fd, out var entry))
965
+ {
966
+ param.fail?.Invoke(new()
967
+ {
968
+ errCode = -1,
969
+ errMsg = "bad file descriptor"
970
+ });
971
+ return;
972
+ }
973
+
974
+ try
975
+ {
976
+ FileInfo fileInfo = new FileInfo(entry.Item4);
977
+ var info = new TTStatInfo
978
+ {
979
+ size = fileInfo.Length,
980
+ mode = 33060,
981
+ lastAccessedTime = GetUnixTime(fileInfo.LastAccessTimeUtc.Ticks),
982
+ lastModifiedTime = GetUnixTime(fileInfo.LastWriteTimeUtc.Ticks)
983
+ };
984
+ param.success?.Invoke(new(){ stats = info });
985
+ }
986
+ catch (Exception e)
987
+ {
988
+ param.fail?.Invoke(new(){ errCode = -1, errMsg = e.Message });
989
+ }
990
+ }
991
+
992
+ public override TTStatInfo FstatSync(FstatSyncParam param)
993
+ {
994
+ if (!_openFiles.TryGetValue(param.fd, out var entry))
995
+ {
996
+ throw new Exception("bad file descriptor");
997
+ }
998
+
999
+ FileInfo fileInfo = new FileInfo(entry.Item4);
1000
+ return new TTStatInfo
1001
+ {
1002
+ size = fileInfo.Length,
1003
+ mode = 33060,
1004
+ lastAccessedTime = GetUnixTime(fileInfo.LastAccessTimeUtc.Ticks),
1005
+ lastModifiedTime = GetUnixTime(fileInfo.LastWriteTimeUtc.Ticks)
1006
+ };
1007
+ }
1008
+
1009
+ public override void Ftruncate(FtruncateParam param)
1010
+ {
1011
+ if (!_openFiles.TryGetValue(param.fd, out var entry))
1012
+ {
1013
+ param.fail?.Invoke(new TTBaseResponse { errCode = -1, errMsg = "bad file descriptor" });
1014
+ return;
1015
+ }
1016
+ try
1017
+ {
1018
+ entry.Item1.SetLength(param.length);
1019
+ entry.Item1.Flush();
1020
+ param.success?.Invoke(new TTBaseResponse());
1021
+ }
1022
+ catch (Exception e)
1023
+ {
1024
+ param.fail?.Invoke(new TTBaseResponse { errCode = -1, errMsg = e.Message });
1025
+ }
1026
+ }
1027
+
1028
+ public override void FtruncateSync(FtruncateSyncParam param)
1029
+ {
1030
+ if (!_openFiles.TryGetValue(param.fd, out var entry))
1031
+ {
1032
+ throw new Exception("bad file descriptor");
1033
+ }
1034
+
1035
+ entry.Item1.SetLength(param.length);
1036
+ entry.Item1.Flush();
1037
+ }
1038
+ }
1039
+ }