voicemail.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. const path = require('path')
  2. const fs = require('fs-extra')
  3. // Derive filenames based on domain + file path
  4. const fileHash = require('../../util/backup_filehash')
  5. const log = require('../../util/log')
  6. const VOICEMAIL_DB = fileHash('Library/Voicemail/voicemail.db')
  7. module.exports = {
  8. version: 4,
  9. name: 'phone.voicemail',
  10. description: `List all or extract voicemails on device`,
  11. requiresBackup: true,
  12. // Run on a v3 lib / backup object.
  13. run (lib, { backup, extract }) {
  14. return new Promise(async (resolve, reject) => {
  15. try {
  16. let voicemails = await getVoicemailsList(backup)
  17. if (extract) {
  18. extractVoicemails(voicemails, backup, extract)
  19. }
  20. resolve(voicemails)
  21. } catch (e) {
  22. reject(e)
  23. }
  24. })
  25. },
  26. // Manifest fields.
  27. output: {
  28. id: el => el.ROWID,
  29. date: el => el.XFORMATTEDDATESTRING,
  30. sender: el => el.sender,
  31. token: el => el.token,
  32. duration: el => el.duration,
  33. expiration: el => el.expiration,
  34. trashed: el => el.trashed_date,
  35. flags: el => el.flags
  36. }
  37. }
  38. // Extract a list of voicemails from a backup to a folder on disk.
  39. // - voicemails: list of voicemail data objects.
  40. // - backup: backup api object
  41. // - extractDest: extract location on disk
  42. function extractVoicemails (voicemails, backup, extractDest) {
  43. for (let voicemail of voicemails) {
  44. try {
  45. // Get sender number
  46. let sender = (voicemail.sender || '').replace(/[ +()-]/g, '')
  47. var outDir = path.join(extractDest, `voicemail_${sender}_${voicemail.ROWID}.amr`)
  48. // Get file hash of matching voicemail
  49. let id = backup.getFileID(`Library/Voicemail/${voicemail.ROWID}.amr`)
  50. var srcDir = backup.getFileName(id)
  51. // Log the export
  52. log.action('extract', srcDir)
  53. // Ensure output dir exists
  54. fs.ensureDirSync(path.dirname(outDir))
  55. // Create a stream to the output.
  56. fs.createReadStream(srcDir).pipe(fs.createWriteStream(outDir))
  57. } catch (e) {
  58. log.error(`Couldn't extract: ${srcDir}`, e)
  59. }
  60. }
  61. }
  62. // Get all voicemails from the db.
  63. function getVoicemailsList (backup) {
  64. return new Promise((resolve, reject) => {
  65. backup.openDatabase(VOICEMAIL_DB)
  66. .then(db => {
  67. db.all(`SELECT *, datetime(date, 'unixepoch') AS XFORMATTEDDATESTRING from voicemail ORDER BY date ASC`, function (err, rows) {
  68. if (err) reject(err)
  69. resolve(rows)
  70. })
  71. })
  72. .catch(reject)
  73. })
  74. }