runoff 1.0.1 → 2.0.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/.gitignore +29 -15
- data/README.md +9 -3
- data/bin/runoff +26 -53
- data/lib/runoff/adapters/adapter.rb +31 -0
- data/lib/runoff/adapters/json_adapter.rb +88 -0
- data/lib/runoff/adapters/txt_adapter.rb +69 -0
- data/lib/runoff/chat.rb +38 -0
- data/lib/runoff/commandline/all.rb +53 -0
- data/lib/runoff/commandline/command.rb +34 -0
- data/lib/runoff/commandline/none.rb +45 -0
- data/lib/runoff/commandline/some.rb +84 -0
- data/lib/runoff/file_writer.rb +37 -58
- data/lib/runoff/location.rb +23 -20
- data/lib/runoff/version.rb +1 -1
- data/lib/runoff.rb +12 -4
- data/runoff.gemspec +0 -1
- data/test/command_all_test.rb +90 -0
- data/test/command_some_test.rb +49 -0
- data/test/data/custom_location/test_main.db +0 -0
- data/test/data/test_main.db +0 -0
- data/test/location_test.rb +78 -0
- metadata +21 -25
- data/lib/runoff/commands/all.rb +0 -22
- data/lib/runoff/commands/command.rb +0 -19
- data/lib/runoff/commands/some.rb +0 -38
- data/lib/runoff/skype_data_format.rb +0 -128
- data/test/skype_data_format_test.rb +0 -58
- data/test/test_db.sqlite +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4aeef27e77018f295faf0e6f43909ddf9516f71
|
4
|
+
data.tar.gz: 13d13befb22b12e797673c36448a44dfed2467e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a739d9f63e5176c2563de12886bf4bfcddaf955446e55a6a714d734710e3a3743218569ca6fd78c25677f598eb2fed56b04fd6ccf8e3d04632fa78d9bf2d835
|
7
|
+
data.tar.gz: d58f520e774251942f003a61adcb6576364db95d0656b39584157fe7ea37eaae6a4338f4f5ebf896f15a690c195af89878d76bb160f44d4a831c4f6052729511
|
data/.gitignore
CHANGED
@@ -1,18 +1,32 @@
|
|
1
1
|
*.gem
|
2
2
|
*.rbc
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Documentation cache and generated files:
|
13
|
+
/.yardoc/
|
14
|
+
/_yardoc/
|
15
|
+
/doc/
|
16
|
+
/rdoc/
|
17
|
+
|
18
|
+
## Environment normalisation:
|
19
|
+
/.bundle/
|
20
|
+
/lib/bundler/man/
|
21
|
+
|
22
|
+
# for a library or gem, you might want to ignore these files since the code is
|
23
|
+
# intended to run in multiple environments; otherwise, check them in:
|
6
24
|
Gemfile.lock
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
17
|
-
tmp
|
18
|
-
.DS_Store
|
25
|
+
.ruby-version
|
26
|
+
.ruby-gemset
|
27
|
+
|
28
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
29
|
+
.rvmrc
|
30
|
+
|
31
|
+
# additional stuff
|
32
|
+
.DS_Store
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# runoff
|
2
2
|
## About
|
3
3
|
|
4
|
-
A few years ago I had enough of loosing my Skype chat history every time I reinstalled the operating system, so I decided to write a small application that could export it as plain text files. The application
|
4
|
+
A few years ago I had enough of loosing my Skype chat history every time I reinstalled the operating system, so I decided to write a small application that could export it as plain text files. The application was called SDBR and it was an open source project that I do not maintain anymore. Why? I could say that I lost my interest in it, but the real reason probably is the implementation.
|
5
5
|
|
6
|
-
SDBR
|
6
|
+
SDBR was written in C# using WPF, therefore it ran only on Windows. Moreover, it was a GUI application. Yeah, that's a problem, because you don't need the GUI for this kind of functionality. runoff is a command-line tool, that automates the process of exporting your chat history.
|
7
7
|
|
8
8
|
## Install
|
9
9
|
|
@@ -26,12 +26,18 @@ To export specific chats.
|
|
26
26
|
|
27
27
|
runoff some skype_username
|
28
28
|
|
29
|
-
If you don't want to put files into an archive, use `--no-archive` option
|
29
|
+
If you don't want to put files into an archive, use `--no-archive` option.
|
30
30
|
|
31
31
|
runoff all skype_username --no-archive
|
32
32
|
|
33
33
|
runoff some skype_username --no-archive
|
34
34
|
|
35
|
+
Sometimes you might want to use the exported data in a different app, therefore runoff has an option to export in JSON instead of TXT. You just need to specify an adapter using `-A` option.
|
36
|
+
|
37
|
+
runoff all skype_username -A json
|
38
|
+
|
39
|
+
The resulting JSON file contains an array of objects with 3 keys: `date`, `user` and `message`. Each object represents a single chat record.
|
40
|
+
|
35
41
|
## What else?
|
36
42
|
|
37
43
|
Things to do in the future versions:
|
data/bin/runoff
CHANGED
@@ -1,58 +1,31 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
|
-
|
5
|
-
require 'commander/import'
|
6
|
-
require 'runoff'
|
7
3
|
require 'colorize'
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
command :some do |c|
|
39
|
-
c.syntax = 'runoff some [SKYPE_USERNAME] [OPTIONS]'
|
40
|
-
c.description = "Export only some chats' history"
|
41
|
-
c.option '-f', '--from FILE', 'Location of the main.db file'
|
42
|
-
c.option '-d', '--destination DIR', 'Location for the exoprted files'
|
43
|
-
c.option '--[no-]archive', 'Indicates whether to create an archive'
|
44
|
-
|
45
|
-
c.action do |args, options|
|
46
|
-
begin
|
47
|
-
puts "Exporting...".colorize :green
|
48
|
-
Runoff::Commands::Some.process args, options
|
49
|
-
puts "Export finished.".colorize :green
|
50
|
-
rescue ArgumentError => e
|
51
|
-
puts e.message.colorize :red
|
52
|
-
rescue Sequel::DatabaseError
|
53
|
-
puts "Error: To use runoff you must make sure that the Skype is not running".colorize :red
|
54
|
-
rescue StandardError => e
|
55
|
-
puts e.message.colorize :red
|
56
|
-
end
|
57
|
-
end
|
5
|
+
require_relative '../lib/runoff/commandline/none'
|
6
|
+
require_relative '../lib/runoff/commandline/all'
|
7
|
+
require_relative '../lib/runoff/commandline/some'
|
8
|
+
|
9
|
+
options = { archive: true, adapter: 'TxtAdapter' }
|
10
|
+
available_commands = {
|
11
|
+
'_none' => Runoff::Commandline::None.new(options),
|
12
|
+
'all' => Runoff::Commandline::All.new(options),
|
13
|
+
'some' => Runoff::Commandline::Some.new(options)
|
14
|
+
}
|
15
|
+
|
16
|
+
available_commands['_none'].parser.order!
|
17
|
+
command = available_commands[ARGV.shift]
|
18
|
+
|
19
|
+
if command
|
20
|
+
command.parser.order!
|
21
|
+
command.parser.parse!
|
22
|
+
|
23
|
+
#begin
|
24
|
+
command.execute ARGV
|
25
|
+
#rescue StandardError => e
|
26
|
+
# warn e.message.colorize :red
|
27
|
+
# puts 'Terminated.'.colorize :yellow
|
28
|
+
#end
|
29
|
+
else
|
30
|
+
puts available_commands['_none'].parser.help
|
58
31
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Runoff
|
2
|
+
module Adapters
|
3
|
+
class Adapter
|
4
|
+
protected
|
5
|
+
|
6
|
+
# Internal: Converts a Unix timestamp to a datetime string.
|
7
|
+
#
|
8
|
+
# timestamp - An integer with a Unix timestamp value.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# format_timestamp 1397852412
|
13
|
+
# # => "2014-18-04 20:20:12"
|
14
|
+
#
|
15
|
+
# Returns a datetime string in a format of YYY-DD-MM HH:MM::SS
|
16
|
+
def format_timestamp(timestamp)
|
17
|
+
Time.at(timestamp).strftime '%Y-%m-%d %H:%M:%S'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Internal: Skip.
|
21
|
+
def format_from_dispname(dispname)
|
22
|
+
dispname
|
23
|
+
end
|
24
|
+
|
25
|
+
# Internal: Skip.
|
26
|
+
def format_body_xml(xml_content)
|
27
|
+
xml_content
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Runoff
|
4
|
+
module Adapters
|
5
|
+
class JsonAdapter < Adapter
|
6
|
+
# Public: A format String used to build a single entry.
|
7
|
+
ENTRY_FORMAT = '{ "date": "%s", "user": "%s", "message": %s }'
|
8
|
+
|
9
|
+
# Public: Builds a single entry.
|
10
|
+
#
|
11
|
+
# row - An Array containing a single row of data from the database.
|
12
|
+
#
|
13
|
+
# Examples
|
14
|
+
#
|
15
|
+
# build_entry { chatname: "#first_user/$second_user;d3d86c6b0e3b8320" ... }
|
16
|
+
# # => "{ "date": "2014-04-18 20:20:12", "user": "first_user", "message": "This is a text" }"
|
17
|
+
def build_entry(row)
|
18
|
+
formated_data = []
|
19
|
+
|
20
|
+
# NOTE: The first column in the array is used for the grouping by id and
|
21
|
+
# the second is used for the filename.
|
22
|
+
Runoff::COLUMNS[2..-1].each do |column|
|
23
|
+
formated_data << send("format_#{column}", row[column])
|
24
|
+
end
|
25
|
+
|
26
|
+
ENTRY_FORMAT % formated_data
|
27
|
+
end
|
28
|
+
|
29
|
+
# Public: returns a file name.
|
30
|
+
#
|
31
|
+
# chatname - A String with a Skype chatname
|
32
|
+
#
|
33
|
+
# Examples
|
34
|
+
#
|
35
|
+
# get_file_name "#first_user/$second_user;d3d86c6b0e3b8320"
|
36
|
+
# # => first_user_second_user.json
|
37
|
+
#
|
38
|
+
# Returns a valid file name.
|
39
|
+
def get_file_name(chatname)
|
40
|
+
parse_chatname(chatname) + '.json'
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: Parses a chatname into a human readable name.
|
44
|
+
#
|
45
|
+
# raw_chatname - A String with a Skype chatname.
|
46
|
+
#
|
47
|
+
# Examples
|
48
|
+
#
|
49
|
+
# parse_chatname "#first_user/$second_user;d3d86c6b0e3b8320"
|
50
|
+
# # => first_user_second_user
|
51
|
+
#
|
52
|
+
# Returns a valid name.
|
53
|
+
def parse_chatname(raw_chatname)
|
54
|
+
pattern = /^#(.*)\/\$(.*);.*$/
|
55
|
+
parts = raw_chatname.match(pattern).captures
|
56
|
+
|
57
|
+
parts.reject(&:empty?).join('_')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Public: Formats the provided data buffer so that it could be writter to
|
61
|
+
# a JSON file.
|
62
|
+
#
|
63
|
+
# buffer - An Array containing all the chat entries.
|
64
|
+
#
|
65
|
+
# Returns a String
|
66
|
+
def format_file_content(buffer)
|
67
|
+
content = buffer.join(",\n")
|
68
|
+
|
69
|
+
"[#{content}]"
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
# Internal: Escapes the message body so that it could be used in a JSON string
|
75
|
+
#
|
76
|
+
# xml_content - A String containing the chat message
|
77
|
+
#
|
78
|
+
# Examples
|
79
|
+
#
|
80
|
+
# format_body_xml 'foo' # => "\"foo\""
|
81
|
+
#
|
82
|
+
# Returns a String
|
83
|
+
def format_body_xml(xml_content)
|
84
|
+
JSON.generate(xml_content, quirks_mode: true)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Runoff
|
2
|
+
module Adapters
|
3
|
+
class TxtAdapter < Adapter
|
4
|
+
# Public: A format String used to build a single entry.
|
5
|
+
ENTRY_FORMAT = "[%s] %s: %s"
|
6
|
+
|
7
|
+
# Public: Builds a single entry.
|
8
|
+
#
|
9
|
+
# row - An Array containing a single row of data from the database.
|
10
|
+
#
|
11
|
+
# Examples
|
12
|
+
#
|
13
|
+
# build_entry { chatname: "#first_user/$second_user;d3d86c6b0e3b8320" ... }
|
14
|
+
# # => "[2014-04-18 20:20:12] first_user: This is a text"
|
15
|
+
def build_entry(row)
|
16
|
+
formated_data = []
|
17
|
+
|
18
|
+
# NOTE: The first column in the array is used for the grouping by id and
|
19
|
+
# the second is used for the filename.
|
20
|
+
Runoff::COLUMNS[2..-1].each do |column|
|
21
|
+
formated_data << send("format_#{column}", row[column])
|
22
|
+
end
|
23
|
+
|
24
|
+
ENTRY_FORMAT % formated_data
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: returns a file name.
|
28
|
+
#
|
29
|
+
# chatname - A String with a Skype chatname
|
30
|
+
#
|
31
|
+
# Examples
|
32
|
+
#
|
33
|
+
# get_file_name "#first_user/$second_user;d3d86c6b0e3b8320"
|
34
|
+
# # => first_user_second_user.txt
|
35
|
+
#
|
36
|
+
# Returns a valid file name.
|
37
|
+
def get_file_name(chatname)
|
38
|
+
parse_chatname(chatname) + '.txt'
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Parses a chatname into a human readable name.
|
42
|
+
#
|
43
|
+
# raw_chatname - A String with a Skype chatname.
|
44
|
+
#
|
45
|
+
# Examples
|
46
|
+
#
|
47
|
+
# parse_chatname "#first_user/$second_user;d3d86c6b0e3b8320"
|
48
|
+
# # => first_user_second_user
|
49
|
+
#
|
50
|
+
# Returns a valid name.
|
51
|
+
def parse_chatname(raw_chatname)
|
52
|
+
pattern = /^#(.*)\/\$(.*);.*$/
|
53
|
+
parts = raw_chatname.match(pattern).captures
|
54
|
+
|
55
|
+
parts.reject(&:empty?).join('_')
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Formats the provided data buffer so that it could be writter to
|
59
|
+
# a text file.
|
60
|
+
#
|
61
|
+
# buffer - An Array containing all the chat entries.
|
62
|
+
#
|
63
|
+
# Returns a String
|
64
|
+
def format_file_content(buffer)
|
65
|
+
buffer.join("\n")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/runoff/chat.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module Runoff
|
5
|
+
# Public: Reads data from the SQLite database used by Skype/
|
6
|
+
class Chat
|
7
|
+
|
8
|
+
# Public: Initializes a Chat object.
|
9
|
+
#
|
10
|
+
# db_location - A String with a path to the database file.
|
11
|
+
def initialize(db_location, options)
|
12
|
+
@messages = Sequel.sqlite(db_location)[Runoff::TABLE]
|
13
|
+
@adapter = Object.const_get("Runoff::Adapters::#{options[:adapter]}").new
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Returns a list of all the records in the databse.
|
17
|
+
def get_messages
|
18
|
+
@messages.select(*Runoff::COLUMNS).all.sort_by do |row|
|
19
|
+
[row[Runoff::COLUMNS[0]], row[Runoff::COLUMNS[2]]]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: Creates a collection with all chats available for export.
|
24
|
+
#
|
25
|
+
# Returns a Set with hashes e.g. [{ id: 12, name: "chatname" }, ... ]
|
26
|
+
def get_chatname_options
|
27
|
+
options = Set.new
|
28
|
+
|
29
|
+
@messages.select(*Runoff::COLUMNS[0..1]).each do |row|
|
30
|
+
readable_name = @adapter.parse_chatname row[Runoff::COLUMNS[1]]
|
31
|
+
|
32
|
+
options << { id: row[Runoff::COLUMNS[0]], name: readable_name }
|
33
|
+
end
|
34
|
+
|
35
|
+
options
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require_relative 'command'
|
2
|
+
|
3
|
+
module Runoff
|
4
|
+
# Public: Command classes used by the executable.
|
5
|
+
module Commandline
|
6
|
+
# Public: A command class that is used to export all chat history.
|
7
|
+
#
|
8
|
+
# Examples
|
9
|
+
#
|
10
|
+
# command = All.new { archive: true }
|
11
|
+
# command.execute [ 'skype_username' ]
|
12
|
+
class All < Command
|
13
|
+
# Public: initialize a new All command object.
|
14
|
+
#
|
15
|
+
# options - A Hash of commandline options (default { archive: true, adapter: 'TxtAdapter' }).
|
16
|
+
def initialize(options = {})
|
17
|
+
@options = options
|
18
|
+
@parser = OptionParser.new do |opts|
|
19
|
+
opts.banner = 'Exports all chats: runoff all [SKYPE_USERNAME] [OPTIONS]'
|
20
|
+
opts.on '-h', '--help', 'Displays help' do
|
21
|
+
puts opts
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on '-f', '--from PATH', 'Specifies the location of the database file (main.db)' do |path|
|
26
|
+
@options[:from] = path
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on '-d', '--destination PATH', 'Changes the default path for the exported files' do |path|
|
30
|
+
@options[:destination] = path
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on '-a', '--[no-]archive', 'Toggles archiving feature' do |enable|
|
34
|
+
@options[:archive] = enable
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on '-A', '--adapter [NAME]', 'Uses a specific file type adapter' do |adapter|
|
38
|
+
@options[:adapter] = adapter.capitalize + 'Adapter'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: executes the command.
|
44
|
+
#
|
45
|
+
# args - An Array of commandline arguments.
|
46
|
+
def execute(args)
|
47
|
+
super args do |chat, file_writer|
|
48
|
+
file_writer.write chat.get_messages
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
require_relative '../../runoff'
|
5
|
+
|
6
|
+
module Runoff
|
7
|
+
# Public: Command classes used by the executable.
|
8
|
+
module Commandline
|
9
|
+
# Public: A base class for all runoff commands except None.
|
10
|
+
#
|
11
|
+
# Should be used only by inheriting.
|
12
|
+
class Command
|
13
|
+
# Public: Returns an OptionParser object
|
14
|
+
attr_reader :parser
|
15
|
+
|
16
|
+
# Public: executes the command.
|
17
|
+
#
|
18
|
+
# args - An Array of commandline arguments.
|
19
|
+
def execute(args)
|
20
|
+
puts 'Exporting...'.colorize :green
|
21
|
+
|
22
|
+
db_location = Location.get_database_path args, @options
|
23
|
+
chat = Chat.new db_location, @options
|
24
|
+
file_writer = FileWriter.new @options
|
25
|
+
|
26
|
+
yield chat, file_writer if block_given?
|
27
|
+
|
28
|
+
file_writer.archive if @options[:archive]
|
29
|
+
|
30
|
+
puts 'Finished.'.colorize :green
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require_relative '../../runoff.rb'
|
3
|
+
|
4
|
+
module Runoff
|
5
|
+
# Public: Command classes used by the executable.
|
6
|
+
module Commandline
|
7
|
+
# Public: The default class that is used when the executable is called
|
8
|
+
# without any commands.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# command = None.new { archive: false }
|
13
|
+
class None
|
14
|
+
# Public: Returns an OptionParser object
|
15
|
+
attr_reader :parser
|
16
|
+
|
17
|
+
# Public: initialize a new None command object.
|
18
|
+
#
|
19
|
+
# options - A Hash of commandline options (default { archive: false }).
|
20
|
+
def initialize(options = {})
|
21
|
+
@option = options
|
22
|
+
@parser = OptionParser.new do |opts|
|
23
|
+
opts.banner = <<END
|
24
|
+
runoff - a simple application to create Skype backups
|
25
|
+
|
26
|
+
Usage:
|
27
|
+
|
28
|
+
runoff <COMMAND> [SKYPE_USERNAME] [OPTIONS]
|
29
|
+
|
30
|
+
END
|
31
|
+
|
32
|
+
opts.on '-h', '--help', 'Displays help' do
|
33
|
+
puts opts
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on '-v', '--version', 'Displays a version number' do
|
38
|
+
puts Runoff::VERSION
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative 'command'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
module Runoff
|
5
|
+
# Public: Command classes used by the executable.
|
6
|
+
module Commandline
|
7
|
+
# Public: A command class that is used to export specified chat history.
|
8
|
+
#
|
9
|
+
# Examples
|
10
|
+
#
|
11
|
+
# command = Some.new { archive: true }
|
12
|
+
# command.execute [ 'skype_username' ]
|
13
|
+
class Some < Command
|
14
|
+
# Public: initialize a new All command object.
|
15
|
+
#
|
16
|
+
# options - A Hash of commandline options (default { archive: true }).
|
17
|
+
def initialize(options = {})
|
18
|
+
@options = options
|
19
|
+
@parser = OptionParser.new do |opts|
|
20
|
+
opts.banner = 'Exports specified chats: runoff some [SKYPE_USERNAME] [OPTIONS]'
|
21
|
+
opts.on '-h', '--help', 'Displays help' do
|
22
|
+
puts opts
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on '-f', '--from PATH', 'Specifies the location of the database file (main.db)' do |path|
|
27
|
+
@options[:from] = path
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on '-d', '--destination PATH', 'Changes the default path for the exported files' do |path|
|
31
|
+
@options[:destination] = path
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.on '-a', '--[no-]archive', 'Toggles archiving feature' do |enable|
|
35
|
+
@options[:archive] = enable
|
36
|
+
end
|
37
|
+
|
38
|
+
opts.on '-A', '--adapter [NAME]', 'Uses a specific file type adapter' do |adapter|
|
39
|
+
@options[:adapter] = adapter.capitalize + 'Adapter'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Public: executes the command.
|
45
|
+
#
|
46
|
+
# args - An Array of commandline arguments.
|
47
|
+
def execute(args)
|
48
|
+
super args do |chat, file_writer|
|
49
|
+
ids = prompt_for_chatnames chat
|
50
|
+
messages = chat.get_messages
|
51
|
+
|
52
|
+
selected_messages = messages.keep_if { |m| ids.include? m[Runoff::COLUMNS[0]] }
|
53
|
+
|
54
|
+
file_writer.write selected_messages
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Public: Asks user to specify, which chats to export.
|
59
|
+
#
|
60
|
+
# chat - A Chat object.
|
61
|
+
#
|
62
|
+
# Examples
|
63
|
+
#
|
64
|
+
# get_requested_chatnames Chat.new('/path/to/main.db')
|
65
|
+
# # => [120, 86, 201]
|
66
|
+
#
|
67
|
+
# Returns an Array of conversation ids.
|
68
|
+
def prompt_for_chatnames(chat)
|
69
|
+
puts 'Specify numbers of the chats that you want to export (e.g., 201, 86, 120)'
|
70
|
+
puts
|
71
|
+
|
72
|
+
chat.get_chatname_options.each do |opt|
|
73
|
+
puts "[#{opt[:id]}] #{opt[:name]}"
|
74
|
+
end
|
75
|
+
|
76
|
+
puts
|
77
|
+
print "Numbers: "
|
78
|
+
options = STDIN.gets # NOTE: For some reason just gets throws an error here.
|
79
|
+
|
80
|
+
options.split(',').map(&:to_i)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|