contacts_txt 0.2.11 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/contacts_txt.rb +190 -56
- data.tar.gz.sig +0 -0
- metadata +32 -27
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf478e02d22813b059b002369a94120ffa7db0c98e7ee02f7eb5a7604f000e36
|
4
|
+
data.tar.gz: 0e220217e01429b1b35c059df1e8459100ee4003a618c8634dcafd09ca30baeb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71e031cd9bef37e5d93c634832d2ba450a17605cbbf5c088898a73b1678cb0c477bfce0eddfa60604c784805b3126bd8e1305ebc494e78927aea4024339e0752
|
7
|
+
data.tar.gz: 1d0686e575cd7242676541d2ad093a113c5ffd95666f56450d1139376d4d399ecd6c67e7b547f9118e02cc4f7e42620e93dd2752b550f445c43cab008d216a0c
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/contacts_txt.rb
CHANGED
@@ -3,26 +3,27 @@
|
|
3
3
|
# file: contacts_txt.rb
|
4
4
|
|
5
5
|
require 'dynarex'
|
6
|
+
require 'rxfreadwrite'
|
6
7
|
|
7
8
|
|
8
9
|
class ContactsTxt
|
9
|
-
include
|
10
|
+
include RXFReadWriteModule
|
10
11
|
|
11
12
|
attr_reader :to_s
|
12
|
-
|
13
|
-
def initialize(src=nil, fields: %w(role organisation mobile
|
14
|
-
sms email dob tags address notes note mobile2 ),
|
13
|
+
|
14
|
+
def initialize(src=nil, fields: %w(role organisation mobile
|
15
|
+
sms email dob tags address notes note mobile2 ),
|
15
16
|
username: nil, password: nil, debug: false)
|
16
|
-
|
17
|
+
|
17
18
|
@debug = debug
|
18
19
|
@fields = %w(fullname firstname lastname tel) | fields
|
19
20
|
|
20
21
|
txt, type = if src then
|
21
|
-
|
22
|
+
RXFReader.read(src, username: username, password: password)
|
22
23
|
else
|
23
24
|
['', :unknown]
|
24
25
|
end
|
25
|
-
|
26
|
+
|
26
27
|
case type
|
27
28
|
when :file
|
28
29
|
@path, @filename = File.dirname(src), File.basename(src)
|
@@ -33,94 +34,165 @@ class ContactsTxt
|
|
33
34
|
when :unknown
|
34
35
|
@path, @filename = '.', 'contacts.txt'
|
35
36
|
end
|
36
|
-
|
37
|
+
|
37
38
|
@dx = txt.lines.length > 1 ? import_to_dx(txt) : new_dx()
|
38
39
|
|
39
40
|
end
|
40
|
-
|
41
|
+
|
42
|
+
def all()
|
43
|
+
@dx.all
|
44
|
+
end
|
45
|
+
|
41
46
|
def dx()
|
42
47
|
@dx
|
43
48
|
end
|
44
|
-
|
49
|
+
|
45
50
|
def find_by_id(id)
|
46
|
-
|
51
|
+
|
47
52
|
@dx.find_by_id id
|
48
|
-
|
53
|
+
|
49
54
|
end
|
50
|
-
|
55
|
+
|
51
56
|
def find_by_mobile(raw_number, countrycode='44')
|
52
57
|
|
53
58
|
number = Regexp.new raw_number.sub(/^(?:0|#{countrycode})/,'').gsub(/[ -]*/,'')
|
54
|
-
|
55
|
-
@dx.all.find {|x| x.mobile.gsub(/[ -]*/,'') =~ number }
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
+
@dx.all.find {|x| x.mobile.gsub(/[ -]*/,'') =~ number }
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def find_by_name(s)
|
65
|
+
|
66
|
+
# Appending a hashtag to the name can help with finding the specific record
|
67
|
+
# e.g. 'Peter#plumber' or 'Peter #plumber'
|
68
|
+
|
69
|
+
raw_name, tag = s.split('#',2).map(&:strip)
|
60
70
|
|
61
71
|
name = Regexp.new "\b#{raw_name}\b|#{raw_name}", Regexp::IGNORECASE
|
62
72
|
puts 'name: ' + name.inspect if @debug
|
63
|
-
|
64
|
-
@dx.all.select do |x|
|
73
|
+
|
74
|
+
a = @dx.all.select do |x|
|
65
75
|
x.fullname =~ name or x.firstname =~ name or x.lastname =~ name
|
66
76
|
end
|
67
77
|
|
68
|
-
|
69
|
-
|
78
|
+
if tag then
|
79
|
+
a.find {|x| x.tags.split.map(&:downcase).include? tag.downcase }
|
80
|
+
else
|
81
|
+
a
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
70
86
|
def find_by_sms(raw_number, countrycode='44')
|
71
87
|
|
72
88
|
number = Regexp.new raw_number\
|
73
89
|
.sub(/^(?:0|#{countrycode})/,'').gsub(/[ -]*/,'')
|
74
|
-
|
90
|
+
|
75
91
|
@dx.all.find {|x| x.sms.gsub(/[ -]*/,'') =~ number \
|
76
|
-
or x.mobile.gsub(/[ -]*/,'') =~ number }
|
92
|
+
or x.mobile.gsub(/[ -]*/,'') =~ number }
|
77
93
|
|
78
|
-
end
|
79
|
-
|
80
|
-
# find using the tel, mobile, or mobile2 fields
|
94
|
+
end
|
95
|
+
|
96
|
+
# find using the tel, mobile, or mobile2 fields
|
81
97
|
#
|
82
98
|
def find_by_telno(raw_number)
|
83
99
|
|
84
100
|
number = Regexp.new raw_number.gsub(/[ -]*/,'')
|
85
|
-
|
101
|
+
|
86
102
|
@dx.all.find do |x|
|
87
|
-
|
103
|
+
|
88
104
|
numbers = %i(tel mobile mobile2).map do |y|
|
89
105
|
x.method(y).call.gsub(/[ -]*/,'') if x.respond_to? y
|
90
106
|
end
|
91
|
-
|
107
|
+
|
92
108
|
puts 'numbers: ' + numbers.inspect if @debug
|
93
109
|
numbers.grep(number).any?
|
94
110
|
end
|
95
111
|
|
96
|
-
end
|
112
|
+
end
|
97
113
|
|
98
114
|
# returns a Dynarex object
|
99
|
-
#
|
115
|
+
#
|
100
116
|
def email_list()
|
101
117
|
@dx.filter {|x| x.email.length > 0}
|
102
118
|
end
|
103
|
-
|
119
|
+
|
104
120
|
def list_names()
|
105
|
-
|
121
|
+
|
106
122
|
@dx.all.inject([]) do |r, x|
|
107
123
|
x.fullname.length >= 1 ? r << x.fullname : r
|
108
124
|
end
|
109
125
|
|
110
126
|
end
|
111
|
-
|
127
|
+
|
112
128
|
def mobile_list()
|
113
129
|
@dx.filter {|x| x.mobile.length > 0}
|
114
|
-
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def multi_tel_index()
|
133
|
+
|
134
|
+
a = @dx.all.map do |x|
|
135
|
+
|
136
|
+
tel = %i(tel mobile mobile2).detect do |name|
|
137
|
+
!x.method(name).call.empty?
|
138
|
+
end
|
139
|
+
next unless tel
|
140
|
+
"%s %s" % [x.fullname, x.method(tel).call]
|
141
|
+
end.compact
|
142
|
+
|
143
|
+
|
144
|
+
# group by first name
|
145
|
+
r = a.group_by {|x| x[0]}
|
146
|
+
|
147
|
+
a2 = a.clone
|
148
|
+
|
149
|
+
# group by last name
|
150
|
+
r2 = a.group_by {|x| x.split(/ /,2).last[0]}
|
151
|
+
c = r2.merge(r)
|
152
|
+
|
153
|
+
c.each do |k, v|
|
154
|
+
|
155
|
+
puts "k: %s v: %s" % [k, v]
|
156
|
+
v.concat(r2[k]) if r2[k]
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
h = c.sort.each {|k,v| v.uniq!}.to_h
|
161
|
+
|
162
|
+
out = []
|
163
|
+
|
164
|
+
h.each do |k,v|
|
165
|
+
|
166
|
+
out << ' ' + (' ' * 30) + k
|
167
|
+
|
168
|
+
v.each do |x|
|
169
|
+
|
170
|
+
name, phone = x.split(/(?=\d)/,2)
|
171
|
+
out << "\n" + (name.length >= 29 ? name[0..26] + '...' : name)
|
172
|
+
tel = (' ' + ' ' * (26 - phone.length)) + 't: ' + phone
|
173
|
+
out << tel + "\n"
|
174
|
+
out << ('-' * 30)
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
puts out.join("\n")
|
181
|
+
|
182
|
+
end
|
115
183
|
|
116
184
|
def save(filename=@filename)
|
117
|
-
|
185
|
+
|
118
186
|
s = dx_to_s(@dx)
|
119
187
|
FileX.write File.join(@path, filename), s
|
120
188
|
@dx.save File.join(@path, filename.sub(/\.txt$/,'.xml'))
|
121
|
-
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
def to_dx()
|
193
|
+
@dx
|
122
194
|
end
|
123
|
-
|
195
|
+
|
124
196
|
def to_s()
|
125
197
|
dx_to_s @dx
|
126
198
|
end
|
@@ -128,9 +200,9 @@ class ContactsTxt
|
|
128
200
|
private
|
129
201
|
|
130
202
|
def dx_to_s(dx)
|
131
|
-
|
203
|
+
|
132
204
|
rows = dx.all.map do |row|
|
133
|
-
|
205
|
+
|
134
206
|
h = row.to_h
|
135
207
|
|
136
208
|
fullname = h.delete :fullname
|
@@ -140,11 +212,11 @@ class ContactsTxt
|
|
140
212
|
|
141
213
|
([fullname] + a.map {|x| x.join(': ') }).join("\n")
|
142
214
|
end
|
143
|
-
|
215
|
+
|
144
216
|
"<?contacts fields='%s'?>\n\n%s" % [@fields, rows.join("\n\n")]
|
145
|
-
|
217
|
+
|
146
218
|
end
|
147
|
-
|
219
|
+
|
148
220
|
def import_to_dx(raw_s)
|
149
221
|
|
150
222
|
s = if raw_s =~ /<?contacts / then
|
@@ -156,35 +228,97 @@ class ContactsTxt
|
|
156
228
|
found = s2[/(?<=#{keyword}=['"])[^'"]+/]
|
157
229
|
found ? r.merge(keyword.to_sym => found) : r
|
158
230
|
end
|
159
|
-
|
231
|
+
|
160
232
|
h = {
|
161
|
-
fields: @fields.join(', '),
|
162
|
-
}.merge attributes
|
233
|
+
fields: @fields.join(', '),
|
234
|
+
}.merge attributes
|
163
235
|
|
164
|
-
@fields = h[:fields].split(/ *, */)
|
236
|
+
@fields = h[:fields].split(/ *, */)
|
165
237
|
|
166
238
|
if h[:root] then
|
167
|
-
"\n\n" + h[:root] + "\n" +
|
239
|
+
"\n\n" + h[:root] + "\n" +
|
168
240
|
raw_contacts.strip.lines.map {|line| ' ' + line}.join
|
169
241
|
else
|
170
242
|
raw_contacts
|
171
243
|
end
|
172
|
-
|
244
|
+
|
173
245
|
else
|
174
|
-
|
246
|
+
|
175
247
|
raw_s.lstrip.lines[2..-1].join.strip
|
176
248
|
|
177
249
|
end
|
178
250
|
|
179
251
|
new_dx().import "--+\n" + s.split(/\s+(?=^[\w\s\(\)]+$)/)\
|
180
|
-
.map {|x| 'fullname: ' + x }.join("\n")
|
181
|
-
|
252
|
+
.map {|x| 'fullname: ' + x }.join("\n")
|
253
|
+
|
182
254
|
end
|
183
|
-
|
255
|
+
|
184
256
|
def new_dx()
|
185
|
-
|
257
|
+
|
186
258
|
Dynarex.new "contacts/contact(#{@fields.join ', '})"
|
187
|
-
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
class ContactsTxtAgent < ContactsTxt
|
265
|
+
|
266
|
+
def find_mobile_by_name(s)
|
267
|
+
|
268
|
+
result = find_by_name(s)
|
269
|
+
|
270
|
+
r = validate(result)
|
271
|
+
|
272
|
+
numbers = [r.sms.empty? ? r.mobile : r.sms, r.mobile].uniq\
|
273
|
+
.map {|x| x.sub(/\([^\)]+\)/,'').strip}
|
274
|
+
|
275
|
+
h = {}
|
276
|
+
h[:msg] = if numbers.length > 1 then
|
277
|
+
"The SMS number for %s is %s and the mobile number is %s" % \
|
278
|
+
[r.fullname, *numbers]
|
279
|
+
elsif numbers.first.length > 0 then
|
280
|
+
"The mobile number for %s is %s" % [r.fullname, numbers.first]
|
281
|
+
elsif r.tel.length > 0 then
|
282
|
+
"I don't have a mobile number, but the landline telephone " + \
|
283
|
+
"number for %s is %s" % [r.fullname, r.tel]
|
284
|
+
else
|
285
|
+
"I don't have a telephone number for " + r.fullname
|
286
|
+
end
|
287
|
+
|
288
|
+
h[:tags] = r.tags.to_s
|
289
|
+
h
|
290
|
+
end
|
291
|
+
|
292
|
+
def find_tel_by_name(s)
|
293
|
+
|
294
|
+
result = find_by_name(s)
|
295
|
+
r = validate(result)
|
296
|
+
|
297
|
+
h = {}
|
298
|
+
|
299
|
+
if r.tel.empty? then
|
300
|
+
return find_mobile_by_name(s)
|
301
|
+
else
|
302
|
+
h[:msg] = "The telephone number for %s is %s" % [r.fullname, r.tel]
|
303
|
+
end
|
304
|
+
|
305
|
+
h[:tags] = r.tags.to_s
|
306
|
+
h
|
307
|
+
end
|
308
|
+
|
309
|
+
private
|
310
|
+
|
311
|
+
def validate(result)
|
312
|
+
|
313
|
+
case result.class.to_s
|
314
|
+
when 'RecordX'
|
315
|
+
result
|
316
|
+
when 'Array'
|
317
|
+
result.first
|
318
|
+
when 'NilClass'
|
319
|
+
return "I couldn't find that name."
|
320
|
+
end
|
321
|
+
|
188
322
|
end
|
189
323
|
|
190
324
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contacts_txt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -10,27 +10,32 @@ bindir: bin
|
|
10
10
|
cert_chain:
|
11
11
|
- |
|
12
12
|
-----BEGIN CERTIFICATE-----
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
13
|
+
MIIEXjCCAsagAwIBAgIBATANBgkqhkiG9w0BAQsFADAsMSowKAYDVQQDDCFnZW1t
|
14
|
+
YXN0ZXIvREM9amFtZXNyb2JlcnRzb24vREM9ZXUwHhcNMjIwMjIzMTk0ODIwWhcN
|
15
|
+
MjMwMjIzMTk0ODIwWjAsMSowKAYDVQQDDCFnZW1tYXN0ZXIvREM9amFtZXNyb2Jl
|
16
|
+
cnRzb24vREM9ZXUwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDlecEA
|
17
|
+
1V+ZCFfCwQwbOZ9S2Tn+ggDp85hVOoHZyfA+E6MMOShj1CE22RDfbyrAal+Z01C5
|
18
|
+
dol4wfM2s3x3QGwU/BhwoBs1el3beCkqEf86/bAfBMZ7TsxP8NcxeaQYxd4XUW52
|
19
|
+
f0UTA6EgM65L4F+K6vBWD76vjHwO6Z+hF9BrVVvifuT1jNykZ/PoDncs4nZaQKFP
|
20
|
+
yCtrrfjq9WOVG+ueHSm1+7rWqxBO2jH95Nlyfe2t2Q27gOz4hpcU6tyCGEb5Liz/
|
21
|
+
za+SUVNKbv8kxVBoQYYDMyHgZeS5YN1qlkxXSjSrUAIpp4eUHxaKMo6lTcXPXRPA
|
22
|
+
CezHTFC1cn276L80YXTj0Gw2Jp9On2AJXifKZ11nlOs+gBSS32r8UiqptAGe97Py
|
23
|
+
PotM+fYUjH7yunVnvsPIN+EC08vAhXCrMfFnvCuuyeSv8KKUFxmIeZE1Fn29MooE
|
24
|
+
Qd6QI6SJGWQ918Vj1NE4Lo/EKtgl5opL4cVPRzrH7yH82oyQiI/7NiemwrMCAwEA
|
25
|
+
AaOBijCBhzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUaABOt2ER
|
26
|
+
TZ9I1b5uj7HkRf+YVr4wJgYDVR0RBB8wHYEbZ2VtbWFzdGVyQGphbWVzcm9iZXJ0
|
27
|
+
c29uLmV1MCYGA1UdEgQfMB2BG2dlbW1hc3RlckBqYW1lc3JvYmVydHNvbi5ldTAN
|
28
|
+
BgkqhkiG9w0BAQsFAAOCAYEABS1c63h+vQL2hjWs7BvQM6vFxp1T4RDvviUqLUBt
|
29
|
+
YAg1/vWquUZ0PVi+Hf9gAaSumDjBb7qbbkn3Y2j/aV7wpG/yFtBoknIqihp7oH7/
|
30
|
+
wqGlntx9baORy7chaaBRA4CB4gGUFQ0wYHCBrHmj9zvfFWXnnRoFa06JIHm2DmOB
|
31
|
+
41DwQiiLflNj4iYbLzNQSI5X0iRu3H8zcAp45HJNF2LBrY32b8U+4Uf1w9QOJ4Io
|
32
|
+
bXdjMDxNnHEj2+V2yaq4J8v0o/xEE0Qv2TEeXyiv2fvIRz5VsS3ayYv+rHVmxGuo
|
33
|
+
VuXOnyLlTUjeB0IakaSYdBFWW3uno+fds/mIBL9VtmZzPJ4UhirVs0t4GvftJ2oT
|
34
|
+
weBCjBPmFwYPtn66vFgOaUHK421yIA2FC+AQO/pOOSgngHz0pm08NMpcTeTaufKu
|
35
|
+
x9gWyaB0gatLOaqUuwj8jCICpzNLo20JZQyEav2hZDxdB1EQjxq9jZrMaxwW3lF/
|
36
|
+
zHoZFKaw47O+Nd14HCqMVZUt
|
32
37
|
-----END CERTIFICATE-----
|
33
|
-
date:
|
38
|
+
date: 2022-02-23 00:00:00.000000000 Z
|
34
39
|
dependencies:
|
35
40
|
- !ruby/object:Gem::Dependency
|
36
41
|
name: dynarex
|
@@ -38,22 +43,22 @@ dependencies:
|
|
38
43
|
requirements:
|
39
44
|
- - "~>"
|
40
45
|
- !ruby/object:Gem::Version
|
41
|
-
version: '1.
|
46
|
+
version: '1.9'
|
42
47
|
- - ">="
|
43
48
|
- !ruby/object:Gem::Version
|
44
|
-
version: 1.
|
49
|
+
version: 1.9.6
|
45
50
|
type: :runtime
|
46
51
|
prerelease: false
|
47
52
|
version_requirements: !ruby/object:Gem::Requirement
|
48
53
|
requirements:
|
49
54
|
- - "~>"
|
50
55
|
- !ruby/object:Gem::Version
|
51
|
-
version: '1.
|
56
|
+
version: '1.9'
|
52
57
|
- - ">="
|
53
58
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.
|
59
|
+
version: 1.9.6
|
55
60
|
description:
|
56
|
-
email:
|
61
|
+
email: digital.robertson@gmail.com
|
57
62
|
executables: []
|
58
63
|
extensions: []
|
59
64
|
extra_rdoc_files: []
|
@@ -78,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
83
|
- !ruby/object:Gem::Version
|
79
84
|
version: '0'
|
80
85
|
requirements: []
|
81
|
-
rubygems_version: 3.
|
86
|
+
rubygems_version: 3.2.22
|
82
87
|
signing_key:
|
83
88
|
specification_version: 4
|
84
89
|
summary: Reads a contacts.txt file
|
metadata.gz.sig
CHANGED
Binary file
|