-
Notifications
You must be signed in to change notification settings - Fork 2
/
c2h.rb
executable file
·274 lines (240 loc) · 7.89 KB
/
c2h.rb
1
2
3
4
5
6
7
8
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#! env ruby
require 'optparse'
require 'ostruct'
require 'pathname'
require 'date'
require_relative 'wacb'
#
# ----------------------------------------------------------------------
# Command line handling.
# ----------------------------------------------------------------------
#
class CmdLine
def self.parse(args)
options = OpenStruct.new
options.outputType = :Html
options.outputDirectory = "."
options.chatName = nil
options.printChatNames = false
options.printChatParticipants = nil
options.title = nil
options.me = nil
options.from = nil
options.to = nil
options.senderMap = {}
options.verbose = 0
options.split = nil
options.emojiDir = nil
options.imageWidth = nil
options.imageHeight = nil
options.backgroundImage = nil
options.attachments = nil
options.renameAttachments = false
opt_parser = OptionParser.new do |opts|
opts.banner = "Usage: c2h.rb [options] inputFile ..."
opts.on("--outputType=[html,chat]", "Output type (default is Html).") do |o|
if o.downcase == "html"
options.outputType = :Html
elsif o.downcase == "chat"
options.outputType = :Chat
else
raise "Invalid value for --outputType option: \"#{o}\""
end
end
opts.on("-o", "--outputDirectory=DIR", "Output directory, will be created if it does not exist.") do |o|
options.outputDirectory = o
end
opts.on("-n", "--chatName=name", "Chat name (only relevant for Explorer for WhatsApp files).") do |o|
options.chatName = o
end
opts.on("--printChatNames", "No conversion, just print the names of all chats.") do
options.printChatNames = true
end
opts.on("--printChatParticipants", "No conversion, just print the names of all participants.") do
options.printChatParticipants = true
end
opts.on("--from=yyyy[-mm[-dd]]", "Select messages from this date or later.") do |date|
parts = date.split("-")
year = parts[0].to_i
month = (parts.size() > 1) ? parts[1].to_i : 1
day = (parts.size() > 2) ? parts[2].to_i : 1
options.from = Date.new(year, month, day)
end
opts.on("--to=yyyy[-mm[-dd]]", "Select messages from until this date.") do |date|
parts = date.split("-")
year = parts[0].to_i
month = (parts.size() > 1) ? parts[1].to_i : -1
day = (parts.size() > 2) ? parts[2].to_i : -1
options.to = Date.new(year, month, day)
end
opts.on("--me=name", "Identify yourself.") do |me|
options.me = me
end
opts.on("--map=<sender=name>,...", Array, "Map sender ids to proper names.") do |list|
list.each { |map|
senderId, name = map.split("=")
options.senderMap[senderId] = name
}
end
opts.on("--attachments=[Copy,Move]", "Copy or move attachments to output directory.") do |o|
if o.downcase == "copy"
options.attachments = :Copy
elsif o.downcase == "move"
options.attachments = :Move
else
raise "Invalid value for --attachments option: \"#{o}\""
end
end
opts.on("--renameAttachments", "Rename attachments by date.") do
options.renameAttachments = true
end
opts.on("-t", "--title=Title", "[HTML] Chat title.") do |t|
options.title = t
end
opts.on("--split=[month,year]", "[HTML] Split into monthly or annual files.") do |o|
if o.downcase == "month"
options.split = :Month
elsif o.downcase == "year"
options.split = :Year
else
raise "Invalid value for --split option: \"#{o}\""
end
end
opts.on("--emojiDir=directory", "[HTML] Use emoji image files from this directory.") do |e|
options.emojiDir = e
end
opts.on("-b", "--backgroundImage=fileName", "[HTML] Background image name.") do |b|
options.backgroundImage = b
end
opts.on("--imageSize=<width>x<height>", "[HTML] Limit size of embedded images, default 320x240.") do |s|
sa = s.split("x")
options.imageWidth = sa[0].to_i
options.imageHeight = sa[1].to_i
end
opts.on("-v", "--verbose", "Increase verbosity.") do
options.verbose = options.verbose + 1
end
opts.on_tail("-h", "--help", "Show this message.") do
puts opts
exit
end
end
opt_parser.parse!(args)
return options, args
end
end
options, inputFiles = CmdLine.parse(ARGV)
if inputFiles.empty?
CmdLine.parse(["-h"]) # exits
end
#
# ----------------------------------------------------------------------
# Main.
# ----------------------------------------------------------------------
#
allMessages = WhatsAppChatBeautifier::Messages.new()
allMessages.setSenderMap(options.senderMap)
log = WhatsAppChatBeautifier::ConsoleOutput.new(options.verbose)
#
# Load input files.
#
inputFiles.each { |inputFileName|
log.begin("Loading chat from \"#{inputFileName}\"")
inputFile = WhatsAppChatBeautifier.openInput(inputFileName)
cp = WhatsAppChatBeautifier.parseChat(inputFile, options.me, options.from, options.to)
log.end()
#
# Print chat names.
#
if options.printChatNames
if !cp.is_a?(WhatsAppChatBeautifier::ExwaParser)
raise "The --chatNames option is only available with Explorer for WhatsApp files."
end
puts("Chat names:")
chatNames = cp.getChatNames()
chatNames.each_key { |chatName|
puts("\t" + chatName)
if options.verbose > 0
chatNames[chatName].each { |p|
puts("\t\t" + p)
}
end
}
exit
end
#
# Select the desired chat.
#
if cp.is_a?(WhatsAppChatBeautifier::ExwaParser)
if !options.chatName
raise "Must use --chatName with Explorer for WhatsApp files."
end
selectedChat = cp.matchChatName(options.chatName)
raise "Oops, chat \"#{options.chatName}\" not found." if !selectedChat
log.begin("Selecting chat \"#{selectedChat}\"")
cp.select(selectedChat)
log.end()
end
#
# When the "Me" option is not given, the WhatsApp parser selects on
# of the chat participants as "me".
#
if !options.me and cp.is_a?(WhatsAppChatBeautifier::WhatsAppParser)
options.me = cp.getMe()
end
messages = cp.getMessages()
allMessages.add(messages, inputFile)
#
# Print chat participants.
#
if options.printChatParticipants
puts("Chat participants:")
participants = allMessages.getSenders()
participants.each { |participant|
puts("\t" + participant)
}
exit
end
}
#
# Create output directory if it does not exist.
#
outputDir = Pathname.new(options.outputDirectory)
if !outputDir.directory? and !outputDir.exist?
outputDir.mkdir()
end
if !outputDir.directory?
puts "Oops: \"" + outputDir.to_s + "\" is not a directory."
exit
end
#
# Export
#
case (options.outputType)
when :Html
htmlExporterOptions = {
:me => options.me,
:title => options.title,
:backgroundImage => options.backgroundImage,
:split => options.split,
:emojiDir => options.emojiDir,
:imageWidth => options.imageWidth,
:imageHeight => options.imageHeight,
:attachments => options.attachments,
:renameAttachments => options.renameAttachments,
:log => log
}
wace = WhatsAppChatBeautifier::HtmlExporter.new(outputDir, allMessages, htmlExporterOptions)
wace.export()
when :Chat
whatsAppExporterOptions = {
:me => options.me,
:attachments => options.attachments,
:renameAttachments => options.renameAttachments,
:log => log
}
wace = WhatsAppChatBeautifier::WhatsAppExporter.new(outputDir, allMessages, whatsAppExporterOptions)
wace.export()
else
raise "Oops"
end