pidgin2adium 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/README.rdoc +26 -2
- data/bin/pidgin2adium +30 -6
- data/lib/pidgin2adium.rb +18 -8
- data/lib/pidgin2adium/log_converter.rb +4 -0
- data/lib/pidgin2adium/log_file.rb +10 -9
- data/lib/pidgin2adium/log_parser.rb +26 -10
- metadata +3 -3
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 2.0.2 / 2009-12-18
|
2
|
+
* Much better documentation (more of it, and higher quality too!)
|
3
|
+
* Allow user-provided output dir at commandline
|
4
|
+
* Cleaner error messages
|
5
|
+
* require 'time' for Time.zone_offset (fixes bug)
|
6
|
+
* Gracefully handle lack of timezone info
|
7
|
+
* Gracefully handle nonexistent output dir
|
8
|
+
* Gracefully handle parsing errors
|
9
|
+
* Print error messages during *and* after batch converting so they're actually seen
|
10
|
+
|
1
11
|
=== 2.0.1 / 2009-12-06
|
2
12
|
* Fix timestamps so they show up in Adium chat log viewer
|
3
13
|
|
data/README.rdoc
CHANGED
@@ -38,8 +38,9 @@ Or:
|
|
38
38
|
|
39
39
|
===Example (using library)
|
40
40
|
The library style allows you to parse a log file and get back a
|
41
|
-
LogFile instance for easy reading, manipulation, etc.
|
42
|
-
You can also create log files yourself using Pidgin2Adium.parse_and_generate.
|
41
|
+
LogFile[link:classes/Pidgin2Adium/LogFile.html] instance for easy reading, manipulation, etc.
|
42
|
+
You can also create log files yourself using Pidgin2Adium.parse_and_generate[link:classes/Pidgin2Adium.html#M000006].
|
43
|
+
For batch processing, use LogConverter[link:classes/Pidgin2Adium/LogConverter.html].
|
43
44
|
|
44
45
|
require 'pidgin2adium'
|
45
46
|
logfile = Pidgin2Adium.parse("/path/to/log/file.html", "gabe,gbw,gabeb-w")
|
@@ -64,12 +65,35 @@ You can also create log files yourself using Pidgin2Adium.parse_and_generate.
|
|
64
65
|
# Prints out the message in Adium log format
|
65
66
|
puts message.to_s
|
66
67
|
end
|
68
|
+
success = logfile.write_out()
|
69
|
+
# To overwrite file if it exists:
|
70
|
+
# logfile.write_out(overwrite = true)
|
71
|
+
# To specify your own output dir (default = Pidgin2Adium::ADIUM_LOG_DIR):
|
72
|
+
# logfile.write_out(false, output_dir = my_dir)
|
73
|
+
# Or combine them:
|
74
|
+
# logfile.write_out(true, my_dir)
|
75
|
+
if success == false
|
76
|
+
puts "An error occurred!"
|
77
|
+
elsif success == Pidgin2Adium::FILE_EXISTS
|
78
|
+
# Not returned if overwrite set to true
|
79
|
+
puts "File already exists."
|
80
|
+
else
|
81
|
+
puts "Successfully wrote out log file!"
|
82
|
+
puts "Path to output file: #{success}"
|
83
|
+
end
|
84
|
+
# This deletes search indexes to Adium re-indexes the new chat logs.
|
85
|
+
# Not automatically called after log_file.write_out()
|
86
|
+
# If you're converting >1 log, call it after converting all of them, since
|
87
|
+
# it takes up a tiny bit of processing power.
|
88
|
+
Pidgin2Adium.delete_search_indexes()
|
67
89
|
end
|
68
90
|
|
69
91
|
===Example 2 (using library)
|
70
92
|
If you want to output the logfile to an output dir instead of just parsing it, use Pidgin2Adium.parse_and_generate:
|
71
93
|
|
72
94
|
require 'pidgin2adium'
|
95
|
+
# Both options are optional; without :output_dir, writes to Adium log dir
|
96
|
+
# (which is usually what you want anyway).
|
73
97
|
opts = {:overwrite => true, :output_dir => "/my/output/dir"}
|
74
98
|
path_to_converted_log = Pidgin2Adium.parse_and_generate("/path/to/log/file.html", "gabe,gbw,gabeb-w", opts)
|
75
99
|
|
data/bin/pidgin2adium
CHANGED
@@ -15,21 +15,41 @@ automatically recognized.
|
|
15
15
|
require 'pidgin2adium/log_converter'
|
16
16
|
require 'optparse'
|
17
17
|
|
18
|
+
version = <<EOL
|
19
|
+
Pidgin2Adium, version #{Pidgin2Adium::VERSION}
|
20
|
+
Written by Gabe Berke-Williams (gbw@rubyforge.org)
|
21
|
+
EOL
|
22
|
+
|
18
23
|
options = {}
|
19
24
|
oparser = OptionParser.new do |opts|
|
20
25
|
opts.banner = "Usage: #{File.basename($0)} [options]"
|
21
|
-
opts.on('-i', '--in=IN_DIR', String, '
|
26
|
+
opts.on('-i', '--in=IN_DIR', String, 'Directory where pidgin logs are stored') do |i|
|
22
27
|
options[:in] = i
|
23
28
|
end
|
24
29
|
opts.on('-a alias1,alias2', "--aliases alias1,alias2",
|
25
|
-
"A comma-separated list of your alias(es)
|
26
|
-
which person in a chat
|
30
|
+
"A comma-separated list of your alias(es)",
|
31
|
+
"so this script knows which person in a chat",
|
32
|
+
"is you. Whitespace and case do not matter.") do |aliases|
|
27
33
|
options[:aliases] = aliases
|
28
34
|
end
|
29
|
-
opts.on('-
|
35
|
+
opts.on('-o', '--out [OUT_DIR]',
|
36
|
+
'The top-level directory under which to',
|
37
|
+
'store the logs (each in its own folder',
|
38
|
+
'by screen name).',
|
39
|
+
"Defaults to: #{Pidgin2Adium::ADIUM_LOG_DIR}") do |out|
|
40
|
+
options[:output_dir] = out
|
41
|
+
end
|
42
|
+
opts.on('-f', '--force', 'If this is set, then logs in the Adium log',
|
43
|
+
'folder that have the same name as converted',
|
44
|
+
'logs will be overwritten.') do |f|
|
30
45
|
options[:force] = f
|
31
46
|
end
|
47
|
+
opts.on("-v", "--version", "Show version information") do
|
48
|
+
puts version
|
49
|
+
exit
|
50
|
+
end
|
32
51
|
opts.on_tail("-h", "--help", "Show this message") do
|
52
|
+
puts version
|
33
53
|
puts opts
|
34
54
|
exit
|
35
55
|
end
|
@@ -65,8 +85,12 @@ if need_opts
|
|
65
85
|
exit 1
|
66
86
|
end
|
67
87
|
|
88
|
+
extra_opts = {:overwrite => options[:force]}
|
89
|
+
if options.has_key?(:output_dir)
|
90
|
+
extra_opts[:output_dir] = options[:output_dir]
|
91
|
+
end
|
92
|
+
|
68
93
|
log_converter = Pidgin2Adium::LogConverter.new(options[:in],
|
69
94
|
options[:aliases],
|
70
|
-
|
71
|
-
)
|
95
|
+
extra_opts)
|
72
96
|
log_converter.start
|
data/lib/pidgin2adium.rb
CHANGED
@@ -14,17 +14,22 @@ module Pidgin2Adium
|
|
14
14
|
ADIUM_LOG_DIR = File.expand_path('~/Library/Application Support/Adium 2.0/Users/Default/Logs/') << '/'
|
15
15
|
# These files/directories show up in Dir.entries()
|
16
16
|
BAD_DIRS = %w{. .. .DS_Store Thumbs.db .system}
|
17
|
-
VERSION = "2.0.
|
17
|
+
VERSION = "2.0.2"
|
18
|
+
# For displaying after we finish converting
|
19
|
+
@@oops_messages = []
|
20
|
+
@@error_messages = []
|
18
21
|
|
19
|
-
def log_msg(str) #:nodoc
|
22
|
+
def log_msg(str) #:nodoc:
|
20
23
|
puts str.to_s
|
21
24
|
end
|
22
25
|
|
23
|
-
def oops(str) #:nodoc
|
26
|
+
def oops(str) #:nodoc:
|
27
|
+
@@oops_messages << str
|
24
28
|
warn("Oops: #{str}")
|
25
29
|
end
|
26
30
|
|
27
|
-
def error(str) #:nodoc
|
31
|
+
def error(str) #:nodoc:
|
32
|
+
@@error_messages << str
|
28
33
|
warn("Error: #{str}")
|
29
34
|
end
|
30
35
|
|
@@ -43,7 +48,7 @@ module Pidgin2Adium
|
|
43
48
|
elsif(ext == "txt")
|
44
49
|
parser = TextLogParser.new(logfile_path, my_aliases)
|
45
50
|
else
|
46
|
-
error("logfile
|
51
|
+
error("Doing nothing, logfile is not a text or html file. Path: #{logfile_path}.")
|
47
52
|
return false
|
48
53
|
end
|
49
54
|
|
@@ -72,14 +77,19 @@ module Pidgin2Adium
|
|
72
77
|
|
73
78
|
unless File.directory?(output_dir)
|
74
79
|
puts "Output log directory (#{output_dir}) does not exist or is not a directory."
|
75
|
-
|
80
|
+
begin
|
81
|
+
FileUtils.mkdir_p(output_dir)
|
82
|
+
rescue Errno::EACCES
|
83
|
+
puts "Permission denied, could not create output directory (#{output_dir})"
|
84
|
+
return false
|
85
|
+
end
|
76
86
|
end
|
77
87
|
|
78
88
|
logfile_obj = parse(logfile_path, my_aliases)
|
79
89
|
return false if logfile_obj == false
|
80
90
|
dest_file_path = logfile_obj.write_out(overwrite, output_dir)
|
81
91
|
if dest_file_path == false
|
82
|
-
error("
|
92
|
+
error("Successfully parsed file, but failed to write it out. Path: #{logfile_path}.")
|
83
93
|
return false
|
84
94
|
elsif dest_file_path == FILE_EXISTS
|
85
95
|
log_msg("File already exists.")
|
@@ -109,7 +119,7 @@ module Pidgin2Adium
|
|
109
119
|
if File.writable?(f)
|
110
120
|
File.delete(f)
|
111
121
|
else
|
112
|
-
error("
|
122
|
+
error("File exists but is not writable. Please delete it yourself: #{f}")
|
113
123
|
end
|
114
124
|
end
|
115
125
|
end
|
@@ -53,6 +53,10 @@ module Pidgin2Adium
|
|
53
53
|
delete_search_indexes()
|
54
54
|
|
55
55
|
log_msg "Finished converting! Converted #{total_successes} files of #{total_files} total."
|
56
|
+
puts "Minor error messages:"
|
57
|
+
puts @@oops_messages.join("\n")
|
58
|
+
puts "Major error messages:"
|
59
|
+
puts @@error_messages.join("\n")
|
56
60
|
end
|
57
61
|
|
58
62
|
###########
|
@@ -1,16 +1,17 @@
|
|
1
|
-
# ADD DOCUMENTATION
|
2
|
-
|
3
1
|
require 'fileutils'
|
4
2
|
|
5
3
|
module Pidgin2Adium
|
6
4
|
# A holding object for the result of LogParser.parse. It makes the
|
7
|
-
# instance variable @chat_lines available, which is an array of
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
5
|
+
# instance variable @chat_lines available, which is an array of Message
|
6
|
+
# subclass instances (XMLMessage, Event, etc.)
|
7
|
+
# Here is a list of the instance variables for each class in @chat_lines:
|
8
|
+
#
|
9
|
+
# <b>All of these variables are read/write.</b>
|
10
|
+
# All:: sender, time, buddy_alias
|
11
|
+
# XMLMessage:: body
|
12
|
+
# AutoReplyMessage:: body
|
13
|
+
# Event:: body, event_type
|
14
|
+
# StatusMessage:: status
|
14
15
|
class LogFile
|
15
16
|
include Pidgin2Adium
|
16
17
|
def initialize(chat_lines, service, user_SN, partner_SN, adium_chat_time_start)
|
@@ -5,6 +5,7 @@
|
|
5
5
|
# Please use Pidgin2Adium.parse or Pidgin2Adium.parse_and_generate instead of
|
6
6
|
# using these classes directly.
|
7
7
|
require 'parsedate'
|
8
|
+
require 'time' # for Time.zone_offset
|
8
9
|
|
9
10
|
require 'pidgin2adium/balance_tags'
|
10
11
|
require 'pidgin2adium/log_file'
|
@@ -64,7 +65,7 @@ module Pidgin2Adium
|
|
64
65
|
@adium_chat_time_start = pre_parse()
|
65
66
|
rescue InvalidFirstLineError
|
66
67
|
@first_line_is_valid = false
|
67
|
-
error("
|
68
|
+
error("Failed to parse, invalid first line: #{@src_path}")
|
68
69
|
return # stop processing
|
69
70
|
end
|
70
71
|
|
@@ -143,19 +144,26 @@ module Pidgin2Adium
|
|
143
144
|
@file_content = cleanup(@file_content).split("\n")
|
144
145
|
|
145
146
|
@file_content.map! do |line|
|
147
|
+
# "next" returns nil which is removed by compact
|
146
148
|
next if line =~ /^\s+$/
|
147
149
|
if line =~ @line_regex
|
148
150
|
create_msg($~.captures)
|
149
151
|
elsif line =~ @line_regex_status
|
150
|
-
create_status_or_event_msg($~.captures)
|
152
|
+
msg = create_status_or_event_msg($~.captures)
|
153
|
+
# Error occurred while parsing
|
154
|
+
return false if msg == false
|
151
155
|
else
|
152
156
|
error "Could not parse line:"
|
153
|
-
p line
|
154
|
-
|
157
|
+
p line
|
158
|
+
return false
|
155
159
|
end
|
156
|
-
end
|
160
|
+
end
|
161
|
+
@file_content.compact!
|
157
162
|
return LogFile.new(@file_content, @service, @user_SN, @partner_SN, @adium_chat_time_start)
|
158
163
|
end
|
164
|
+
# Prevent parse from being called directly from BasicParser, since
|
165
|
+
# it uses subclassing magic.
|
166
|
+
protected :parse
|
159
167
|
|
160
168
|
#################
|
161
169
|
private
|
@@ -167,7 +175,7 @@ module Pidgin2Adium
|
|
167
175
|
# 1) the log has an empty start date column in the viewer
|
168
176
|
# 2) The timestamps are all the same for the whole log
|
169
177
|
tz_match = /([-\+]\d+)[A-Z]{3}\.(?:txt|htm|html)/.match(@src_path)
|
170
|
-
if tz_match[1]
|
178
|
+
if tz_match and tz_match[1]
|
171
179
|
tz_offset = tz_match[1]
|
172
180
|
else
|
173
181
|
zone = Time.local(Time.new.year).zone
|
@@ -296,6 +304,8 @@ module Pidgin2Adium
|
|
296
304
|
#--
|
297
305
|
# create_status_or_event_msg takes an array of +MatchData+ captures from
|
298
306
|
# matching against @line_regex_status and returns an Event or Status.
|
307
|
+
# Returns nil if it's a message that should be ignored, or false if an
|
308
|
+
# error occurred.
|
299
309
|
#++
|
300
310
|
def create_status_or_event_msg(matches)
|
301
311
|
# ["22:58:00", "BuddyName logged in."]
|
@@ -322,10 +332,8 @@ module Pidgin2Adium
|
|
322
332
|
if @event_map.detect{|regex,event_type| str =~ regex}
|
323
333
|
regex, event_type = $1, $2
|
324
334
|
else
|
325
|
-
error("
|
326
|
-
|
327
|
-
error(sprintf("str: %p", str))
|
328
|
-
exit 1
|
335
|
+
error(sprintf("Error parsing status or event message, no status or event found: %p", str))
|
336
|
+
return false
|
329
337
|
end
|
330
338
|
end
|
331
339
|
if regex and event_type
|
@@ -367,6 +375,8 @@ module Pidgin2Adium
|
|
367
375
|
@line_regex_status = /#{@timestamp_rx} ([^:]+)/o
|
368
376
|
end
|
369
377
|
|
378
|
+
public :parse
|
379
|
+
|
370
380
|
#################
|
371
381
|
private
|
372
382
|
#################
|
@@ -407,6 +417,8 @@ module Pidgin2Adium
|
|
407
417
|
# 1: status message
|
408
418
|
@line_regex_status = /#{@timestamp_rx} ?<b> (.+)<\/b><br ?\/>/o
|
409
419
|
end
|
420
|
+
|
421
|
+
public :parse
|
410
422
|
|
411
423
|
#################
|
412
424
|
private
|
@@ -520,8 +532,12 @@ module Pidgin2Adium
|
|
520
532
|
# Subclasses: XMLMessage, AutoReplyMessage, StatusMessage, Event.
|
521
533
|
class Message
|
522
534
|
def initialize(sender, time, buddy_alias)
|
535
|
+
# The sender's screen name
|
523
536
|
@sender = sender
|
537
|
+
# The time the message was sent, in Adium format (e.g.
|
538
|
+
# "2008-10-05T22:26:20-0800")
|
524
539
|
@time = time
|
540
|
+
# The receiver's alias (NOT screen name)
|
525
541
|
@buddy_alias = buddy_alias
|
526
542
|
end
|
527
543
|
attr_accessor :sender, :time, :buddy_alias
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pidgin2adium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabe B-W
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-18 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -20,7 +20,7 @@ dependencies:
|
|
20
20
|
requirements:
|
21
21
|
- - ">="
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: 2.
|
23
|
+
version: 2.4.0
|
24
24
|
version:
|
25
25
|
description: |-
|
26
26
|
Pidgin2Adium is a fast, easy way to convert Pidgin (formerly gaim) logs to the
|