nosy 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -1
- data/README.md +59 -3
- data/bin/nosy +13 -0
- data/lib/nosy.rb +29 -0
- data/lib/nosy/output.rb +49 -0
- data/lib/nosy/output/html_helpers.rb +162 -0
- data/nosy.gemspec +8 -5
- data/spec/nosy/output_spec.rb +140 -0
- data/spec/nosy_spec.rb +50 -0
- data/spec/spec_helper.rb +6 -0
- metadata +38 -10
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -12,6 +12,13 @@ Nosy returns an array of messages with the fields
|
|
12
12
|
* imessage (Boolean)
|
13
13
|
* date (contains a unix timestamp)
|
14
14
|
|
15
|
+
which can then be outputted to
|
16
|
+
|
17
|
+
* a html file (default)
|
18
|
+
* a json string
|
19
|
+
* a json document
|
20
|
+
* a csv documents
|
21
|
+
|
15
22
|
|
16
23
|
## Install
|
17
24
|
|
@@ -19,7 +26,37 @@ Nosy returns an array of messages with the fields
|
|
19
26
|
|
20
27
|
Or add Nosy to your Gemfile and run `bundle install`.
|
21
28
|
|
29
|
+
## From the command line
|
30
|
+
|
31
|
+
Nosy can be run from the command line using:
|
32
|
+
|
33
|
+
# Find, parse and output to an HTML file
|
34
|
+
$ nosy
|
35
|
+
|
36
|
+
# … to a JSON file
|
37
|
+
$ nosy json true
|
38
|
+
|
39
|
+
# … to a JSON string
|
40
|
+
$ nosy json false
|
41
|
+
|
42
|
+
# … to a CSV file
|
43
|
+
$ nosy csv
|
44
|
+
|
45
|
+
Note: This will only work on a Mac OSX system. Nosy (is nosy, and) will try to grab your iOS message database, parse it, and then export it, but only knows where the files are stored on a Mac system.
|
46
|
+
|
22
47
|
## Find and Parse
|
48
|
+
If you are on a Mac OSX system, Nosy (is nosy, and) will try to grab your iOS message database, parse it, and then export it.
|
49
|
+
|
50
|
+
all_texts = Nosy.hunt_and_parse
|
51
|
+
|
52
|
+
all_texts.each do |text|
|
53
|
+
text.receiver
|
54
|
+
text.sender
|
55
|
+
text.message
|
56
|
+
text.imessage
|
57
|
+
text.date
|
58
|
+
end
|
59
|
+
|
23
60
|
If you are on a Mac OSX system, Nosy (is nosy, and) will try to grab your iOS message database and parse it.
|
24
61
|
|
25
62
|
all_texts = Nosy.hunt_and_parse
|
@@ -78,7 +115,7 @@ Nosy can search through the texts in your iOS message database. Nosy searching s
|
|
78
115
|
* imessage
|
79
116
|
* date - supports a Unix timestamp and an optional leading operator [ < , > , <= , >= ]
|
80
117
|
|
81
|
-
|
118
|
+
Note
|
82
119
|
|
83
120
|
nosty_texts = Nosy.new(iphone_database_location)
|
84
121
|
|
@@ -89,7 +126,27 @@ Nosy can search through the texts in your iOS message database. Nosy searching s
|
|
89
126
|
before_then_texts = nosty_texts.search(:date => "<1273175931")
|
90
127
|
|
91
128
|
# Array of texts where I am the sender and the date is less than 1273175931
|
92
|
-
before_then_texts = nosty_texts.search(:sender => "me", :date => "<1273175931")
|
129
|
+
before_then_texts = nosty_texts.search(:sender => "me", :date => "<1273175931")`
|
130
|
+
|
131
|
+
## Outputting
|
132
|
+
|
133
|
+
If you provide nosy with an array of texts it will be able to output them to a html file, json string, json file, or csv. The method will return the location of the file.
|
134
|
+
|
135
|
+
# All texts to a json file
|
136
|
+
all_texts = Nosy.hunt_and_parse
|
137
|
+
Nosy.output(all_texts, "json", true)
|
138
|
+
|
139
|
+
# All texts to a json string
|
140
|
+
Nosy.output(all_texts, "json", false)
|
141
|
+
|
142
|
+
# Texts from me to a csv file
|
143
|
+
nosty_texts = Nosy.new(iphone_database_location)
|
144
|
+
my_sent_texts = nosty_texts.search(:sender => "me")
|
145
|
+
Nosy.output(my_sent_texts, "csv")
|
146
|
+
|
147
|
+
# Texts from me to a html file
|
148
|
+
Nosy.output(my_sent_texts, "html")
|
149
|
+
|
93
150
|
|
94
151
|
## Contributions
|
95
152
|
Contributions, improvements, and suggestions more than welcome! Please!
|
@@ -101,7 +158,6 @@ Currently, Nosy is yet to...
|
|
101
158
|
* Properly handle MMS (group and media) messages.
|
102
159
|
* Let you search for two values in one key.
|
103
160
|
* Let you hunt for the iOS message database on systems other than Mac OSX.
|
104
|
-
* Support creating a backup file.
|
105
161
|
* Run on Heroku due to its dependency on Sqlite3.
|
106
162
|
|
107
163
|
## Acknowledgment
|
data/bin/nosy
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'nosy'
|
4
|
+
|
5
|
+
if ARGV[0] == nil
|
6
|
+
p Nosy.hunt_parse_and_output
|
7
|
+
elsif ["html","json","csv"].include?(ARGV[0])
|
8
|
+
p Nosy.hunt_parse_and_output(ARGV[0], ARGV[1] == "true" ? true : false)
|
9
|
+
elsif ["hunt","find","locate"].include?(ARGV[0])
|
10
|
+
p Nosy.hunt
|
11
|
+
else
|
12
|
+
p Nosy.hunt_parse_and_output
|
13
|
+
end
|
data/lib/nosy.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "nosy/hunter"
|
2
|
+
require "nosy/output"
|
2
3
|
require "nosy/parser"
|
3
4
|
require "nosy/searcher"
|
4
5
|
|
@@ -12,6 +13,20 @@ module Nosy
|
|
12
13
|
Parser.new.parse(Hunter.new.hunt)
|
13
14
|
end
|
14
15
|
|
16
|
+
def self.hunt_parse_and_output(output_type="html", output_to_file=true)
|
17
|
+
if output_type == "json"
|
18
|
+
if output_to_file == true
|
19
|
+
Output.new.to_json(parse(Hunter.new.hunt), true)
|
20
|
+
else
|
21
|
+
Output.new.to_json(parse(Hunter.new.hunt), false)
|
22
|
+
end
|
23
|
+
elsif output_type == "csv"
|
24
|
+
Output.new.to_csv(parse(Hunter.new.hunt))
|
25
|
+
else
|
26
|
+
Output.new.to_html(parse(Hunter.new.hunt))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
15
30
|
def self.new(file)
|
16
31
|
Searcher.new(file)
|
17
32
|
end
|
@@ -23,4 +38,18 @@ module Nosy
|
|
23
38
|
def self.parse(file)
|
24
39
|
Parser.new.parse(file)
|
25
40
|
end
|
41
|
+
|
42
|
+
def self.output(texts, output_type="html", output_to_file=true)
|
43
|
+
if output_type == "json"
|
44
|
+
if output_to_file == true
|
45
|
+
Output.new.to_json(texts, true)
|
46
|
+
else
|
47
|
+
Output.new.to_json(texts, false)
|
48
|
+
end
|
49
|
+
elsif output_type == "csv"
|
50
|
+
Output.new.to_csv(texts)
|
51
|
+
else
|
52
|
+
Output.new.to_html(texts)
|
53
|
+
end
|
54
|
+
end
|
26
55
|
end
|
data/lib/nosy/output.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'nosy/output/html_helpers'
|
2
|
+
require 'json'
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
module Nosy
|
6
|
+
|
7
|
+
class Output
|
8
|
+
include HtmlHelpers
|
9
|
+
|
10
|
+
def to_html( texts )
|
11
|
+
File.open("iphone-texts.html","w") do |f|
|
12
|
+
generate_html(f, texts)
|
13
|
+
end
|
14
|
+
"#{Dir.pwd}/iphone-texts.html"
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_json( texts, file=false )
|
18
|
+
hash = to_hash(texts)
|
19
|
+
|
20
|
+
if file == true
|
21
|
+
File.open("iphone-texts.json","w") do |f|
|
22
|
+
f.write(hash.to_json)
|
23
|
+
end
|
24
|
+
"#{Dir.pwd}/iphone-texts.json"
|
25
|
+
else
|
26
|
+
hash.to_json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_csv( texts, output=nil )
|
31
|
+
CSV.open("iphone-texts.csv", "w") do |csv|
|
32
|
+
csv << ["id", "date", "sender", "receiver", "message", "imessage"]
|
33
|
+
texts.each_with_index do |text, index|
|
34
|
+
csv << [index+1, text.date, text.sender, text.receiver, text.message, text.imessage]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
"#{Dir.pwd}/iphone-texts.csv"
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_hash (texts)
|
41
|
+
hash = {}
|
42
|
+
texts.each_with_index do |m, index|
|
43
|
+
hash["#{index}"] = { date: m.date, sender: m.sender, receiver: m.receiver, message: m.message, imessage: m.imessage }
|
44
|
+
end
|
45
|
+
hash
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module Nosy
|
2
|
+
|
3
|
+
class Output
|
4
|
+
|
5
|
+
module HtmlHelpers
|
6
|
+
|
7
|
+
def generate_html(f, texts)
|
8
|
+
f.puts "<!doctype html><head>#{head}<style>#{css}</style></head><body><div id='container'>"
|
9
|
+
texts.each do |text|
|
10
|
+
if text.sender == "me"
|
11
|
+
f.puts "<article class='sending'>"
|
12
|
+
html_text(f, text)
|
13
|
+
f.puts "</article>"
|
14
|
+
else
|
15
|
+
f.puts "<article class='receiving'>"
|
16
|
+
html_text(f, text)
|
17
|
+
f.puts "</article>"
|
18
|
+
end
|
19
|
+
f.puts ""
|
20
|
+
f.puts "<hr />"
|
21
|
+
f.puts ""
|
22
|
+
end
|
23
|
+
f.puts "</div></body></html>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def css
|
27
|
+
"/* http://meyerweb.com/eric/tools/css/reset/
|
28
|
+
v2.0 | 20110126
|
29
|
+
License: none (public domain)
|
30
|
+
*/
|
31
|
+
|
32
|
+
html, body, div, span, applet, object, iframe,
|
33
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
34
|
+
a, abbr, acronym, address, big, cite, code,
|
35
|
+
del, dfn, em, img, ins, kbd, q, s, samp,
|
36
|
+
small, strike, strong, sub, sup, tt, var,
|
37
|
+
b, u, i, center,
|
38
|
+
dl, dt, dd, ol, ul, li,
|
39
|
+
fieldset, form, label, legend,
|
40
|
+
table, caption, tbody, tfoot, thead, tr, th, td,
|
41
|
+
article, aside, canvas, details, embed,
|
42
|
+
figure, figcaption, footer, header, hgroup,
|
43
|
+
menu, nav, output, ruby, section, summary,
|
44
|
+
time, mark, audio, video {
|
45
|
+
margin: 0;
|
46
|
+
padding: 0;
|
47
|
+
border: 0;
|
48
|
+
font-size: 100%;
|
49
|
+
font: inherit;
|
50
|
+
vertical-align: baseline;
|
51
|
+
}
|
52
|
+
/* HTML5 display-role reset for older browsers */
|
53
|
+
article, aside, details, figcaption, figure,
|
54
|
+
footer, header, hgroup, menu, nav, section {
|
55
|
+
display: block;
|
56
|
+
}
|
57
|
+
body {
|
58
|
+
line-height: 1;
|
59
|
+
}
|
60
|
+
ol, ul {
|
61
|
+
list-style: none;
|
62
|
+
}
|
63
|
+
blockquote, q {
|
64
|
+
quotes: none;
|
65
|
+
}
|
66
|
+
blockquote:before, blockquote:after,
|
67
|
+
q:before, q:after {
|
68
|
+
content: '';
|
69
|
+
content: none;
|
70
|
+
}
|
71
|
+
table {
|
72
|
+
border-collapse: collapse;
|
73
|
+
border-spacing: 0;
|
74
|
+
}
|
75
|
+
|
76
|
+
body{
|
77
|
+
background: #f9f8f6;
|
78
|
+
color: #606060;
|
79
|
+
font-family: Helvetica, Arial, sans-serif;
|
80
|
+
font-size: 18px;
|
81
|
+
line-height: 1.8333em;
|
82
|
+
padding: 40px 0;
|
83
|
+
word-wrap: break-word;
|
84
|
+
-webkit-font-smoothing: antialiased;
|
85
|
+
}
|
86
|
+
|
87
|
+
#container{
|
88
|
+
width: 400px;
|
89
|
+
margin: 0 auto;
|
90
|
+
padding: 0 40px;
|
91
|
+
}
|
92
|
+
|
93
|
+
hr {
|
94
|
+
border: none;
|
95
|
+
background-color: #ccc;
|
96
|
+
color: #ccc;
|
97
|
+
height: 1px;
|
98
|
+
margin: 45px 0;
|
99
|
+
}
|
100
|
+
|
101
|
+
article ul {
|
102
|
+
margin: 40px 0 0 0;
|
103
|
+
}
|
104
|
+
|
105
|
+
article ul li {
|
106
|
+
font-size: 0.6777em;
|
107
|
+
padding: 0px;
|
108
|
+
line-height: 1.7em;
|
109
|
+
}
|
110
|
+
|
111
|
+
article ul li.sender{
|
112
|
+
font-size: 1.555em;
|
113
|
+
font-weight: bold;
|
114
|
+
}
|
115
|
+
|
116
|
+
article.sending{
|
117
|
+
text-align: right;
|
118
|
+
}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def head
|
122
|
+
"<meta charset='utf-8'>
|
123
|
+
<title>Texts</title>
|
124
|
+
<meta name='description' content=''>
|
125
|
+
<meta name='author' content='Nosy - pdud - Phil Dudley - iPhone Message (SMS/ iMessage) Exporter'>
|
126
|
+
<meta name='viewport' content='width=device-width, user-scalable=no'>
|
127
|
+
<!-- IE Fix for HTML5 Tags -->
|
128
|
+
<!--[if lt IE 9]>
|
129
|
+
<script src='http://html5shiv.googlecode.com/svn/trunk/html5.js'></script>
|
130
|
+
<![endif]-->"
|
131
|
+
end
|
132
|
+
|
133
|
+
def html_text (f, text)
|
134
|
+
f.puts "<p>#{text.message}</p>"
|
135
|
+
f.puts "<ul>"
|
136
|
+
sender_html(f, text)
|
137
|
+
f.puts "<li>#{Time.at(text.date).strftime('%A, %B %e, %Y at %l:%M%P')}</li>"
|
138
|
+
end
|
139
|
+
|
140
|
+
def sender_html(f, text)
|
141
|
+
if text.sender == "me"
|
142
|
+
f.puts "<li class='sender'>#{text.sender}</li>"
|
143
|
+
f.puts "<li>to #{text.receiver} via #{imessage_or_sms(f, text)}</li>"
|
144
|
+
else
|
145
|
+
f.puts "<li class='sender'>#{text.sender}</li>"
|
146
|
+
f.puts "<li>to #{text.receiver} via #{imessage_or_sms(f, text)}</li>"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def imessage_or_sms(f, text)
|
151
|
+
if text.imessage
|
152
|
+
"iMessage"
|
153
|
+
else
|
154
|
+
"SMS"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
|
data/nosy.gemspec
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = 'nosy'
|
3
|
-
gem.version = '0.0.
|
4
|
-
gem.date = '2012-01-
|
5
|
-
gem.summary = "Output, backup, and read all your iPhone text messages"
|
6
|
-
gem.description = "Nosy fetches, parses and searches the iPhone's SMS database that is created on your machine each time you make a backup."
|
3
|
+
gem.version = '0.0.5'
|
4
|
+
gem.date = '2012-01-08'
|
5
|
+
gem.summary = "Output, backup, search, and read all your iPhone text messages"
|
6
|
+
gem.description = "Nosy fetches, parses and searches the iPhone's SMS database that is created on your machine each time you make a backup. It can export to HTML, CSV, or JSON."
|
7
7
|
gem.authors = ["Philip Dudley"]
|
8
8
|
gem.homepage = "https://github.com/pdud/Nosy"
|
9
9
|
gem.email = 'pdudley89@gmail.com'
|
10
10
|
gem.files = `git ls-files`.split("\n")
|
11
11
|
gem.add_dependency("sqlite3", "~> 1.3.4")
|
12
|
+
gem.add_dependency("json", "~> 1.6.4")
|
12
13
|
gem.add_development_dependency("rspec", "~> 2.6.0")
|
13
|
-
|
14
|
+
gem.add_development_dependency("capybara", "~> 1.1.2")
|
15
|
+
gem.executables << 'nosy'
|
16
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'nosy'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Nosy::Output, "#to_json( texts )" do
|
5
|
+
|
6
|
+
let(:texts) { Nosy.parse(File.join('spec', 'support', 'db', 'texts.sqlite'))}
|
7
|
+
|
8
|
+
context "#to_html" do
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@response = subject.to_html( texts )
|
12
|
+
visit(@response)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return the location to the created file" do
|
16
|
+
@response.should == "#{Dir.pwd}/iphone-texts.html"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should create an html document with the correct texts messages" do
|
20
|
+
page.all('article')[0].should have_content texts[0].message
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should create an html document with the correct sender" do
|
24
|
+
page.all('article ul li.sender')[0].should have_content texts[0].sender
|
25
|
+
page.all('article ul li.sender')[1].should have_content texts[1].sender
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should create an html document with the correct receiver" do
|
29
|
+
page.all('article')[0].find('li')[1].should have_content texts[0].receiver
|
30
|
+
page.all('article')[0].find('li')[1].should have_content texts[1].receiver
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should create an html document with the imessage indicator" do
|
34
|
+
page.all('article')[0].find('li')[1].should have_content "SMS"
|
35
|
+
page.all('article')[3].find('li')[1].should have_content "iMessage"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should create an html document with an easy to understand date" do
|
39
|
+
page.all('article')[0].should have_content "Thursday, May 6, 2010 at 3:58pm"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should include every text" do
|
43
|
+
page.all('article').length.should == texts.length
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
context "#to_json" do
|
49
|
+
|
50
|
+
let(:json_texts_output) { JSON.parse( subject.to_json( texts ) ) }
|
51
|
+
|
52
|
+
describe "Output" do
|
53
|
+
|
54
|
+
it "should return a parsable json document" do
|
55
|
+
json_texts_output['1'].should == {"date"=>1273176415, "sender"=>"+1234567890", "receiver"=>"me", "message"=>"Okie doke, i just have my fake final at 6 to do", "imessage"=>false}
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should include every text" do
|
59
|
+
json_texts_output.length.should == texts.length
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should have a parsable date field" do
|
63
|
+
json_texts_output['1']['date'].should == 1273176415
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should have a parsable sender field" do
|
67
|
+
json_texts_output['1']['sender'].should == "+1234567890"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should have a parsable receiver field" do
|
71
|
+
json_texts_output['1']['receiver'].should == "me"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should have a parsable message field" do
|
75
|
+
json_texts_output['1']['message'].should == "Okie doke, i just have my fake final at 6 to do"
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should have a parsable imessage field" do
|
79
|
+
json_texts_output['1']['imessage'].should == false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "Output to file" do
|
84
|
+
|
85
|
+
before(:each) do
|
86
|
+
@response = subject.to_json( texts, true )
|
87
|
+
file = File.open("iphone-texts.json")
|
88
|
+
@json_texts_file = JSON.parse( file.gets )
|
89
|
+
end
|
90
|
+
|
91
|
+
after(:each) { File.delete("iphone-texts.json") }
|
92
|
+
|
93
|
+
it "should return the location to the created file" do
|
94
|
+
@response.should == "#{Dir.pwd}/iphone-texts.json"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should create a parsable json file" do
|
98
|
+
@json_texts_file['1'].should == {"date"=>1273176415, "sender"=>"+1234567890", "receiver"=>"me", "message"=>"Okie doke, i just have my fake final at 6 to do", "imessage"=>false}
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should have the same contents as the regular output" do
|
102
|
+
@json_texts_file.should == json_texts_output
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "#to_csv" do
|
108
|
+
|
109
|
+
let(:csv_texts_output) { CSV.parse( subject.to_csv( texts ) )}
|
110
|
+
|
111
|
+
describe "Output to file" do
|
112
|
+
|
113
|
+
before(:each) do
|
114
|
+
@response = subject.to_csv( texts, "file" )
|
115
|
+
@csv = CSV.read( "iphone-texts.csv", { :headers => true })
|
116
|
+
end
|
117
|
+
|
118
|
+
after(:each) { File.delete("iphone-texts.csv") }
|
119
|
+
|
120
|
+
it "should return the location to the created file" do
|
121
|
+
@response.should == "#{Dir.pwd}/iphone-texts.csv"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should create a csv file" do
|
125
|
+
@csv[0][0].should == 1.to_s
|
126
|
+
@csv[0][1].should == texts[0].date.to_s
|
127
|
+
@csv[0][2].should == texts[0].sender
|
128
|
+
@csv[0][3].should == texts[0].receiver
|
129
|
+
@csv[0][4].should == texts[0].message
|
130
|
+
@csv[0][5].should == texts[0].imessage.to_s
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should include every text" do
|
134
|
+
@csv.length.should == texts.length
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
data/spec/nosy_spec.rb
CHANGED
@@ -4,6 +4,7 @@ describe Nosy do
|
|
4
4
|
|
5
5
|
let(:iphone_database) { File.join('spec', 'support', 'db', 'texts.sqlite') }
|
6
6
|
let(:texts) { subject.new(iphone_database) }
|
7
|
+
let(:parsed_texts) { Nosy.parse(File.join('spec', 'support', 'db', 'texts.sqlite'))}
|
7
8
|
|
8
9
|
describe "#hunt" do
|
9
10
|
|
@@ -29,6 +30,30 @@ describe Nosy do
|
|
29
30
|
|
30
31
|
end
|
31
32
|
|
33
|
+
describe "#hunt_parse_and_output( output_type, to_file)" do
|
34
|
+
|
35
|
+
it "should by default get the database, parse it, and output it as an html file" do
|
36
|
+
Nosy.hunt_parse_and_output.should == Nosy::Output.new.to_html(Nosy::Parser.new.parse(Nosy::Hunter.new.hunt))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should get the database, parse it, and output it as json string" do
|
40
|
+
Nosy.hunt_parse_and_output("json", false).should == Nosy::Output.new.to_json(Nosy::Parser.new.parse(Nosy::Hunter.new.hunt), false)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should get the database, parse it, and output it as json file" do
|
44
|
+
Nosy.hunt_parse_and_output("json", true).should == Nosy::Output.new.to_json(Nosy::Parser.new.parse(Nosy::Hunter.new.hunt), true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should get the database, parse it, and output it as an html file" do
|
48
|
+
Nosy.hunt_parse_and_output("html").should == Nosy::Output.new.to_html(Nosy::Parser.new.parse(Nosy::Hunter.new.hunt))
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should get the database, parse it, and output it as a csv file" do
|
52
|
+
Nosy.hunt_parse_and_output("csv").should == Nosy::Output.new.to_csv(Nosy::Parser.new.parse(Nosy::Hunter.new.hunt))
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
32
57
|
describe "#parse" do
|
33
58
|
|
34
59
|
it "should return the same results as a parse" do
|
@@ -45,4 +70,29 @@ describe Nosy do
|
|
45
70
|
|
46
71
|
end
|
47
72
|
|
73
|
+
describe "#output( output_type, to_file)" do
|
74
|
+
|
75
|
+
|
76
|
+
it "should by default output it as an html file" do
|
77
|
+
Nosy.output(parsed_texts).should == Nosy::Output.new.to_html(parsed_texts)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should output it as json string" do
|
81
|
+
Nosy.output(parsed_texts, "json", false).should == Nosy::Output.new.to_json(parsed_texts, false)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should output it as json file" do
|
85
|
+
Nosy.output(parsed_texts, "json", true).should == Nosy::Output.new.to_json(parsed_texts, true)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should output it as an html file" do
|
89
|
+
Nosy.output(parsed_texts, "html").should == Nosy::Output.new.to_html(parsed_texts)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should output it as a csv file" do
|
93
|
+
Nosy.output(parsed_texts, "csv").should == Nosy::Output.new.to_csv(parsed_texts)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
48
98
|
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nosy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-01-
|
12
|
+
date: 2012-01-08 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sqlite3
|
16
|
-
requirement: &
|
16
|
+
requirement: &70361786273640 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,21 @@ dependencies:
|
|
21
21
|
version: 1.3.4
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70361786273640
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: json
|
27
|
+
requirement: &70361786272420 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.6.4
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70361786272420
|
25
36
|
- !ruby/object:Gem::Dependency
|
26
37
|
name: rspec
|
27
|
-
requirement: &
|
38
|
+
requirement: &70361786271660 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
40
|
requirements:
|
30
41
|
- - ~>
|
@@ -32,34 +43,51 @@ dependencies:
|
|
32
43
|
version: 2.6.0
|
33
44
|
type: :development
|
34
45
|
prerelease: false
|
35
|
-
version_requirements: *
|
46
|
+
version_requirements: *70361786271660
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: capybara
|
49
|
+
requirement: &70361786270900 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.2
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70361786270900
|
36
58
|
description: Nosy fetches, parses and searches the iPhone's SMS database that is created
|
37
|
-
on your machine each time you make a backup.
|
59
|
+
on your machine each time you make a backup. It can export to HTML, CSV, or JSON.
|
38
60
|
email: pdudley89@gmail.com
|
39
|
-
executables:
|
61
|
+
executables:
|
62
|
+
- nosy
|
40
63
|
extensions: []
|
41
64
|
extra_rdoc_files: []
|
42
65
|
files:
|
43
66
|
- .gitignore
|
44
67
|
- .rspec
|
45
68
|
- README.md
|
69
|
+
- bin/nosy
|
46
70
|
- lib/.DS_Store
|
47
71
|
- lib/nosy.rb
|
48
72
|
- lib/nosy/hunter.rb
|
73
|
+
- lib/nosy/output.rb
|
74
|
+
- lib/nosy/output/html_helpers.rb
|
49
75
|
- lib/nosy/parser.rb
|
50
76
|
- lib/nosy/parser/imessage.rb
|
51
77
|
- lib/nosy/parser/message_support.rb
|
52
78
|
- lib/nosy/parser/parse_checks.rb
|
53
79
|
- lib/nosy/parser/smsmessage.rb
|
54
80
|
- lib/nosy/searcher.rb
|
55
|
-
- nosy-0.0.
|
81
|
+
- nosy-0.0.5.gem
|
56
82
|
- nosy.gemspec
|
57
83
|
- spec/.DS_Store
|
58
84
|
- spec/nosy/.DS_Store
|
59
85
|
- spec/nosy/hunter_spec.rb
|
86
|
+
- spec/nosy/output_spec.rb
|
60
87
|
- spec/nosy/parser_spec.rb
|
61
88
|
- spec/nosy/searcher_spec.rb
|
62
89
|
- spec/nosy_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
63
91
|
- spec/support/.DS_Store
|
64
92
|
- spec/support/db/.DS_Store
|
65
93
|
- spec/support/db/empty_iphone_database.sqlite
|
@@ -92,5 +120,5 @@ rubyforge_project:
|
|
92
120
|
rubygems_version: 1.8.10
|
93
121
|
signing_key:
|
94
122
|
specification_version: 3
|
95
|
-
summary: Output, backup, and read all your iPhone text messages
|
123
|
+
summary: Output, backup, search, and read all your iPhone text messages
|
96
124
|
test_files: []
|