pidgin2adium 0.0.1 → 1.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.
- data/bin/pidgin2adium_logs +11 -11
- data/lib/pidgin2adium/ChatFileGenerator.rb +30 -214
- data/lib/pidgin2adium/SrcFileParse.rb +401 -196
- data/lib/pidgin2adium/balance-tags.rb +16 -16
- data/lib/pidgin2adium/logs.rb +57 -57
- data/lib/pidgin2adium/status.rb +7 -2
- metadata +5 -14
@@ -7,7 +7,7 @@ module Pidgin2Adium
|
|
7
7
|
# @license GPL v2.0
|
8
8
|
# @copyright November 4, 2001
|
9
9
|
# @return string Balanced text.
|
10
|
-
def Pidgin2Adium.
|
10
|
+
def Pidgin2Adium.balanceTags( text )
|
11
11
|
tagstack = []
|
12
12
|
stacksize = 0
|
13
13
|
tagqueue = ''
|
@@ -16,14 +16,15 @@ module Pidgin2Adium
|
|
16
16
|
nestable_tags = ['blockquote', 'div', 'span'] # Tags that can be immediately nested within themselves
|
17
17
|
tag_regex = /<(\/?\w*)\s*([^>]*)>/
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
# WP bug fix for comments - in case you REALLY meant to type '< !--'
|
20
|
+
text.gsub!('< !--', '< !--')
|
21
|
+
|
21
22
|
# WP bug fix for LOVE <3 (and other situations with '<' before a number)
|
22
23
|
text.gsub!(/<([0-9]{1})/, '<\1')
|
23
24
|
|
24
25
|
while ( regex = text.match(tag_regex) )
|
25
26
|
regex = regex.to_a
|
26
|
-
newtext
|
27
|
+
newtext << tagqueue
|
27
28
|
i = text.index(regex[0])
|
28
29
|
l = regex[0].length
|
29
30
|
|
@@ -38,7 +39,7 @@ module Pidgin2Adium
|
|
38
39
|
#or close to be safe tag = '/' . tag
|
39
40
|
# if stacktop value = tag close value then pop
|
40
41
|
elsif (tagstack[stacksize - 1] == tag) # found closing tag
|
41
|
-
tag = '</'
|
42
|
+
tag = '</' << tag << '>'; # Close Tag
|
42
43
|
# Pop
|
43
44
|
tagstack.pop
|
44
45
|
stacksize -= 1
|
@@ -48,7 +49,7 @@ module Pidgin2Adium
|
|
48
49
|
# add tag to tagqueue
|
49
50
|
ss = stacksize - 1
|
50
51
|
ss.downto(j) do |k|
|
51
|
-
tagqueue
|
52
|
+
tagqueue << '</' << tagstack.pop << '>'
|
52
53
|
stacksize -= 1
|
53
54
|
end
|
54
55
|
break
|
@@ -65,14 +66,14 @@ module Pidgin2Adium
|
|
65
66
|
# If: self-closing or '', don't do anything.
|
66
67
|
elsif ( single_tags.include?(tag) )
|
67
68
|
# ElseIf: it's a known single-entity tag but it doesn't close itself, do so
|
68
|
-
regex[2]
|
69
|
+
regex[2] << '/'
|
69
70
|
else
|
70
71
|
# Push the tag onto the stack
|
71
72
|
# If the top of the stack is the same as the tag we want to push, close previous tag
|
72
73
|
if ((stacksize > 0) &&
|
73
74
|
! nestable_tags.include?(tag) &&
|
74
75
|
(tagstack[stacksize - 1] == tag))
|
75
|
-
tagqueue = '</'
|
76
|
+
tagqueue = '</' << tagstack.pop << '>'
|
76
77
|
stacksize -= 1
|
77
78
|
end
|
78
79
|
stacksize = tagstack.push(tag).length
|
@@ -81,29 +82,28 @@ module Pidgin2Adium
|
|
81
82
|
# Attributes
|
82
83
|
attributes = regex[2]
|
83
84
|
if(attributes != '')
|
84
|
-
attributes = ' '
|
85
|
+
attributes = ' ' << attributes
|
85
86
|
end
|
86
|
-
tag = '<'
|
87
|
+
tag = '<' << tag << attributes << '>'
|
87
88
|
#If already queuing a close tag, then put this tag on, too
|
88
89
|
if (tagqueue)
|
89
|
-
tagqueue
|
90
|
+
tagqueue << tag
|
90
91
|
tag = ''
|
91
92
|
end
|
92
93
|
end
|
93
|
-
newtext
|
94
|
-
# text = substr(text,i+l)
|
94
|
+
newtext << text[0,i] << tag
|
95
95
|
text = text[i+l, text.length - (i+l)]
|
96
96
|
end
|
97
97
|
|
98
98
|
# Clear Tag Queue
|
99
|
-
newtext
|
99
|
+
newtext << tagqueue
|
100
100
|
|
101
101
|
# Add Remaining text
|
102
|
-
newtext
|
102
|
+
newtext << text
|
103
103
|
|
104
104
|
# Empty Stack
|
105
105
|
while(x = tagstack.pop)
|
106
|
-
newtext
|
106
|
+
newtext << '</' << x << '>'; # Add remaining tags to close
|
107
107
|
end
|
108
108
|
|
109
109
|
# WP fix for the bug with HTML comments
|
data/lib/pidgin2adium/logs.rb
CHANGED
@@ -8,6 +8,10 @@
|
|
8
8
|
#A ruby program to convert Pidgin log files to Adium log files, then place
|
9
9
|
#them in the Adium log directory with allowances for time zone differences.
|
10
10
|
|
11
|
+
require 'pidgin2adium/SrcFileParse'
|
12
|
+
require 'pidgin2adium/ChatFileGenerator'
|
13
|
+
require 'fileutils'
|
14
|
+
|
11
15
|
class Time
|
12
16
|
ZoneOffset = {
|
13
17
|
'UTC' => 0,
|
@@ -46,11 +50,6 @@ class Time
|
|
46
50
|
end
|
47
51
|
|
48
52
|
module Pidgin2Adium
|
49
|
-
require 'pidgin2adium/SrcFileParse'
|
50
|
-
require 'pidgin2adium/ChatFileGenerator'
|
51
|
-
require 'parsedate'
|
52
|
-
require 'fileutils'
|
53
|
-
|
54
53
|
# put's content. Also put's to @LOG_FILE_FH if @debug == true.
|
55
54
|
def Pidgin2Adium.logMsg(str, isError=false)
|
56
55
|
content = str.to_s
|
@@ -66,37 +65,30 @@ module Pidgin2Adium
|
|
66
65
|
def initialize(src, out, aliases, libdir, tz=nil, debug=false)
|
67
66
|
# These files/directories show up in Dir.entries(x)
|
68
67
|
@BAD_DIRS = %w{. .. .DS_Store Thumbs.db .system}
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
@src_dir = File.expand_path(src)
|
69
|
+
@out_dir = File.expand_path(out)
|
70
|
+
# Whitespace is removed for easy matching later on.
|
71
|
+
@my_aliases = aliases.map{|x| x.downcase.gsub(/\s+/,'') }.uniq
|
72
|
+
# @libdir is the directory in
|
73
|
+
# ~/Library/Application Support/Adium 2.0/Users/Default/Logs/.
|
74
|
+
# For AIM, it's like "AIM.<screenname>"
|
75
|
+
# FIXME: don't make the user pass in libdir - we can and SHOULD change it on a per-service/screenname basis
|
76
|
+
@libdir = libdir
|
77
|
+
@DEFAULT_TIME_ZONE = tz || Time.now.zone
|
78
|
+
@debug = debug
|
79
|
+
unless File.directory?(@src_dir)
|
80
|
+
puts "Source directory #{@src_dir} does not exist or is not a directory."
|
73
81
|
raise Errno::ENOENT
|
74
82
|
end
|
75
|
-
unless File.directory?(
|
83
|
+
unless File.directory?(@out_dir)
|
76
84
|
begin
|
77
|
-
FileUtils.mkdir_p(
|
85
|
+
FileUtils.mkdir_p(@out_dir)
|
78
86
|
rescue
|
79
|
-
puts "Output directory #{
|
87
|
+
puts "Output directory #{@out_dir} does not exist or is not a directory and could not be created."
|
80
88
|
raise Errno::ENOENT
|
81
89
|
end
|
82
90
|
end
|
83
91
|
|
84
|
-
if libdir.nil?
|
85
|
-
puts "You must provide libdir."
|
86
|
-
raise Error
|
87
|
-
end
|
88
|
-
|
89
|
-
@src_dir = src
|
90
|
-
@out_dir = out
|
91
|
-
|
92
|
-
# Whitespace is removed for easy matching later on.
|
93
|
-
@my_aliases = aliases.map{|x| x.downcase.gsub(/\s+/,'') }.uniq
|
94
|
-
# @libdir is the directory in
|
95
|
-
# ~/Library/Application Support/Adium 2.0/Users/Default/Logs/.
|
96
|
-
# For AIM, it's like "AIM.<screenname>"
|
97
|
-
@libdir = libdir
|
98
|
-
@debug = debug
|
99
|
-
@DEFAULT_TIME_ZONE = tz || Time.now.zone
|
100
92
|
# local offset, like "-0800" or "+1000"
|
101
93
|
@DEFAULT_TZ_OFFSET = '%+03d00'%Time.zone_offset(@DEFAULT_TIME_ZONE)
|
102
94
|
end
|
@@ -104,16 +96,20 @@ module Pidgin2Adium
|
|
104
96
|
def start
|
105
97
|
Pidgin2Adium.logMsg "Begin converting."
|
106
98
|
begin
|
107
|
-
filesPath =
|
99
|
+
filesPath = getAllChatFiles(@src_dir)
|
108
100
|
rescue Errno::EACCES => bang
|
109
|
-
Pidgin2Adium.logMsg("Sorry, permission denied for getting chat files from #{@src_dir}.", true)
|
101
|
+
Pidgin2Adium.logMsg("Sorry, permission denied for getting Pidgin chat files from #{@src_dir}.", true)
|
110
102
|
Pidgin2Adium.logMsg("Details: #{bang.message}", true)
|
111
103
|
raise Errno::EACCES
|
112
104
|
end
|
113
105
|
|
114
|
-
Pidgin2Adium.logMsg(filesPath.length
|
115
|
-
filesPath.
|
116
|
-
|
106
|
+
Pidgin2Adium.logMsg("#{filesPath.length} files to convert.")
|
107
|
+
totalFiles = filesPath.size
|
108
|
+
filesPath.each_with_index do |fname, i|
|
109
|
+
Pidgin2Adium.logMsg(
|
110
|
+
sprintf("[%d/%d] Converting %s...",
|
111
|
+
(i+1), totalFiles, fname)
|
112
|
+
)
|
117
113
|
convert(fname)
|
118
114
|
end
|
119
115
|
|
@@ -164,10 +160,10 @@ module Pidgin2Adium
|
|
164
160
|
Pidgin2Adium.logMsg("Could not create #{toCreate}: #{bang.class} #{bang.message}", true)
|
165
161
|
return false
|
166
162
|
end
|
167
|
-
fileWithXmlExt = srcPath[0, srcPath.size-File.extname(srcPath).size]
|
163
|
+
fileWithXmlExt = srcPath[0, srcPath.size-File.extname(srcPath).size] << ".xml"
|
168
164
|
# @src_dir/log.chatlog (file) -> @out_dir/log.chatlog/log.xml
|
169
165
|
File.cp(srcPath, File.join(@out_dir, srcPath, fileWithXmlExt))
|
170
|
-
Pidgin2Adium.logMsg("Copied #{srcPath} to "
|
166
|
+
Pidgin2Adium.logMsg("Copied #{srcPath} to " << File.join(@out_dir, srcPath, fileWithXmlExt))
|
171
167
|
return true
|
172
168
|
else
|
173
169
|
Pidgin2Adium.logMsg("srcPath (#{srcPath}) is not a txt, html, or chatlog file. Doing nothing.")
|
@@ -192,54 +188,58 @@ module Pidgin2Adium
|
|
192
188
|
end
|
193
189
|
end
|
194
190
|
|
195
|
-
def
|
191
|
+
def getAllChatFiles(dir)
|
196
192
|
return [] if File.basename(dir) == ".system"
|
197
193
|
# recurse into each subdir
|
198
|
-
return (Dir.glob(File.join(@src_dir, '**', '*.{html,txt}')) - @BAD_DIRS)
|
194
|
+
return (Dir.glob(File.join(@src_dir, '**', '*.{htm,html,txt}')) - @BAD_DIRS)
|
199
195
|
end
|
200
196
|
|
201
197
|
# Copies logs, accounting for timezone changes
|
202
198
|
def copyLogs
|
203
199
|
Pidgin2Adium.logMsg "Copying logs with accounting for different time zones..."
|
204
|
-
|
205
|
-
|
200
|
+
# FIXME: not all logs are AIM logs, libdir may change
|
201
|
+
realSrcDir = File.expand_path('~/Library/Application Support/Adium 2.0/Users/Default/Logs/') << "/#{@libdir}/"
|
202
|
+
realDestDir = File.join(@out_dir, @libdir) << '/'
|
206
203
|
|
207
|
-
src_entries = Dir.entries(
|
208
|
-
dest_entries = Dir.entries(
|
204
|
+
src_entries = Dir.entries(realSrcDir)
|
205
|
+
dest_entries = Dir.entries(realDestDir)
|
209
206
|
both_entries = (src_entries & dest_entries) - @BAD_DIRS
|
210
207
|
|
211
208
|
both_entries.each do |name|
|
212
|
-
my_src_entries = Dir.entries(
|
213
|
-
my_dest_entries = Dir.entries(
|
209
|
+
my_src_entries = Dir.entries(realSrcDir << name) - @BAD_DIRS
|
210
|
+
my_dest_entries = Dir.entries(realDestDir << name) - @BAD_DIRS
|
214
211
|
|
215
212
|
in_both = my_src_entries & my_dest_entries
|
216
213
|
in_both.each do |logdir|
|
217
214
|
FileUtils.cp(
|
218
|
-
File.join(
|
219
|
-
|
215
|
+
File.join(realSrcDir, name, logdir, logdir.sub('chatlog', 'xml')),
|
216
|
+
File.join(realDestDir, name, logdir) << '/',
|
220
217
|
:verbose => false)
|
221
218
|
end
|
222
|
-
# The logs that are only in one of the dirs are not necessarily
|
223
|
-
# They might just have different
|
219
|
+
# The logs that are only in one of the dirs are not necessarily
|
220
|
+
# different logs than the dest. They might just have different
|
221
|
+
# timestamps. Thus, we use regexes.
|
224
222
|
only_in_src = my_src_entries - in_both
|
225
223
|
only_in_dest = my_dest_entries - in_both
|
226
|
-
# Move files from
|
224
|
+
# Move files from realSrcDir that are actually in both, but
|
225
|
+
# just have different time zones.
|
227
226
|
only_in_src.each do |srcLogDir|
|
228
227
|
# Match on everything except the timezone ("-0400.chatlog")
|
229
|
-
|
230
|
-
|
231
|
-
if
|
232
|
-
# Only in source, so we can copy it without fear of
|
233
|
-
|
234
|
-
|
228
|
+
fileBeginRegex = Regexp.new('^'<<Regexp.escape(srcLogDir.sub(/-\d{4}.\.chatlog$/, '')) )
|
229
|
+
targetChatlogDir = only_in_dest.find{|d| d =~ fileBeginRegex}
|
230
|
+
if targetChatlogDir.nil?
|
231
|
+
# Only in source, so we can copy it without fear of
|
232
|
+
# overwriting.
|
233
|
+
targetChatlogDir = srcLogDir
|
234
|
+
FileUtils.mkdir_p(File.join(realDestDir, name, targetChatlogDir))
|
235
235
|
end
|
236
|
-
# Move to
|
236
|
+
# Move to targetChatlogDir so we overwrite the destination
|
237
237
|
# file but still use its timestamp
|
238
238
|
# (if it exists; if it doesn't, then we're using our own
|
239
239
|
# timestamp).
|
240
240
|
FileUtils.cp(
|
241
|
-
File.join(
|
242
|
-
File.join(
|
241
|
+
File.join(realSrcDir, name, srcLogDir, srcLogDir.sub('chatlog', 'xml')),
|
242
|
+
File.join(realDestDir, name, targetChatlogDir, targetChatlogDir.sub('chatlog', 'xml')),
|
243
243
|
:verbose => false
|
244
244
|
)
|
245
245
|
end
|
data/lib/pidgin2adium/status.rb
CHANGED
@@ -8,8 +8,13 @@
|
|
8
8
|
# It doesn't work in Mac OSX 10.5 (Leopard).
|
9
9
|
# See: http://trac.adiumx.com/ticket/8863
|
10
10
|
# It should work in Mac OSX 10.4 (Tiger), but is untested.
|
11
|
-
|
12
|
-
#
|
11
|
+
#
|
12
|
+
# TODO: check adium version in
|
13
|
+
# /Applications/Adium.app/Contents
|
14
|
+
# with this:
|
15
|
+
# <key>CFBundleShortVersionString</key>
|
16
|
+
# <string>1.3.4</string>
|
17
|
+
# For Mac 10.5+, needs to be 1.4; should work for 10.4 with 1.3.x
|
13
18
|
|
14
19
|
require 'rubygems'
|
15
20
|
require 'hpricot'
|
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: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabe B-W
|
@@ -9,19 +9,10 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-24 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
name: hpricot
|
17
|
-
type: :runtime
|
18
|
-
version_requirement:
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
20
|
-
requirements:
|
21
|
-
- - ">="
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 0.8.1
|
24
|
-
version:
|
14
|
+
dependencies: []
|
15
|
+
|
25
16
|
description: Converts Pidgin logs and statuses to Adium format and makes them available to Adium. Also installstwo shell scripts, pidgin2adium_logs and pidgin2adium_status.
|
26
17
|
email: gbw@rubyforge.org
|
27
18
|
executables:
|
@@ -61,7 +52,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
52
|
requirements: []
|
62
53
|
|
63
54
|
rubyforge_project: pidgin2adium
|
64
|
-
rubygems_version: 1.3.
|
55
|
+
rubygems_version: 1.3.5
|
65
56
|
signing_key:
|
66
57
|
specification_version: 3
|
67
58
|
summary: Converts Pidgin logs and statuses to Adium format and makes them available to Adium.
|