chronicle-safari 0.1.2 → 0.2.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/bin/console +4 -12
- data/chronicle-safari.gemspec +29 -24
- data/lib/chronicle/safari/{safari_extractor.rb → browse_extractor.rb} +16 -11
- data/lib/chronicle/safari/browse_transformer.rb +51 -0
- data/lib/chronicle/safari/version.rb +1 -1
- data/lib/chronicle/safari.rb +3 -3
- metadata +70 -12
- data/lib/chronicle/safari/safari_transformer.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7330b68fd8e6fc1a77c118d177ae175dc42567e760b34332723227bbd6f011cf
|
4
|
+
data.tar.gz: 7f6c17d05026554124eb50c52e0ca2119a3e377859b48404a81a2183883961ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94711ac7afd35f5d0427d909c75f4b3b89d7ec6075ea8e88a6242d82ebdefb7ecd19b174c9cae75e2f07651efe58d8e302bca543e3f0a564c4346af3b8a090e2
|
7
|
+
data.tar.gz: 0c3b6e5211641cddcf462daab83f1d0f787e769a8715b4f410b59fe558aee9ab9d2471284a0a9c5b0fb37ad5e4278fb637ae6aaba64a43065a5dfe89e9bfd58e
|
data/.rubocop.yml
ADDED
data/bin/console
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'chronicle/safari'
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
-
# require "pry"
|
12
|
-
# Pry.start
|
13
|
-
|
14
|
-
require "irb"
|
15
|
-
IRB.start(__FILE__)
|
6
|
+
require 'pry'
|
7
|
+
Pry.start
|
data/chronicle-safari.gemspec
CHANGED
@@ -1,45 +1,50 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path(
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
-
require
|
5
|
+
require 'chronicle/safari/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = 'chronicle-safari'
|
9
9
|
spec.version = Chronicle::Safari::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
10
|
+
spec.authors = ['Andrew Louis']
|
11
|
+
spec.email = ['andrew@hyfen.net']
|
12
12
|
|
13
|
-
spec.summary =
|
14
|
-
spec.description =
|
15
|
-
spec.homepage =
|
13
|
+
spec.summary = 'Safari importer for Chronicle'
|
14
|
+
spec.description = 'Import your safari history'
|
15
|
+
spec.homepage = 'https://github.com/chronicle-app/chronicle-safari'
|
16
16
|
|
17
17
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
18
|
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
19
|
if spec.respond_to?(:metadata)
|
20
|
-
spec.metadata['allowed_push_host'] =
|
20
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
21
21
|
|
22
|
-
spec.metadata[
|
23
|
-
spec.metadata[
|
24
|
-
spec.metadata[
|
22
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
23
|
+
spec.metadata['source_code_uri'] = 'https://github.com/chronicle-app/chronicle-safari'
|
24
|
+
spec.metadata['changelog_uri'] = 'https://github.com/chronicle-app/chronicle-safari'
|
25
25
|
else
|
26
|
-
raise
|
27
|
-
|
26
|
+
raise 'RubyGems 2.0 or newer is required to protect against ' \
|
27
|
+
'public gem pushes.'
|
28
28
|
end
|
29
29
|
|
30
30
|
# Specify which files should be added to the gem when it is released.
|
31
31
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
32
|
-
spec.files
|
32
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
33
33
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
34
34
|
end
|
35
|
-
spec.bindir =
|
35
|
+
spec.bindir = 'exe'
|
36
36
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
|
-
spec.require_paths = [
|
38
|
-
|
39
|
-
spec.add_dependency
|
40
|
-
spec.add_dependency
|
41
|
-
|
42
|
-
spec.
|
43
|
-
spec.
|
44
|
-
|
37
|
+
spec.require_paths = ['lib']
|
38
|
+
|
39
|
+
spec.add_dependency 'chronicle-core', '~> 0.3'
|
40
|
+
spec.add_dependency 'chronicle-etl', '~> 0.6'
|
41
|
+
spec.add_dependency 'faraday', '~> 2'
|
42
|
+
spec.add_dependency 'omniauth-oauth2', '~> 1'
|
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'
|
49
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
45
50
|
end
|
@@ -2,10 +2,12 @@ require 'chronicle/etl'
|
|
2
2
|
require 'sqlite3'
|
3
3
|
|
4
4
|
module Chronicle
|
5
|
-
module Safari
|
6
|
-
class
|
5
|
+
module Safari
|
6
|
+
class BrowseExtractor < Chronicle::ETL::Extractor
|
7
7
|
register_connector do |r|
|
8
|
-
r.
|
8
|
+
r.source = :safari
|
9
|
+
r.type = :browse
|
10
|
+
r.strategy = :local_db
|
9
11
|
r.description = 'browser history'
|
10
12
|
end
|
11
13
|
|
@@ -23,7 +25,10 @@ module Chronicle
|
|
23
25
|
def extract
|
24
26
|
@history.each do |entry|
|
25
27
|
entry.transform_keys!(&:to_sym)
|
26
|
-
|
28
|
+
|
29
|
+
meta = {}
|
30
|
+
meta[:my_icloud_account] = @icloud_account
|
31
|
+
yield build_extraction(data: entry, meta:)
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
@@ -50,22 +55,22 @@ module Chronicle
|
|
50
55
|
|
51
56
|
def load_history
|
52
57
|
conditions = []
|
53
|
-
conditions <<
|
58
|
+
conditions << 'history_visits.redirect_destination IS NULL'
|
54
59
|
conditions << "visit_time_utc > '#{@config.since.utc}'" if @config.since
|
55
60
|
conditions << "visit_time_utc < '#{@config.until.utc}'" if @config.until
|
56
61
|
|
57
62
|
sql = <<~SQL
|
58
63
|
SELECT
|
59
64
|
*,
|
60
|
-
datetime(visit_time + 978307200, 'unixepoch') as visit_time_utc
|
65
|
+
datetime(visit_time + 978307200, 'unixepoch') as visit_time_utc
|
61
66
|
FROM
|
62
|
-
history_visits
|
67
|
+
history_visits
|
63
68
|
LEFT JOIN
|
64
|
-
history_items
|
65
|
-
ON history_items.id = history_item
|
69
|
+
history_items
|
70
|
+
ON history_items.id = history_item
|
66
71
|
SQL
|
67
|
-
sql += " WHERE #{conditions.join(
|
68
|
-
sql +=
|
72
|
+
sql += " WHERE #{conditions.join(' AND ')}" if conditions.any?
|
73
|
+
sql += ' ORDER BY visit_time_utc DESC'
|
69
74
|
sql += " LIMIT #{@config.limit}" if @config.limit
|
70
75
|
|
71
76
|
results = @db.execute(sql)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'chronicle/etl'
|
2
|
+
require 'chronicle/models'
|
3
|
+
|
4
|
+
module Chronicle
|
5
|
+
module Safari
|
6
|
+
class BrowseTransformer < Chronicle::ETL::Transformer
|
7
|
+
register_connector do |r|
|
8
|
+
r.source = :safari
|
9
|
+
r.type = :browse
|
10
|
+
r.strategy = :local_db
|
11
|
+
r.description = 'a history item'
|
12
|
+
r.from_schema = :extraction
|
13
|
+
r.to_schema = :chronicle
|
14
|
+
end
|
15
|
+
|
16
|
+
def transform(record)
|
17
|
+
build_browse(record.data, record.extraction.meta[:my_icloud_account])
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def build_browse(data, icloud_account)
|
23
|
+
Chronicle::Models::ViewAction.new do |r|
|
24
|
+
r.source = 'safari'
|
25
|
+
r.end_time = Time.parse(data[:visit_time_utc])
|
26
|
+
r.agent = build_agent(icloud_account)
|
27
|
+
r.object = build_site(data)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_site(data)
|
32
|
+
Chronicle::Models::Thing.new do |r|
|
33
|
+
r.name = data[:title]
|
34
|
+
r.url = data[:url]
|
35
|
+
|
36
|
+
r.dedupe_on = [[:url]]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def build_agent(icloud_account)
|
41
|
+
Chronicle::Models::Person.new do |r|
|
42
|
+
r.name = icloud_account[:display_name]
|
43
|
+
r.source = 'icloud'
|
44
|
+
r.slug = icloud_account[:id]
|
45
|
+
r.source_id = icloud_account[:dsid]
|
46
|
+
r.dedupe_on = [%i[type source source_id]]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/chronicle/safari.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative 'safari/version'
|
4
|
+
require_relative 'safari/browse_extractor'
|
5
|
+
require_relative 'safari/browse_transformer'
|
6
6
|
|
7
7
|
module Chronicle
|
8
8
|
module Safari
|
metadata
CHANGED
@@ -1,29 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chronicle-safari
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chronicle-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.3'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: chronicle-etl
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
31
|
- - "~>"
|
18
32
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
33
|
+
version: '0.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faraday
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: omniauth-oauth2
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1'
|
20
62
|
type: :runtime
|
21
63
|
prerelease: false
|
22
64
|
version_requirements: !ruby/object:Gem::Requirement
|
23
65
|
requirements:
|
24
66
|
- - "~>"
|
25
67
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
68
|
+
version: '1'
|
27
69
|
- !ruby/object:Gem::Dependency
|
28
70
|
name: sqlite3
|
29
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,34 +94,48 @@ dependencies:
|
|
52
94
|
- - "~>"
|
53
95
|
- !ruby/object:Gem::Version
|
54
96
|
version: '2.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.10'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.10'
|
55
111
|
- !ruby/object:Gem::Dependency
|
56
112
|
name: rake
|
57
113
|
requirement: !ruby/object:Gem::Requirement
|
58
114
|
requirements:
|
59
115
|
- - "~>"
|
60
116
|
- !ruby/object:Gem::Version
|
61
|
-
version: 13.0
|
117
|
+
version: '13.0'
|
62
118
|
type: :development
|
63
119
|
prerelease: false
|
64
120
|
version_requirements: !ruby/object:Gem::Requirement
|
65
121
|
requirements:
|
66
122
|
- - "~>"
|
67
123
|
- !ruby/object:Gem::Version
|
68
|
-
version: 13.0
|
124
|
+
version: '13.0'
|
69
125
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
126
|
+
name: rubocop
|
71
127
|
requirement: !ruby/object:Gem::Requirement
|
72
128
|
requirements:
|
73
129
|
- - "~>"
|
74
130
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
131
|
+
version: '1.63'
|
76
132
|
type: :development
|
77
133
|
prerelease: false
|
78
134
|
version_requirements: !ruby/object:Gem::Requirement
|
79
135
|
requirements:
|
80
136
|
- - "~>"
|
81
137
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
138
|
+
version: '1.63'
|
83
139
|
description: Import your safari history
|
84
140
|
email:
|
85
141
|
- andrew@hyfen.net
|
@@ -88,6 +144,7 @@ extensions: []
|
|
88
144
|
extra_rdoc_files: []
|
89
145
|
files:
|
90
146
|
- ".gitignore"
|
147
|
+
- ".rubocop.yml"
|
91
148
|
- CODE_OF_CONDUCT.md
|
92
149
|
- Gemfile
|
93
150
|
- README.md
|
@@ -96,8 +153,8 @@ files:
|
|
96
153
|
- bin/setup
|
97
154
|
- chronicle-safari.gemspec
|
98
155
|
- lib/chronicle/safari.rb
|
99
|
-
- lib/chronicle/safari/
|
100
|
-
- lib/chronicle/safari/
|
156
|
+
- lib/chronicle/safari/browse_extractor.rb
|
157
|
+
- lib/chronicle/safari/browse_transformer.rb
|
101
158
|
- lib/chronicle/safari/version.rb
|
102
159
|
homepage: https://github.com/chronicle-app/chronicle-safari
|
103
160
|
licenses: []
|
@@ -106,6 +163,7 @@ metadata:
|
|
106
163
|
homepage_uri: https://github.com/chronicle-app/chronicle-safari
|
107
164
|
source_code_uri: https://github.com/chronicle-app/chronicle-safari
|
108
165
|
changelog_uri: https://github.com/chronicle-app/chronicle-safari
|
166
|
+
rubygems_mfa_required: 'true'
|
109
167
|
post_install_message:
|
110
168
|
rdoc_options: []
|
111
169
|
require_paths:
|
@@ -121,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
179
|
- !ruby/object:Gem::Version
|
122
180
|
version: '0'
|
123
181
|
requirements: []
|
124
|
-
rubygems_version: 3.
|
182
|
+
rubygems_version: 3.4.10
|
125
183
|
signing_key:
|
126
184
|
specification_version: 4
|
127
185
|
summary: Safari importer for Chronicle
|
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'chronicle/etl'
|
2
|
-
|
3
|
-
module Chronicle
|
4
|
-
module Safari
|
5
|
-
class SafariTransformer < Chronicle::ETL::Transformer
|
6
|
-
register_connector do |r|
|
7
|
-
r.provider = 'safari'
|
8
|
-
r.description = 'a history item'
|
9
|
-
end
|
10
|
-
|
11
|
-
def transform
|
12
|
-
@data = @extraction.data
|
13
|
-
build_browsed
|
14
|
-
end
|
15
|
-
|
16
|
-
def id
|
17
|
-
# IDs from local db aren't global or stable across multiple installs
|
18
|
-
end
|
19
|
-
|
20
|
-
def timestamp
|
21
|
-
Time.parse(@data[:visit_time_utc])
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def build_browsed
|
27
|
-
record = ::Chronicle::ETL::Models::Activity.new({
|
28
|
-
verb: 'browsed',
|
29
|
-
provider: 'safari',
|
30
|
-
end_at: timestamp
|
31
|
-
})
|
32
|
-
record.dedupe_on << [:provider, :verb, :end_at]
|
33
|
-
record.actor = build_actor
|
34
|
-
record.involved = build_involved
|
35
|
-
record
|
36
|
-
end
|
37
|
-
|
38
|
-
def build_involved
|
39
|
-
record = ::Chronicle::ETL::Models::Entity.new({
|
40
|
-
title: @data[:title],
|
41
|
-
provider_url: @data[:url],
|
42
|
-
})
|
43
|
-
record.dedupe_on << [:provider_url]
|
44
|
-
record
|
45
|
-
end
|
46
|
-
|
47
|
-
def build_actor
|
48
|
-
record = ::Chronicle::ETL::Models::Entity.new({
|
49
|
-
represents: 'identity',
|
50
|
-
provider: 'icloud',
|
51
|
-
provider_id: @extraction.meta[:icloud_account][:dsid],
|
52
|
-
title: @extraction.meta[:icloud_account][:display_name],
|
53
|
-
slug: @extraction.meta[:icloud_account][:id]
|
54
|
-
})
|
55
|
-
record.dedupe_on << [:provider, :represents, :slug]
|
56
|
-
record
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|