( item: MessageItem, cdnBaseUrl: string, )
| 40 | } |
| 41 | |
| 42 | async function downloadMedia( |
| 43 | item: MessageItem, |
| 44 | cdnBaseUrl: string, |
| 45 | ): Promise<{ path: string; type: string } | null> { |
| 46 | let encryptQueryParam: string | undefined |
| 47 | let aesKey: string | undefined |
| 48 | let ext = '' |
| 49 | let mediaType = '' |
| 50 | |
| 51 | switch (item.type) { |
| 52 | case MessageItemType.IMAGE: |
| 53 | encryptQueryParam = item.image_item?.media?.encrypt_query_param |
| 54 | aesKey = item.image_item?.aeskey |
| 55 | ? Buffer.from(item.image_item.aeskey, 'hex').toString('base64') |
| 56 | : item.image_item?.media?.aes_key |
| 57 | ext = '.jpg' |
| 58 | mediaType = 'image' |
| 59 | break |
| 60 | case MessageItemType.VOICE: |
| 61 | encryptQueryParam = item.voice_item?.media?.encrypt_query_param |
| 62 | aesKey = item.voice_item?.media?.aes_key |
| 63 | ext = '.silk' |
| 64 | mediaType = 'voice' |
| 65 | break |
| 66 | case MessageItemType.FILE: |
| 67 | encryptQueryParam = item.file_item?.media?.encrypt_query_param |
| 68 | aesKey = item.file_item?.media?.aes_key |
| 69 | ext = item.file_item?.file_name |
| 70 | ? `.${item.file_item.file_name.split('.').pop()}` |
| 71 | : '' |
| 72 | mediaType = 'file' |
| 73 | break |
| 74 | case MessageItemType.VIDEO: |
| 75 | encryptQueryParam = item.video_item?.media?.encrypt_query_param |
| 76 | aesKey = item.video_item?.media?.aes_key |
| 77 | ext = '.mp4' |
| 78 | mediaType = 'video' |
| 79 | break |
| 80 | default: |
| 81 | return null |
| 82 | } |
| 83 | |
| 84 | if (!encryptQueryParam || !aesKey) return null |
| 85 | |
| 86 | try { |
| 87 | const data = await downloadAndDecrypt({ |
| 88 | encryptQueryParam, |
| 89 | aesKey, |
| 90 | cdnBaseUrl, |
| 91 | }) |
| 92 | const dir = join(tmpdir(), 'weixin-media') |
| 93 | if (!existsSync(dir)) mkdirSync(dir, { recursive: true }) |
| 94 | const rawFileName = item.file_item?.file_name || `${Date.now()}${ext}` |
| 95 | const fileName = basename(rawFileName) |
| 96 | const filePath = join(dir, fileName) |
| 97 | writeFileSync(filePath, data) |
| 98 | return { path: filePath, type: mediaType } |
| 99 | } catch (error) { |
no test coverage detected