chronicle-imessage 0.2.6 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/README.md +6 -12
- data/bin/console +4 -11
- data/chronicle-imessage.gemspec +30 -25
- data/lib/chronicle/imessage/imessage_extractor.rb +10 -4
- data/lib/chronicle/imessage/imessage_transformer.rb +140 -130
- data/lib/chronicle/imessage/version.rb +1 -1
- data/lib/chronicle/imessage.rb +4 -4
- metadata +56 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03a69e13d41a855786b08bea6c849d1b9d8e8d599c7891fe79c8d68dd133bd0d
|
4
|
+
data.tar.gz: 50bcf0913088dc140b6665ed40b404402c121b53f90fdd82277163928285ccaf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c98ad41fdafab157edaa9549e7ef560ac851997bf2773dd1351fbcbae2f5f2dea2376dedae94aa6a7d1fc7f4a5960b6fc3677ba3b27424455435251dcd87c63
|
7
|
+
data.tar.gz: 2197b73726b4d55f9e2d5e2b991f52a3b6524e377203cd389663ad744dfdb39d8346e1c4b12a042503bac08d2278a8e6bde221f48d2774189fe2b239f18d5f78
|
data/.rubocop.yml
ADDED
data/README.md
CHANGED
@@ -10,23 +10,21 @@ Access your iMessage messages and attachments using the command line with this p
|
|
10
10
|
$ gem install chronicle-etl
|
11
11
|
$ chronicle-etl plugins:install imessage
|
12
12
|
|
13
|
-
# Load messages
|
14
|
-
$ chronicle-etl --extractor imessage --
|
13
|
+
# Load messages from the last week
|
14
|
+
$ chronicle-etl --extractor imessage --schema chronicle --since 1w
|
15
15
|
|
16
16
|
# Of the latest 1000 messages received, who were the top senders?
|
17
|
-
$ chronicle-etl -e imessage
|
18
|
-
|
19
|
-
# Get the raw query results for the latest 10 messages and save as a CSV
|
20
|
-
$ chronicle-etl -e imessage --loader csv --limit 10 -o imessages.csv
|
17
|
+
$ chronicle-etl -e imessage --schema chronicle --limit 1000 --fields agent.name | sort | uniq -c | sort -nr
|
21
18
|
```
|
22
19
|
|
23
20
|
## Available Connectors
|
24
21
|
### Extractors
|
25
22
|
|
26
|
-
#### `
|
27
|
-
Extractor for importing messages and attachments from local macOS iMessage install (`~/Library/Messages/chat.db`)
|
23
|
+
#### `message`
|
24
|
+
Extractor for importing messages and attachments from local macOS iMessage install (via local cache at `~/Library/Messages/chat.db`)
|
28
25
|
|
29
26
|
##### Settings
|
27
|
+
- `input`: (default: ~/Library/Messages/chat.db) Local iMessage sqlite database
|
30
28
|
- `load_attachments`: (default: false) Whether to load message attachments
|
31
29
|
- `only_attachments`: (default: false) Whether to load only messages with attachments
|
32
30
|
|
@@ -36,7 +34,3 @@ We want messages to have sender/receiver information set properly so we try to i
|
|
36
34
|
- `icloud_account_id`: Specify an email address that represents your iCloud account ID
|
37
35
|
- `icloud_account_dsid`: Specify iCloud DSID
|
38
36
|
- Can find in Keychain or by running `$ defaults read MobileMeAccounts Accounts`
|
39
|
-
### Transformers
|
40
|
-
|
41
|
-
#### `imessage`
|
42
|
-
Transform an iMessage message into Chronicle Schema
|
data/bin/console
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'chronicle/imessage'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
6
|
+
require 'pry'
|
7
|
+
Pry.start
|
data/chronicle-imessage.gemspec
CHANGED
@@ -1,44 +1,49 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require 'chronicle/imessage/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'chronicle-imessage'
|
8
7
|
spec.version = Chronicle::Imessage::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
8
|
+
spec.authors = ['Andrew Louis']
|
9
|
+
spec.email = ['andrew@hyfen.net']
|
10
|
+
|
11
|
+
spec.summary = 'iMessage importer for Chronicle'
|
12
|
+
spec.description = 'Connectors for iMessage'
|
13
|
+
spec.homepage = 'https://github.com/chronicle-app/chronicle-imessage'
|
11
14
|
|
12
|
-
spec.
|
13
|
-
spec.description = "Connectors for iMessage"
|
14
|
-
spec.homepage = "https://github.com/chronicle-app/chronicle-imessage"
|
15
|
+
spec.required_ruby_version = '>= 3.1'
|
15
16
|
|
16
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
19
|
if spec.respond_to?(:metadata)
|
19
|
-
spec.metadata['allowed_push_host'] =
|
20
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
20
21
|
|
21
|
-
spec.metadata[
|
22
|
-
spec.metadata[
|
23
|
-
spec.metadata[
|
22
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
23
|
+
spec.metadata['source_code_uri'] = 'https://github.com/chronicle-app/chronicle-imessage'
|
24
|
+
spec.metadata['changelog_uri'] = 'https://github.com/chronicle-app/chronicle-imessage'
|
24
25
|
else
|
25
|
-
raise
|
26
|
-
|
26
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
27
|
+
'public gem pushes.'
|
27
28
|
end
|
28
29
|
|
29
30
|
# Specify which files should be added to the gem when it is released.
|
30
31
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
31
|
-
spec.files
|
32
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
32
33
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
33
34
|
end
|
34
|
-
spec.bindir =
|
35
|
+
spec.bindir = 'exe'
|
35
36
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
36
|
-
spec.require_paths = [
|
37
|
-
|
38
|
-
|
39
|
-
spec.add_dependency
|
40
|
-
spec.add_dependency
|
41
|
-
|
42
|
-
spec.
|
43
|
-
|
37
|
+
spec.require_paths = ['lib']
|
38
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
39
|
+
|
40
|
+
spec.add_dependency 'chronicle-core', '~> 0.3'
|
41
|
+
spec.add_dependency 'chronicle-etl', '~> 0.6'
|
42
|
+
spec.add_dependency 'phonelib', '~> 0.6'
|
43
|
+
spec.add_dependency 'sqlite3', '~> 1.4'
|
44
|
+
|
45
|
+
spec.add_development_dependency 'bundler', '~> 2.3'
|
46
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.10'
|
47
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
48
|
+
spec.add_development_dependency 'rubocop', '~> 1.63'
|
44
49
|
end
|
@@ -5,11 +5,13 @@ module Chronicle
|
|
5
5
|
module Imessage
|
6
6
|
class ImessageExtractor < Chronicle::ETL::Extractor
|
7
7
|
register_connector do |r|
|
8
|
-
r.
|
8
|
+
r.source = :imessage
|
9
|
+
r.type = :message
|
10
|
+
r.strategy = :local_db
|
9
11
|
r.description = 'a local imessage database'
|
10
12
|
end
|
11
13
|
|
12
|
-
setting :
|
14
|
+
setting :input, default: File.join(Dir.home, 'Library', 'Messages', 'chat.db'), required: true
|
13
15
|
setting :load_attachments, default: false
|
14
16
|
setting :only_attachments, default: false
|
15
17
|
setting :my_phone_number
|
@@ -30,7 +32,7 @@ module Chronicle
|
|
30
32
|
meta[:my_phone_contact] = @my_phone_contact if @my_phone_contact.values.all?
|
31
33
|
meta[:my_icloud_account] = @my_icloud_account if @my_icloud_account.values.all?
|
32
34
|
|
33
|
-
yield
|
35
|
+
yield build_extraction(data: message, meta:)
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
@@ -40,8 +42,12 @@ module Chronicle
|
|
40
42
|
|
41
43
|
private
|
42
44
|
|
45
|
+
def db_file
|
46
|
+
[@config.input].flatten.first
|
47
|
+
end
|
48
|
+
|
43
49
|
def prepare_data
|
44
|
-
@db = SQLite3::Database.new(
|
50
|
+
@db = SQLite3::Database.new(db_file, results_as_hash: true)
|
45
51
|
@local_contacts = LocalContacts.new
|
46
52
|
@contacts = @local_contacts.contacts
|
47
53
|
|
@@ -1,164 +1,114 @@
|
|
1
1
|
require 'chronicle/etl'
|
2
|
+
require 'chronicle/models'
|
2
3
|
|
3
4
|
module Chronicle
|
4
|
-
module Imessage
|
5
|
+
module Imessage
|
5
6
|
class ImessageTransformer < Chronicle::ETL::Transformer
|
6
7
|
register_connector do |r|
|
7
|
-
r.
|
8
|
+
r.source = :imessage
|
9
|
+
r.type = :message
|
10
|
+
r.strategy = :local_db
|
8
11
|
r.description = 'a row from a local imessage database'
|
12
|
+
r.from_schema = :extraction
|
13
|
+
r.to_schema = :chronicle
|
9
14
|
end
|
10
15
|
|
11
|
-
def transform
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
def transform(record)
|
17
|
+
participants = record.extraction.meta[:participants].map { |p| build_identity(record.data, p) }
|
18
|
+
my_identity = build_identity_mine(record.data, record.extraction.meta[:my_icloud_account],
|
19
|
+
record.extraction.meta[:my_phone_contact])
|
15
20
|
|
16
|
-
|
17
|
-
record = build_messaged
|
18
|
-
record
|
19
|
-
end
|
20
|
-
|
21
|
-
def timestamp
|
22
|
-
Time.at(ios_timestamp_to_unix(@message['date'].to_i / 1000000000))
|
23
|
-
end
|
24
|
-
|
25
|
-
def id
|
26
|
-
@message['guid']
|
21
|
+
build_action(record.data, my_identity, participants)
|
27
22
|
end
|
28
23
|
|
29
24
|
private
|
30
25
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@actor = me
|
37
|
-
@consumers = @participants.collect{|p| build_identity(p)}
|
26
|
+
def build_action(message, my_identity, participants)
|
27
|
+
if message['is_from_me'] == 1
|
28
|
+
participants -= [my_identity]
|
29
|
+
agent = my_identity
|
30
|
+
consumers = participants
|
38
31
|
else
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
@consumers = receivers.collect{|p| build_identity(p)}
|
43
|
-
@consumers << me
|
44
|
-
@actor = build_identity(sender)
|
32
|
+
agent = participants.select { |p| p.slug == message['id'] }.first
|
33
|
+
consumers = participants - [agent] + [my_identity]
|
45
34
|
end
|
46
|
-
end
|
47
35
|
|
48
|
-
|
49
|
-
record = ::Chronicle::ETL::Models::Activity.new
|
50
|
-
record.end_at = timestamp
|
51
|
-
record.verb = 'messaged'
|
52
|
-
record.provider_id = id
|
53
|
-
record.provider = build_provider(@message['service'])
|
54
|
-
record.dedupe_on = [[:provider, :verb, :provider_id]]
|
36
|
+
raise Chronicle::ETL::UntransformableRecordError, 'Could not find agent' unless agent
|
55
37
|
|
56
|
-
|
57
|
-
|
38
|
+
Chronicle::Models::CommunicateAction.new do |r|
|
39
|
+
r.end_time = Time.at(ios_timestamp_to_unix(message['date'].to_i / 1_000_000_000))
|
40
|
+
r.source = entity_source(message['service'])
|
41
|
+
r.source_id = message['guid']
|
58
42
|
|
59
|
-
|
43
|
+
r.agent = agent
|
44
|
+
r.object = build_message(message, consumers)
|
45
|
+
r.dedupe_on = [%i[source source_id type]]
|
46
|
+
end
|
60
47
|
end
|
61
48
|
|
62
|
-
def build_message
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
record.contains = @attachments.map{ |a| build_attachment(a)}.compact
|
72
|
-
|
73
|
-
record
|
49
|
+
def build_message(message, consumers)
|
50
|
+
Chronicle::Models::Message.new do |r|
|
51
|
+
# TODO: handle text that's in `attributedBody`
|
52
|
+
r.text = normalized_body(message)
|
53
|
+
r.source = 'imessage'
|
54
|
+
r.source_id = message['guid']
|
55
|
+
r.recipient = consumers
|
56
|
+
r.dedupe_on = [%i[source source_id type]]
|
57
|
+
end
|
74
58
|
end
|
75
59
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
attachment_filename = attachment['filename'].gsub("~", Dir.home)
|
84
|
-
return unless File.exist?(attachment_filename)
|
85
|
-
|
86
|
-
attachment_data = ::Chronicle::ETL::Utils::BinaryAttachments.filename_to_base64(filename: attachment_filename, mimetype: attachment['mime_type'])
|
87
|
-
recognized_text = ::Chronicle::ETL::Utils::TextRecognition.recognize_in_image(filename: attachment_filename) if type == 'image'
|
88
|
-
|
89
|
-
record = ::Chronicle::ETL::Models::Entity.new
|
90
|
-
record.provider = 'imessage'
|
91
|
-
record.provider_id = attachment['guid']
|
92
|
-
record.represents = type
|
93
|
-
record.title = File.basename(attachment['filename'])
|
94
|
-
record.metadata[:ocr_text] = recognized_text if recognized_text
|
95
|
-
record.dedupe_on = [[:provider, :provider_id, :represents]]
|
96
|
-
|
97
|
-
attachment = ::Chronicle::ETL::Models::Attachment.new
|
98
|
-
attachment.data = attachment_data
|
99
|
-
record.attachments = [attachment]
|
100
|
-
|
101
|
-
record
|
60
|
+
def build_identity_mine(message, my_icloud_account, my_phone_contact)
|
61
|
+
case agent_source(message['service'])
|
62
|
+
when 'icloud'
|
63
|
+
build_identity_mine_icloud(my_icloud_account)
|
64
|
+
when 'phone'
|
65
|
+
build_identity_mine_phone(my_phone_contact)
|
66
|
+
end
|
102
67
|
end
|
103
68
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
slug: identity['id'],
|
110
|
-
title: identity['full_name'],
|
111
|
-
provider: identity_provider(@message['service']),
|
112
|
-
})
|
113
|
-
record.dedupe_on = [[:represents, :slug, :provider]]
|
114
|
-
record
|
115
|
-
end
|
69
|
+
def build_identity_mine_icloud(icloud_account)
|
70
|
+
unless icloud_account
|
71
|
+
raise(Chronicle::ETL::UntransformableRecordError,
|
72
|
+
'Could not build record due to missing iCloud details. Please provide them through the extractor settings.')
|
73
|
+
end
|
116
74
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
75
|
+
Chronicle::Models::Person.new do |r|
|
76
|
+
r.name = icloud_account[:display_name]
|
77
|
+
r.source = 'icloud'
|
78
|
+
r.slug = icloud_account[:id]
|
79
|
+
r.source_id = icloud_account[:dsid]
|
80
|
+
r.dedupe_on = [%i[type source source_id]]
|
123
81
|
end
|
124
82
|
end
|
125
83
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
slug
|
136
|
-
|
137
|
-
|
138
|
-
record
|
84
|
+
def build_identity_mine_phone(phone_account)
|
85
|
+
unless phone_account
|
86
|
+
raise(Chronicle::ETL::UntransformableRecordError,
|
87
|
+
'Could not build record due to missing phone details. Please provide them through the extractor settings.')
|
88
|
+
end
|
89
|
+
|
90
|
+
Chronicle::Models::Person.new do |r|
|
91
|
+
r.name = phone_account[:name]
|
92
|
+
r.source = 'phone'
|
93
|
+
r.slug = phone_account[:phone_number]
|
94
|
+
r.dedupe_on = [%i[type source slug]]
|
95
|
+
end
|
139
96
|
end
|
140
97
|
|
141
|
-
def
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
title: phone_account[:name],
|
149
|
-
slug: phone_account[:phone_number]
|
150
|
-
})
|
151
|
-
record.dedupe_on << [:provider, :represents, :slug]
|
152
|
-
record
|
98
|
+
def build_identity(message, identity)
|
99
|
+
Chronicle::Models::Person.new do |r|
|
100
|
+
r.name = identity['full_name']
|
101
|
+
r.source = agent_source(message['service'])
|
102
|
+
r.slug = identity['id']
|
103
|
+
r.dedupe_on = [%i[type source slug]]
|
104
|
+
end
|
153
105
|
end
|
154
106
|
|
155
|
-
|
156
|
-
def build_provider service
|
107
|
+
def entity_source(service)
|
157
108
|
service ? service.downcase : 'imessage'
|
158
109
|
end
|
159
110
|
|
160
|
-
|
161
|
-
def identity_provider service
|
111
|
+
def agent_source(service)
|
162
112
|
case service
|
163
113
|
# an SMS message is on the 'sms' provider but the provider of the identity used to send it is 'phone'
|
164
114
|
when 'SMS'then 'phone'
|
@@ -169,12 +119,72 @@ module Chronicle
|
|
169
119
|
end
|
170
120
|
|
171
121
|
# FIXME: refactor to shared
|
172
|
-
def ios_timestamp_to_unix
|
173
|
-
ts +
|
122
|
+
def ios_timestamp_to_unix(ts)
|
123
|
+
ts + 978_307_200
|
174
124
|
end
|
175
|
-
|
176
|
-
|
125
|
+
|
126
|
+
def unix_to_ios_timestamp(ts)
|
127
|
+
ts - 978_307_200
|
128
|
+
end
|
129
|
+
|
130
|
+
def normalized_body(message)
|
131
|
+
message['text'] || normalize_attributed_body(message['attributedBody'])
|
177
132
|
end
|
133
|
+
|
134
|
+
# Based on https://github.com/kndonlee/meds/blob/224be297e8e709e6a52aca5fa05ec42d34af1aef/all_messages.rb#L31
|
135
|
+
def normalize_attributed_body(body)
|
136
|
+
return unless body
|
137
|
+
|
138
|
+
attributed_body = body.force_encoding('UTF-8').encode('UTF-8', invalid: :replace)
|
139
|
+
|
140
|
+
return unless attributed_body.include?('NSNumber')
|
141
|
+
|
142
|
+
attributed_body = attributed_body.split('NSNumber')[0]
|
143
|
+
return unless attributed_body.include?('NSString')
|
144
|
+
|
145
|
+
attributed_body = attributed_body.split('NSString')[1]
|
146
|
+
return unless attributed_body.include?('NSDictionary')
|
147
|
+
|
148
|
+
attributed_body = attributed_body.split('NSDictionary')[0]
|
149
|
+
attributed_body = attributed_body[6..-13]
|
150
|
+
|
151
|
+
if attributed_body =~ /^.[\u0000]/
|
152
|
+
attributed_body.gsub(/^.[\u0000]/, '')
|
153
|
+
else
|
154
|
+
attributed_body
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# def build_attachment(attachment)
|
159
|
+
# return unless attachment['mime_type']
|
160
|
+
|
161
|
+
# type, subtype = attachment['mime_type'].split('/')
|
162
|
+
# return unless %w[image audio video].include?(type)
|
163
|
+
# return unless attachment['filename']
|
164
|
+
|
165
|
+
# attachment_filename = attachment['filename'].gsub('~', Dir.home)
|
166
|
+
# return unless File.exist?(attachment_filename)
|
167
|
+
|
168
|
+
# attachment_data = ::Chronicle::ETL::Utils::BinaryAttachments.filename_to_base64(filename: attachment_filename,
|
169
|
+
# mimetype: attachment['mime_type'])
|
170
|
+
# if type == 'image'
|
171
|
+
# recognized_text = ::Chronicle::ETL::Utils::TextRecognition.recognize_in_image(filename: attachment_filename)
|
172
|
+
# end
|
173
|
+
|
174
|
+
# record = ::Chronicle::ETL::Models::Entity.new
|
175
|
+
# record.provider = 'imessage'
|
176
|
+
# record.provider_id = attachment['guid']
|
177
|
+
# record.represents = type
|
178
|
+
# record.title = File.basename(attachment['filename'])
|
179
|
+
# record.metadata[:ocr_text] = recognized_text if recognized_text
|
180
|
+
# record.dedupe_on = [%i[provider provider_id represents]]
|
181
|
+
|
182
|
+
# attachment = ::Chronicle::ETL::Models::Attachment.new
|
183
|
+
# attachment.data = attachment_data
|
184
|
+
# record.attachments = [attachment]
|
185
|
+
|
186
|
+
# record
|
187
|
+
# end
|
178
188
|
end
|
179
189
|
end
|
180
190
|
end
|
data/lib/chronicle/imessage.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'chronicle/imessage/version'
|
2
|
+
require 'chronicle/imessage/imessage_extractor'
|
3
|
+
require 'chronicle/imessage/imessage_transformer'
|
4
|
+
require 'chronicle/imessage/local_contacts'
|
5
5
|
|
6
6
|
module Chronicle
|
7
7
|
module Imessage
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chronicle-imessage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Louis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: chronicle-
|
14
|
+
name: chronicle-core
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: chronicle-etl
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0.6'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0.6'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: phonelib
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.4'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: bundler
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,20 +80,48 @@ dependencies:
|
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '2.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.10'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.10'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: rake
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
72
100
|
requirements:
|
73
101
|
- - "~>"
|
74
102
|
- !ruby/object:Gem::Version
|
75
|
-
version: 13.0
|
103
|
+
version: '13.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '13.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.63'
|
76
118
|
type: :development
|
77
119
|
prerelease: false
|
78
120
|
version_requirements: !ruby/object:Gem::Requirement
|
79
121
|
requirements:
|
80
122
|
- - "~>"
|
81
123
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
124
|
+
version: '1.63'
|
83
125
|
description: Connectors for iMessage
|
84
126
|
email:
|
85
127
|
- andrew@hyfen.net
|
@@ -88,6 +130,7 @@ extensions: []
|
|
88
130
|
extra_rdoc_files: []
|
89
131
|
files:
|
90
132
|
- ".gitignore"
|
133
|
+
- ".rubocop.yml"
|
91
134
|
- CODE_OF_CONDUCT.md
|
92
135
|
- Gemfile
|
93
136
|
- README.md
|
@@ -107,6 +150,7 @@ metadata:
|
|
107
150
|
homepage_uri: https://github.com/chronicle-app/chronicle-imessage
|
108
151
|
source_code_uri: https://github.com/chronicle-app/chronicle-imessage
|
109
152
|
changelog_uri: https://github.com/chronicle-app/chronicle-imessage
|
153
|
+
rubygems_mfa_required: 'true'
|
110
154
|
post_install_message:
|
111
155
|
rdoc_options: []
|
112
156
|
require_paths:
|
@@ -115,14 +159,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
115
159
|
requirements:
|
116
160
|
- - ">="
|
117
161
|
- !ruby/object:Gem::Version
|
118
|
-
version: '
|
162
|
+
version: '3.1'
|
119
163
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
164
|
requirements:
|
121
165
|
- - ">="
|
122
166
|
- !ruby/object:Gem::Version
|
123
167
|
version: '0'
|
124
168
|
requirements: []
|
125
|
-
rubygems_version: 3.
|
169
|
+
rubygems_version: 3.4.10
|
126
170
|
signing_key:
|
127
171
|
specification_version: 4
|
128
172
|
summary: iMessage importer for Chronicle
|