Skip to content

Commit

Permalink
i commit the files
Browse files Browse the repository at this point in the history
  • Loading branch information
chee committed Jan 27, 2019
0 parents commit d1b960c
Show file tree
Hide file tree
Showing 6 changed files with 2,804 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .eslintrc.yml
@@ -0,0 +1,22 @@
env:
es6: true
node: true
extends: 'eslint:recommended'
parserOptions:
ecmaVersion: 2018
sourceType: module
rules:
indent:
- error
- tab
linebreak-style:
- error
- unix
quotes:
- error
- double
semi:
- error
- never
no-console:
- 0
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
node_modules/
121 changes: 121 additions & 0 deletions bin/imessages
@@ -0,0 +1,121 @@
#!/usr/bin/env -S node -r esm
import {homedir} from "os"
import path from "path"
import Knex from "knex"
import yargs from "yargs"

let applepoch = new Date("2001-01-01").getTime()

let convertAppleDateToIsoDate = date =>
new Date(applepoch + date / 1000000).toISOString()

// let convertIsoDateToAppleDate = date =>
// new Date(date - applepoch).getTime() * 1000000

// The file is always in the same place, and while it would be good to be able
// to take another database other than the live one (one you’ve backed up, or
let databasePath = path.resolve(
homedir(),
"Library",
"Messages",
"chat.db"
)

let knex = Knex({
client: "sqlite3",
useNullAsDefault: true,
connection: {
filename: databasePath
}
})

let get = field => item => item[field]

let getId = get("id")

yargs
.command({
command: "extract <handle> [name] [me]",
describe: "extract messages for a handle",
// aliases: ["$0"],
builder (yargs) {
return yargs
.positional(
"handle",
{
describe: "the handle whümfs messages to extract",
type: "string"
}
)
.positional(
"name",
{
describe: "the name to use for `handle`",
type: "string"
}
)
.positional(
"me",
{
describe: "the name to use for `me`",
type: "string",
default: "me"
}
)
},
handler: extract
})
.command({
command: "list-handles",
aliases: ["handles"],
describe: "list handles (like, contacts) from the database",
async handler () {
await knex
.select("*")
.from("handle")
.map(getId)
.then(handles => handles.forEach(handle => console.info(handle)))
process.exit()
}
})
.demandCommand(1, "you gotta chose a command")
.help()
.wrap(yargs.terminalWidth())
.argv

async function extract (argv) {
let handle = argv.handle.trim()

let messages = await knex
.select([
"text",
"is_from_me",
"date",
"service",
])
.from("message")
.whereIn(
"handle_id",
knex
.select("ROWID")
.from("handle")
.where({
id: handle
})
)
.orderBy("date", "asc")
.then(messages => {
messages.forEach(message => {
message.date = convertAppleDateToIsoDate(message.date)
message.from = message.is_from_me ? argv.me : argv.name
message.to = message.is_from_me ? argv.name : argv.me
delete message.is_from_me
})

return messages

})

console.info(JSON.stringify(messages, 0, "\t"))
process.exit()
}
121 changes: 121 additions & 0 deletions index.js
@@ -0,0 +1,121 @@
#!/usr/bin/env -S node -r esm
import {homedir} from "os"
import path from "path"
import Knex from "knex"
import yargs from "yargs"

let applepoch = new Date("2001-01-01").getTime()

let convertAppleDateToIsoDate = date =>
new Date(applepoch + date / 1000000).toISOString()

// let convertIsoDateToAppleDate = date =>
// new Date(date - applepoch).getTime() * 1000000

// The file is always in the same place, and while it would be good to be able
// to take another database other than the live one (one you’ve backed up, or
let databasePath = path.resolve(
homedir(),
"Library",
"Messages",
"chat.db"
)

let knex = Knex({
client: "sqlite3",
useNullAsDefault: true,
connection: {
filename: databasePath
}
})

let get = field => item => item[field]

let getId = get("id")

yargs
.command({
command: "extract <handle> [name] [me]",
describe: "extract messages for a handle",
// aliases: ["$0"],
builder (yargs) {
return yargs
.positional(
"handle",
{
describe: "the handle whümfs messages to extract",
type: "string"
}
)
.positional(
"name",
{
describe: "the name to use for `handle`",
type: "string"
}
)
.positional(
"me",
{
describe: "the name to use for `me`",
type: "string",
default: "me"
}
)
},
handler: extract
})
.command({
command: "list-handles",
aliases: ["handles"],
describe: "list handles (like, contacts) from the database",
async handler () {
await knex
.select("*")
.from("handle")
.map(getId)
.then(handles => handles.forEach(handle => console.info(handle)))
process.exit()
}
})
.demandCommand(1, "you gotta chose a command")
.help()
.wrap(yargs.terminalWidth())
.argv

async function extract (argv) {
let handle = argv.handle.trim()

let messages = await knex
.select([
"text",
"is_from_me",
"date",
"service",
])
.from("message")
.whereIn(
"handle_id",
knex
.select("ROWID")
.from("handle")
.where({
id: handle
})
)
.orderBy("date", "asc")
.then(messages => {
messages.forEach(message => {
message.date = convertAppleDateToIsoDate(message.date)
message.from = message.is_from_me ? argv.me : argv.name
message.to = message.is_from_me ? argv.name : argv.me
delete message.is_from_me
})

return messages

})

console.info(JSON.stringify(messages, 0, "\t"))
process.exit()
}

0 comments on commit d1b960c

Please sign in to comment.