blackstack_commons 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3aec128e1a1eec0e0a227cb1ce7c8ea7dec098ba
4
- data.tar.gz: 4c0d2d53a5496caae389469a135840d5e347035f
3
+ metadata.gz: e5f9a516f584be61a23ccf4a8e49cc5f62c0f8ca
4
+ data.tar.gz: a75e5f139c87961a3d03f1ea4d9e5c06fb2c060a
5
5
  SHA512:
6
- metadata.gz: b112efb7373ce759aa62bdf003c358d29a0d8a343f80609bb7d33587c2aa775b8764d0c74b2d94bccbabf3243eef9de8c244f432037c5223ced556f9dd478eb3
7
- data.tar.gz: e9151c5041d409ced876f294f4e4d0323d52974ba136bcb83cec3d8bf2e89e00ecc5965b4654e0ef572b8174eb142e6c9698147fdc519b5ed9505421a0b830c2
6
+ metadata.gz: 8491e3bc4478a58267fec9979dd823398d0cc1a3642db74933c19c764dd70ab32e6a10727f70694d070e18417db7b76b6559d01f138d5262a8d7c9ed4002c6e9
7
+ data.tar.gz: b68d4a2df8db3b240b016e80cb6366714e262f7a7eb9f4d56e28fe887bd970f760a373116c0cca9b6882d794de9f42bc8c07b91b66515472e1781df193df9427
@@ -0,0 +1,290 @@
1
+ require_relative '../lib/blackstack_commons'
2
+
3
+ # returns true if the string meets all the security requirements for a password
4
+ puts ""
5
+ puts "Passwords"
6
+ a = ['Hello', 'HelloWorld12$3']
7
+ a.each { |s|
8
+ print "'#{s}'.password?... "
9
+ puts s.password?.to_s
10
+ }
11
+
12
+ # returns true if the string match with the regex of a GUID
13
+ puts ""
14
+ puts "GUIDs"
15
+ a = [
16
+ '{331a92c3-5fe1-47a2-a31b-cfa439b5b4f9}',
17
+ '331a92c3-5fe1-47a2-a31b-cfa439b5b4f9',
18
+ '{331A92C3-5FE1-47A2-A31B-CFA439B5B4F9}',
19
+ '331A92C3-5FE1-47A2-A31B-CFA439B5B4F9',
20
+ '331A92C35FE147A2A31BCFA439B5B4F9',
21
+ ]
22
+ a.each { |s|
23
+ print "'#{s}'.guid?... "
24
+ puts s.guid?.to_s
25
+ }
26
+
27
+ # returns true if the string match with the regex of a filename
28
+ puts ""
29
+ puts "Filenames"
30
+ a = [
31
+ 'filename.txt',
32
+ 'filename',
33
+ 'filename.txt.rar',
34
+ ]
35
+ a.each { |s|
36
+ print "'#{s}'.filename?... "
37
+ puts s.filename?.to_s
38
+ }
39
+
40
+ # returns true if the string match with the regex of an email
41
+ puts ""
42
+ puts "Emails"
43
+ a = [
44
+ 'tango@expandedventure.com',
45
+ 'tango@expandedventure.com.ar',
46
+ 'tango',
47
+ 'tango@',
48
+ ]
49
+ a.each { |s|
50
+ print "'#{s}'.email?... "
51
+ puts s.email?.to_s
52
+ }
53
+
54
+ # returns true if the string match with the regex of a domain
55
+ puts ""
56
+ puts "Domains"
57
+ a = [
58
+ 'tango',
59
+ 'tango@expandedventure',
60
+ 'tango@expandedventure.com',
61
+ 'tango@expandedventure.com.ar',
62
+ 'expandedventure.com',
63
+ 'expandedventure.com.ar',
64
+ 'https://expandedventure.com.ar',
65
+ 'www.expandedventure.com.ar',
66
+ 'https://www.expandedventure.com.ar',
67
+ ]
68
+ a.each { |s|
69
+ print "'#{s}'.domain?... "
70
+ puts s.domain?.to_s
71
+ }
72
+
73
+ # returns true if the string match with the regex of a phone number
74
+ puts ""
75
+ puts "Domains"
76
+ a = [
77
+ '+54 9 11 5061 2148',
78
+ '545-5561-2148',
79
+ '545-561-2148',
80
+ '545 561 2148',
81
+ '54 545 561 2148',
82
+ '+54 545 561 2148',
83
+ '+54 545-561-2148',
84
+ '+54-545-561-2148',
85
+ ]
86
+ a.each { |s|
87
+ print "'#{s}'.domain?... "
88
+ puts s.phone?.to_s
89
+ }
90
+
91
+ # returns true if the string match with the regex of a URL
92
+ puts ""
93
+ puts "URLs"
94
+ a = [
95
+ 'tango',
96
+ 'tango@expandedventure',
97
+ 'tango@expandedventure.com',
98
+ 'tango@expandedventure.com.ar',
99
+ 'expandedventure.com',
100
+ 'expandedventure.com.ar',
101
+ 'https://expandedventure.com.ar',
102
+ 'www.expandedventure.com.ar',
103
+ 'https://www.expandedventure.com.ar',
104
+ ]
105
+ a.each { |s|
106
+ print "'#{s}'.url?... "
107
+ puts s.url?.to_s
108
+ }
109
+
110
+ # returns true if the string match with the regex of a number
111
+ puts ""
112
+ puts "Fixnums"
113
+ a = [
114
+ '5',
115
+ '5.5',
116
+ '5,5',
117
+ '5000',
118
+ '5,000',
119
+ '5.000',
120
+ ]
121
+ a.each { |s|
122
+ print "'#{s.to_s}'.fixnum?... "
123
+ puts s.fixnum?.to_s
124
+ }
125
+
126
+ # returns true if the string match with the regex of a datetime used in the BlackStack's API
127
+ puts ""
128
+ puts "SQL DateTimes"
129
+ a = [
130
+ '20191106215030',
131
+ '20191106',
132
+ '2019-11-06',
133
+ '2019-11-06 21:50:30',
134
+ '2019-13-06 21:50:30', # invalid month
135
+ '2019-11-06 25:50:30', # invalid hour
136
+ '2019-11-06 21:70:30', # invalid minute
137
+ '2019-11-06 21:50:70', # invalid second
138
+ ]
139
+ a.each { |s|
140
+ print "'#{s.to_s}'.sql_datetime?... "
141
+ puts s.sql_datetime?.to_s
142
+ }
143
+
144
+ #
145
+ puts ""
146
+ puts "API DateTimes"
147
+ a = [
148
+ '20191106215030',
149
+ '20191106',
150
+ '2019-11-06',
151
+ '2019-11-06 21:50:30',
152
+ '20191306215030', # invalid month
153
+ '20191106255030', # invalid hour
154
+ '20191106217030', # invalid minute
155
+ '20191106215070', # invalid second
156
+ ]
157
+ a.each { |s|
158
+ print "'#{s.to_s}'.api_datetime?... "
159
+ puts s.api_datetime?.to_s
160
+ }
161
+
162
+ # Convierte un string con formato sql-datatime a un string con formato sql-datetime.
163
+ puts ""
164
+ puts "SQL DateTime -> API DateTime"
165
+ a = [
166
+ '2019-11-06 21:50:30',
167
+ ]
168
+ a.each { |s|
169
+ print "'#{s.to_s}'.sql_to_api_datetime... "
170
+ puts s.sql_to_api_datetime.to_s
171
+ }
172
+
173
+ # Convierte un string con formato api-datatime (yyyymmddhhmmss) a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
174
+ puts ""
175
+ puts "API DateTime -> SQL DateTime"
176
+ a = [
177
+ '20191106215030',
178
+ ]
179
+ a.each { |s|
180
+ print "'#{s.to_s}'.api_to_sql_datetime... "
181
+ puts s.api_to_sql_datetime.to_s
182
+ }
183
+
184
+ # Rewrite a GUID as a standard (normalized) format.
185
+ puts ""
186
+ puts "Any GUID -> Normalized Guid"
187
+ a = [
188
+ '{331a92c3-5fe1-47a2-a31b-cfa439b5b4f9}',
189
+ '331a92c3-5fe1-47a2-a31b-cfa439b5b4f9',
190
+ '{331A92C3-5FE1-47A2-A31B-CFA439B5B4F9}',
191
+ '331A92C3-5FE1-47A2-A31B-CFA439B5B4F9',
192
+ ]
193
+ a.each { |s|
194
+ print "'#{s}'.to_guid... "
195
+ puts s.to_guid.to_s
196
+ }
197
+
198
+ # Escape simple-quotes too add the string into literal-string of a dynamic query build into the Ruby code.
199
+ # Example: "I'm BlackStack" -> "I''m BlackStack"
200
+ puts ""
201
+ puts "Any String -> String with Escaped Quotes"
202
+ a = [
203
+ "I'm BlackStack",
204
+ "Hello World!",
205
+ ]
206
+ a.each { |s|
207
+ print "'#{s}'.to_sql... "
208
+ puts s.to_sql.to_s
209
+ }
210
+
211
+ #
212
+ puts ""
213
+ puts "Spintax"
214
+ a = [
215
+ "I'm BlackStack",
216
+ "Hello World!",
217
+ "{Hello|Hi} World!",
218
+ "{Hello|Hi|Good {Morning|Afternoon}} World!", # Nexted spintax. Not supported.
219
+ "{Hello|Hi World!", # wrong syntax.
220
+ ]
221
+ a.each { |s|
222
+ print "'#{s}'.spintax?... "
223
+ puts s.spintax?.to_s
224
+ }
225
+
226
+ # Returns a random spin from a spintax
227
+ puts ""
228
+ puts "Spin"
229
+ a = [
230
+ "{Hello|Hi|Good Morning|Good Afternoon} World!",
231
+ "{Hello|Hi|Good Morning|Good Afternoon} World!",
232
+ "{Hello|Hi|Good Morning|Good Afternoon} World!",
233
+ "{Hello|Hi|Good Morning|Good Afternoon} World!",
234
+ ]
235
+ a.each { |s|
236
+ print "'#{s}'.spin... "
237
+ puts s.spin
238
+ }
239
+
240
+ # Converts a time object to an SQL friendy string
241
+ puts ""
242
+ puts "Time object -> SQL"
243
+ a = [
244
+ Time.new(2019,11,6,15,25,55),
245
+ DateTime.new(2019,11,6,15,25,55),
246
+ ]
247
+ a.each { |o|
248
+ print "'#{o.to_s}'.to_sql... "
249
+ puts o.to_sql
250
+ }
251
+
252
+ # Converts number to a string with a format like xx,xxx,xxx.xxxx
253
+ puts ""
254
+ puts "Fixnum & Floats -> Screen Friendly Text"
255
+ a = [
256
+ 64443,
257
+ 64443.5454,
258
+ ]
259
+ a.each { |i|
260
+ print "'#{i.to_s}'.to_label... "
261
+ puts i.to_label
262
+ }
263
+
264
+ # Converts number to a string with a format like xx,xxx,xxx.xxxx
265
+ puts ""
266
+ puts "Fixnum Minutes -> Time Spent (days, hours, minutes)"
267
+ a = [
268
+ 59,
269
+ 60,
270
+ 61,
271
+ 600,
272
+ 601,
273
+ 1440,
274
+ 1441,
275
+ 1500,
276
+ 1501,
277
+ ]
278
+ a.each { |i|
279
+ print "Minutes '#{i.to_s}'.to_time_spent... "
280
+ puts i.to_time_spent
281
+ }
282
+
283
+
284
+ =begin # TODO: Pending
285
+ encode_string
286
+ encode_html
287
+ encode_exception
288
+ encode_period
289
+ encode_javascript
290
+ =end
@@ -0,0 +1,3 @@
1
+ require_relative '../lib/blackstack_commons'
2
+
3
+ BlackStack::Netting::api_call('https://connectionsphere.com/api1.4/ping.json')
data/lib/datetime.rb ADDED
@@ -0,0 +1,6 @@
1
+ class DateTime
2
+ # Converts a time object to an SQL friendy string
3
+ def to_sql()
4
+ BlackStack::DateTime::Encoding::datetime_to_sql(self)
5
+ end
6
+ end # class DateTime
data/lib/exception.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Exception
2
+ def to_html
3
+ BlackStack::Strings::Encoding.encode_exception(self)
4
+ end
5
+ end
data/lib/fixnum.rb ADDED
@@ -0,0 +1,14 @@
1
+ class Fixnum
2
+ # Converts number to a string with a format like xx,xxx,xxx.xxxx
3
+ def to_label()
4
+ BlackStack::Number::Encoding::format_with_separator(self)
5
+ end
6
+
7
+ # Convierte una cantidad de minutos a una leyenda legible por el usuario.
8
+ # Ejemplo: "2 days, 5 hours"
9
+ # Ejemplo: "4 hours, 30 minutes"
10
+ # Ejemplo: "3 days, 4 hour"
11
+ def to_time_spent()
12
+ BlackStack::Number::Encoding::encode_minutes(self)
13
+ end
14
+ end # class String
data/lib/float.rb ADDED
@@ -0,0 +1,6 @@
1
+ class Float
2
+ # Converts number to a string with a format like xx,xxx,xxx.xxxx
3
+ def to_label()
4
+ BlackStack::Number::Encoding::format_with_separator(self)
5
+ end
6
+ end # class String
data/lib/functions.rb ADDED
@@ -0,0 +1,555 @@
1
+ module BlackStack
2
+ # -----------------------------------------------------------------------------------------
3
+ # DateTime Functions
4
+ # -----------------------------------------------------------------------------------------
5
+ module DateTime
6
+ # -----------------------------------------------------------------------------------------
7
+ # Encoding
8
+ # -----------------------------------------------------------------------------------------
9
+ module Encoding
10
+ # Convierte un objeto date-time a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
11
+ def self.datetime_to_sql(o)
12
+ return o.strftime("%Y-%m-%d %H:%M:%S")
13
+ end
14
+ end # module Encode
15
+
16
+ # -----------------------------------------------------------------------------------------
17
+ # Miscelaneous
18
+ # -----------------------------------------------------------------------------------------
19
+ module Misc
20
+ def self.datetime_values_check(year,month,day,hour,minute,second)
21
+ if (year.to_i<1900 || year.to_i>=2100)
22
+ return false
23
+ end
24
+
25
+ if (month.to_i<1 || month.to_i>12)
26
+ return false
27
+ end
28
+
29
+ # TODO: Considerar la cantidad de dias de cada mes, y los anios biciestos. Buscar alguna funcion existente.
30
+ if (day.to_i<1 || day.to_i>31)
31
+ return false
32
+ end
33
+
34
+ if (hour.to_i<0 || hour.to_i>23)
35
+ return false
36
+ end
37
+
38
+ if (minute.to_i<0 || minute.to_i>59)
39
+ return false
40
+ end
41
+
42
+ if (second.to_i<0 || second.to_i>59)
43
+ return false
44
+ end
45
+
46
+ return true
47
+ end # datetime_values_check
48
+ end # module Misc
49
+ end # module DateTime
50
+
51
+ # -----------------------------------------------------------------------------------------
52
+ # Numeric Functions
53
+ # -----------------------------------------------------------------------------------------
54
+ module Number
55
+ # -----------------------------------------------------------------------------------------
56
+ # Encoding
57
+ # -----------------------------------------------------------------------------------------
58
+ module Encoding
59
+ # Converts number to a string with a format like xx,xxx,xxx.xxxx
60
+ # number: it may be int or float
61
+ def self.format_with_separator(number)
62
+ whole_part, decimal_part = number.to_s.split('.')
63
+ [whole_part.gsub(/(\d)(?=\d{3}+$)/, '\1,'), decimal_part].compact.join('.')
64
+ end
65
+
66
+ # Convierte una cantidad de minutos a una leyenda legible por el usuario.
67
+ # Ejemplo: "2 days, 5 hours"
68
+ # Ejemplo: "4 hours, 30 minutes"
69
+ # Ejemplo: "3 days, 4 hour"
70
+ def self.encode_minutes(n)
71
+ # TODO: validar que n sea un entero mayor a 0
72
+ if (n<0)
73
+ return "?"
74
+ end
75
+ if (n<60)
76
+ return "#{n} minutes"
77
+ elsif (n<24*60)
78
+ return "#{(n/60).to_i} hours, #{n-60*(n/60).to_i} minutes"
79
+ else
80
+ return "#{(n/(24*60)).to_i} days, #{((n-24*60*(n/(24*60)).to_i)/60).to_i} hours"
81
+ end
82
+ end
83
+ end # module Encode
84
+ end # module Number
85
+
86
+ # -----------------------------------------------------------------------------------------
87
+ # String Functions
88
+ # -----------------------------------------------------------------------------------------
89
+ module Strings
90
+
91
+ GUID_SIZE = 36
92
+ MATCH_PASSWORD = /^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$/
93
+ MATCH_GUID = /[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]\-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]/
94
+ MATCH_FILENAME = /^[\w,\s-]+\.[A-Za-z]{3}$/
95
+ MATCH_EMAIL = /[A-Z0-9._%a-z\-]+@(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}/
96
+ MATCH_DOMAIN = /(?:[A-Z0-9a-z\-]+\.)+[A-Za-z]{2,4}/
97
+ MATCH_DATE_STANDARD = /^\d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])$/
98
+ MATCH_PHONE = /(?:\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}/
99
+ MATCH_URL = /(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/ # /(?:\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}/
100
+ MATCH_LINKEDIN_COMPANY_URL = /(https?:\/\/)?(www\\.)?linkedin\.com\/company\//
101
+ MATCH_FIXNUM = /^[0-9]+$/
102
+ MATCH_CONTENT_SPINNING = /{[^}]+}/
103
+ MATCH_SPINNED_TEXT = /code me/ # TODO: define this regex for the issue #1226
104
+
105
+ # -----------------------------------------------------------------------------------------
106
+ # Fuzzy String Comparsion Functions: How similar are 2 strings that are not exactly equal.
107
+ # -----------------------------------------------------------------------------------------
108
+ module SQL
109
+ def self.string_to_sql_string(s)
110
+ #return s.force_encoding("UTF-8").gsub("'", "''").to_s
111
+ return s.gsub("'", "''").to_s
112
+ end
113
+ end
114
+
115
+ # -----------------------------------------------------------------------------------------
116
+ # Fuzzy String Comparsion Functions: How similar are 2 strings that are not exactly equal.
117
+ # -----------------------------------------------------------------------------------------
118
+ module Comparing
119
+ # retorna 0 si los strings son iguales
120
+ # https://stackoverflow.com/questions/16323571/measure-the-distance-between-two-strings-with-ruby
121
+ def self.levenshtein_distance(s, t)
122
+ s.downcase!
123
+ t.downcase!
124
+
125
+ m = s.length
126
+ n = t.length
127
+ return m if n == 0
128
+ return n if m == 0
129
+ d = Array.new(m+1) {Array.new(n+1)}
130
+
131
+ (0..m).each {|i| d[i][0] = i}
132
+ (0..n).each {|j| d[0][j] = j}
133
+ (1..n).each do |j|
134
+ (1..m).each do |i|
135
+ d[i][j] = if s[i-1] == t[j-1] # adjust index into string
136
+ d[i-1][j-1] # no operation required
137
+ else
138
+ [ d[i-1][j]+1, # deletion
139
+ d[i][j-1]+1, # insertion
140
+ d[i-1][j-1]+1, # substitution
141
+ ].min
142
+ end
143
+ end
144
+ end
145
+ d[m][n]
146
+ end
147
+
148
+ # retorna la cantidad de palabras con mas de 3 caracteres que se encuentran en el parametro s
149
+ def self.max_sardi_distance(s)
150
+ s.downcase!
151
+ s.gsub!(/-/,' ')
152
+ ss = s.scan(/\b([a-z]+)\b/)
153
+ n = 0
154
+ ss.each { |x|
155
+ x = x[0]
156
+ if (x.size > 3) # para evitar keywords triviales como 'and'
157
+ n += 1
158
+ end
159
+ }
160
+ n
161
+ end
162
+
163
+ # retorna la cantidad de palabras con mas de 3 caracteres del parametro s que se encuentran en el parametro t
164
+ def self.sardi_distance(s, t)
165
+ s.downcase!
166
+ t.downcase!
167
+ s.gsub!(/-/,' ')
168
+ t.gsub!(/-/,' ')
169
+ max_distance = max_sardi_distance(s)
170
+ ss = s.scan(/\b([a-z]+)\b/)
171
+ tt = t.scan(/\b([a-z]+)\b/)
172
+ n = 0
173
+ ss.each { |x|
174
+ x = x[0]
175
+ if (x.size > 3) # para evitar keywords triviales como 'and'
176
+ if ( tt.select { |y| y[0] == x }.size > 0 )
177
+ n += 1
178
+ end
179
+ end
180
+ }
181
+ return max_distance - n
182
+ end
183
+ end # module Comparing
184
+
185
+ # -----------------------------------------------------------------------------------------
186
+ # Encoding: Make a string nice to be shown into an HTML string.
187
+ # -----------------------------------------------------------------------------------------
188
+ module Encoding
189
+ # Then it makes it compatible with UTF-8.
190
+ # More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
191
+ def self.encode_string(s)
192
+ s.encode("UTF-8")
193
+ end
194
+
195
+ # Escape the string to be shown into an HTML screen.
196
+ # Then it makes it compatible with UTF-8.
197
+ # More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
198
+ def self.encode_html(s)
199
+ encode_string(CGI.escapeHTML(s.to_s))
200
+ end
201
+
202
+ # Generates a description string from an exception object.
203
+ # Eescapes the string to be shown into an HTML screen.
204
+ # Makes it compatible with UTF-8.
205
+ # More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
206
+ def self.encode_exception(e, include_backtrace=true)
207
+ ret = 'Error:' + encode_html(e.to_s)
208
+ if (include_backtrace == true)
209
+ e.backtrace.each { |s|
210
+ ret += "<br/>" + encode_html(s)
211
+ } # e.backtrace.each
212
+ end # if
213
+ ret
214
+ end
215
+
216
+ # Returns a string with a description of a period of time, to be shown in the screen.
217
+ # period: it may be 'H', 'D', 'W', 'M', 'Y'
218
+ # units: it is a positive integer
219
+ def self.encode_period(period, units)
220
+ s = "Last "
221
+ s += units.to_s + " " if units.to_i > 1
222
+ s += "Hours" if period.upcase == "H" && units.to_i != 1
223
+ s += "Days" if period.upcase == "D" && units.to_i != 1
224
+ s += "Weeks" if period.upcase == "W" && units.to_i != 1
225
+ s += "Months" if period.upcase == "M" && units.to_i != 1
226
+ s += "Years" if period.upcase == "Y" && units.to_i != 1
227
+ s += "Hour" if period.upcase == "H" && units.to_i == 1
228
+ s += "Day" if period.upcase == "D" && units.to_i == 1
229
+ s += "Week" if period.upcase == "W" && units.to_i == 1
230
+ s += "Month" if period.upcase == "M" && units.to_i == 1
231
+ s += "Year" if period.upcase == "Y" && units.to_i == 1
232
+ s
233
+ end
234
+
235
+ #
236
+ def self.encode_guid(s)
237
+ return s.gsub('{',"").gsub('}',"").upcase
238
+ end
239
+
240
+ #
241
+ def self.encode_javascript(s)
242
+ s.to_s.gsub("'", "\\\\'").gsub("\r", "' + String.fromCharCode(13) + '").gsub("\n", "' + String.fromCharCode(10) + '")
243
+ end
244
+
245
+ end # module Encoding
246
+
247
+ # -----------------------------------------------------------------------------------------
248
+ # DateTime
249
+ # -----------------------------------------------------------------------------------------
250
+ module DateTime
251
+ # Check the string has the format yyyymmddhhmmss.
252
+ # => Return true if success. Otherwise, return false.
253
+ # => Year cannot be lower than 1900.
254
+ # => Year cannot be higher or equal than 2100.
255
+ def self.datetime_api_check(s)
256
+ return false if (s.size!=14)
257
+ year = s[0..3]
258
+ month = s[4..5]
259
+ day = s[6..7]
260
+ hour = s[8..9]
261
+ minute = s[10..11]
262
+ second = s[12..13]
263
+ BlackStack::DateTime::Misc::datetime_values_check(year,month,day,hour,minute,second)
264
+ end # def datetime_api_check
265
+
266
+ # Check the string has the format yyyy-mm-dd hh:mm:ss.
267
+ # => Return true if success. Otherwise, return false.
268
+ # => Year cannot be lower than 1900.
269
+ # => Year cannot be higher or equal than 2100.
270
+ def self.datetime_sql_check(s)
271
+ return false if (s.size!=19)
272
+ year = s[0..3]
273
+ month = s[5..6]
274
+ day = s[8..9]
275
+ hour = s[11..12]
276
+ minute = s[14..15]
277
+ second = s[17..18]
278
+ BlackStack::DateTime::Misc::datetime_values_check(year,month,day,hour,minute,second)
279
+ end # def datetime_sql_check
280
+
281
+ # Convierte un string con formato api-datatime (yyyymmddhhmmss) a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
282
+ def self.datetime_api_to_sql(s)
283
+ raise "Wrong Api DataTime Format." if (datetime_api_check(s)==false)
284
+ year = s[0..3]
285
+ month = s[4..5]
286
+ day = s[6..7]
287
+ hour = s[8..9]
288
+ minute = s[10..11]
289
+ second = s[12..13]
290
+ ret = "#{year}-#{month}-#{day} #{hour}:#{minute}:#{second}"
291
+ return ret
292
+ end # def datetime_api_to_sql
293
+
294
+ # Convierte un string con formato sql-datatime a un string con formato sql-datetime.
295
+ def self.datetime_sql_to_api(s)
296
+ raise "Wrong SQL DataTime Format." if (datetime_sql_check(s)==false)
297
+ year = s[0..3]
298
+ month = s[5..6]
299
+ day = s[8..9]
300
+ hour = s[11..12]
301
+ minute = s[14..15]
302
+ second = s[17..18]
303
+ ret = "#{year}#{month}#{day}#{hour}#{minute}#{second}"
304
+ return ret
305
+ end # def datetime_sql_to_api
306
+ end # module DateTime
307
+
308
+
309
+ # -----------------------------------------------------------------------------------------
310
+ # Spinning
311
+ # -----------------------------------------------------------------------------------------
312
+ module Spinning
313
+ # Esta funcion retorna una variacion al azar del texto que se pasa.
314
+ # Esta funcion se ocupa de dividir el texto en partes, para eviar el error "too big to product" que arroja la libraría.
315
+ def self.random_spinning_variation(text)
316
+ ret = text
317
+
318
+ text.scan(MATCH_CONTENT_SPINNING).each { |s|
319
+ a = ContentSpinning.new(s).spin
320
+ rep = a[rand(a.size)]
321
+ ret = ret.gsub(s, rep)
322
+ a = nil
323
+ }
324
+
325
+ return ret
326
+ end
327
+
328
+ # retorna true si la sintaxis del texto spineado es correcta
329
+ # caso contrario retorna false
330
+ # no soporta spinnings anidados. ejemplo: {my|our|{a car of mine}}
331
+ def self.valid_spinning_syntax?(s)
332
+ # valido que exste
333
+ n = 0
334
+ s.split('').each { |c|
335
+ n+=1 if c=='{'
336
+ n-=1 if c=='}'
337
+ if n!=0 && n!=1
338
+ #raise "Closing spining char '}' with not previous opening spining char '{'." if n<0
339
+ #raise "Opening spining char '{' inside another spining block." if n>1
340
+ return false if n<0 # Closing spining char '}' with not previous opening spining char '{'.
341
+ return false if n>1 # Opening spining char '{' inside another spining block.
342
+ end
343
+ }
344
+
345
+ # obtengo cada uno de los spinnings
346
+ s.scan(MATCH_CONTENT_SPINNING).each { |x|
347
+ a = x.split('|')
348
+ raise "No variations delimited by '|' inside spinning block." if a.size <= 1
349
+ }
350
+
351
+ true
352
+ end
353
+
354
+ # returns true if the text is spinned.
355
+ # otherwise, returns false.
356
+ def self.spintax?(s)
357
+ s.scan(MATCH_CONTENT_SPINNING).size > 0
358
+ end
359
+ end # module Spinning
360
+
361
+
362
+ # -----------------------------------------------------------------------------------------
363
+ # Miscelaneus
364
+ # -----------------------------------------------------------------------------------------
365
+ module Misc
366
+ # make a Ruby string safe for a filesystem.
367
+ # References:
368
+ # => https://stackoverflow.com/questions/1939333/how-to-make-a-ruby-string-safe-for-a-filesystem
369
+ # => http://devblog.muziboo.com/2008/06/17/attachment-fu-sanitize-filename-regex-and-unicode-gotcha/
370
+ def self.sanitize_filename(filename)
371
+ ret = filename.strip do |name|
372
+ # NOTE: File.basename doesn't work right with Windows paths on Unix
373
+ # get only the filename, not the whole path
374
+ name.gsub!(/^.*(\\|\/)/, '')
375
+
376
+ # Strip out the non-ascii character
377
+ name.gsub!(/[^0-9A-Za-z.\-]/, '_')
378
+ end
379
+ return ret
380
+ end
381
+ end # module Misc
382
+
383
+
384
+ # -----------------------------------------------------------------------------------------
385
+ # Email Appending Functions
386
+ # -----------------------------------------------------------------------------------------
387
+ module Appending
388
+ APPEND_PATTERN_FNAME_DOT_LNAME = 0
389
+ APPEND_PATTERN_FNAME = 1
390
+ APPEND_PATTERN_LNAME = 2
391
+ APPEND_PATTERN_F_LNAME = 3
392
+ APPEND_PATTERN_F_DOT_LNAME = 4
393
+
394
+ #
395
+ def self.name_pattern(pattern, fname, lname)
396
+ if (pattern==APPEND_PATTERN_FNAME_DOT_LNAME)
397
+ return "#{fname}.#{lname}"
398
+ elsif (pattern==APPEND_PATTERN_FNAME)
399
+ return "#{fname}"
400
+ elsif (pattern==APPEND_PATTERN_LNAME)
401
+ return "#{lname}"
402
+ elsif (pattern==APPEND_PATTERN_F_LNAME)
403
+ return "#{fname[0]}#{lname}"
404
+ elsif (pattern==APPEND_PATTERN_F_DOT_LNAME)
405
+ return "#{fname[0]}.#{lname}"
406
+ else
407
+ raise "getNamePattern: Unknown pattern code."
408
+ end
409
+ end
410
+
411
+ #
412
+ def self.get_email_variations(first_name, last_name, domain, is_a_big_company)
413
+ variations = Array.new
414
+ variations << first_name + "." + last_name + "@" + domain
415
+ variations << first_name[0] + last_name + "@" + domain
416
+ variations << first_name + "_" + last_name + "@" + domain
417
+ variations << first_name[0] + "." + last_name + "@" + domain
418
+ if (is_a_big_company == false)
419
+ variations << last_name + "@" + domain
420
+ variations << first_name + "@" + domain
421
+ end
422
+ #variations << first_name + "." + last_name + "@" + domain
423
+ #variations << first_name + "_" + last_name + "@" + domain
424
+ #variations << last_name + "." + first_name + "@" + domain
425
+ #variations << last_name + "_" + first_name + "@" + domain
426
+ #variations << first_name[0] + "." + last_name + "@" + domain
427
+ #variations << first_name + "." + last_name[0] + "@" + domain
428
+ #variations << last_name[0] + "." + first_name + "@" + domain
429
+ #variations << last_name + "." + first_name[0] + "@" + domain
430
+ #variations << first_name[0] + last_name + "@" + domain
431
+ #variations << first_name + last_name[0] + "@" + domain
432
+ #variations << last_name[0] + first_name + "@" + domain
433
+ #variations << last_name + first_name[0] + "@" + domain
434
+ #variations << first_name + "@" + domain
435
+ #variations << last_name + "@" + domain
436
+ return variations
437
+ end
438
+ end # module Appending
439
+ end # module String
440
+
441
+ # -----------------------------------------------------------------------------------------
442
+ # Network
443
+ # -----------------------------------------------------------------------------------------
444
+ module Netting
445
+ CALL_METHOD_GET = 'get'
446
+ CALL_METHOD_POST = 'post'
447
+ DEFAULT_SSL_VERIFY_MODE = OpenSSL::SSL::VERIFY_NONE
448
+ SUCCESS = 'success'
449
+
450
+ # New call_get
451
+ def self.call_get(uri, params = {}, ssl_verify_mode=BlackStack::Netting::DEFAULT_SSL_VERIFY_MODE)
452
+ uri.query = URI.encode_www_form(params)
453
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', :verify_mode => ssl_verify_mode) do |http|
454
+ req = Net::HTTP::Get.new uri
455
+ res = http.request req
456
+ case res
457
+ when Net::HTTPSuccess then res
458
+ when Net::HTTPRedirection then BlackStack::Netting::call_get(URI(res['location']), params)
459
+ else
460
+ res.error!
461
+ end
462
+ end
463
+ end
464
+
465
+ # New call_post
466
+ def self.call_post(uri, params = {}, ssl_verify_mode=BlackStack::Netting::DEFAULT_SSL_VERIFY_MODE)
467
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https', :verify_mode => ssl_verify_mode) do |http|
468
+ req = Net::HTTP::Post.new(uri)
469
+ req['Content-Type'] = 'application/json'
470
+ req.set_form_data(params)
471
+ res = http.request req
472
+ case res
473
+ when Net::HTTPSuccess then res
474
+ when Net::HTTPRedirection then BlackStack::Netting::call_post(URI(res['location']), params)
475
+ else
476
+ res.error!
477
+ end
478
+ end
479
+ end
480
+
481
+ #
482
+ def self.api_call(url, params={}, method=BlackStack::Netting::CALL_METHOD_POST, ssl_verify_mode=BlackStack::Netting::DEFAULT_SSL_VERIFY_MODE, max_retries=5)
483
+ nTries = 0
484
+ bSuccess = false
485
+ parsed = nil
486
+ sError = ""
487
+ while (nTries < max_retries && bSuccess == false)
488
+ begin
489
+ nTries = nTries + 1
490
+ uri = URI(url)
491
+ res = BlackStack::Netting::call_post(uri, params, ssl_verify_mode) if method==BlackStack::Netting::CALL_METHOD_POST
492
+ res = BlackStack::Netting::call_get(uri, params, ssl_verify_mode) if method==BlackStack::Netting::CALL_METHOD_GET
493
+ parsed = JSON.parse(res.body)
494
+ if (parsed['status']==BlackStack::Netting::SUCCESS)
495
+ bSuccess = true
496
+ else
497
+ sError = "Status: #{parsed['status'].to_s}. Description: #{parsed['value'].to_s}."
498
+ end
499
+ rescue Errno::ECONNREFUSED => e
500
+ sError = "Errno::ECONNREFUSED:" + e.to_s
501
+ rescue => e2
502
+ sError = "Exception:" + e2.to_s
503
+ end
504
+ end # while
505
+
506
+ if (bSuccess==false)
507
+ raise "#{sError}"
508
+ end
509
+ end # apicall
510
+
511
+ # Download a file from an url to a local folder.
512
+ # url: must be somedomain.net instead of somedomain.net/, otherwise, it will throw exception.
513
+ # to: must be a valid path to a folder.
514
+ def self.download(url, to)
515
+ uri = URI(url)
516
+ domain = uri.host.start_with?('www.') ? uri.host[4..-1] : uri.host
517
+ path = uri.path
518
+ filename = path.split("/").last
519
+ Net::HTTP.start(domain) do |http|
520
+ resp = http.get(path)
521
+ open(to, "wb") do |file|
522
+ file.write(resp.body)
523
+ end
524
+ end
525
+ end
526
+
527
+ # Return the extension of the last path into an URL.
528
+ # Example: get_url_extension("http://connect.data.com/sitemap_index.xml?foo_param=foo_value") => ".xml"
529
+ def self.get_url_extension(url)
530
+ return File.extname(URI.parse(url).path.to_s)
531
+ end
532
+
533
+ # Removes the 'www.' from an URL.
534
+ def self.get_host_without_www(url)
535
+ url = "http://#{url}" if URI.parse(url).scheme.nil?
536
+ host = URI.parse(url).host.downcase
537
+ host.start_with?('www.') ? host[4..-1] : host
538
+ end
539
+
540
+ # Get the final URL if a web page is redirecting.
541
+ def self.get_redirect(url)
542
+ uri = URI.parse(url)
543
+ protocol = uri.scheme
544
+ host = uri.host.downcase
545
+ res = Net::HTTP.get_response(uri)
546
+ "#{protocol}://#{host}#{res['location']}"
547
+ end
548
+
549
+ # returns the age in days of the given file
550
+ def self.file_age(filename)
551
+ (Time.now - File.ctime(filename))/(24*3600)
552
+ end
553
+ end # module Netting
554
+
555
+ end # module BlackStack
data/lib/string.rb ADDED
@@ -0,0 +1,115 @@
1
+ class String
2
+ # returns true if the string meets all the security requirements for a password
3
+ def password?
4
+ return true if self.to_s =~ BlackStack::Strings::MATCH_PASSWORD
5
+ return false
6
+ end
7
+
8
+ # returns true if the string match with the regex of a GUID
9
+ def guid?
10
+ return true if self.to_s =~ BlackStack::Strings::MATCH_GUID
11
+ return false
12
+ end
13
+
14
+ # returns true if the string match with the regex of a filename
15
+ def filename?
16
+ return true if self.to_s =~ BlackStack::Strings::MATCH_FILENAME
17
+ return false
18
+ end
19
+
20
+ # returns true if the string match with the regex of an email
21
+ def email?
22
+ return true if self.to_s =~ BlackStack::Strings::MATCH_EMAIL
23
+ return false
24
+ end
25
+
26
+ # returns true if the string match with the regex of a domain
27
+ def domain?
28
+ return true if self.to_s =~ BlackStack::Strings::MATCH_DOMAIN
29
+ return false
30
+ end
31
+
32
+ # returns true if the string match with the regex of a phone number
33
+ def phone?
34
+ return true if self.to_s =~ BlackStack::Strings::MATCH_PHONE
35
+ return false
36
+ end
37
+
38
+ # returns true if the string match with the regex of a URL
39
+ def url?
40
+ return true if self.to_s =~ BlackStack::Strings::MATCH_URL
41
+ return false
42
+ end
43
+
44
+ # returns true if the string match with the regex of a number
45
+ def fixnum?
46
+ return true if self.to_s =~ BlackStack::Strings::MATCH_FIXNUM
47
+ return false
48
+ end
49
+
50
+ # returns true if the string match with the regex of a datetime used in the BlackStack's API
51
+ def api_datetime?
52
+ BlackStack::Strings::DateTime::datetime_api_check(self.to_s)
53
+ end
54
+
55
+ #
56
+ def sql_datetime?
57
+ BlackStack::Strings::DateTime::datetime_sql_check(self.to_s)
58
+ end
59
+
60
+ # Convierte un string con formato sql-datatime a un string con formato sql-datetime.
61
+ def sql_to_api_datetime
62
+ BlackStack::Strings::DateTime::datetime_sql_to_api(self.to_s)
63
+ end
64
+
65
+ # Convierte un string con formato api-datatime (yyyymmddhhmmss) a un string con formato sql-datetime (yyyy-mm-dd hh:mm:ss).
66
+ def api_to_sql_datetime
67
+ BlackStack::Strings::DateTime::datetime_api_to_sql(self.to_s)
68
+ end
69
+
70
+ # Rewrite a GUID as a standard format.
71
+ # Example: {331a92c3-5fe1-47a2-a31b-cfa439b5b4f9} -> 331A92C3-5FE1-47A2-A31B-CFA439B5B4F9
72
+ def to_guid
73
+ BlackStack::Strings::Encoding::encode_guid(self.to_s)
74
+ end
75
+
76
+ # Escape simple-quotes too add the string into literal-string of a dynamic query build into the Ruby code.
77
+ # Example: "I'm BlackStack" -> "I''m BlackStack"
78
+ def to_sql
79
+ BlackStack::Strings::SQL::string_to_sql_string(self.to_s)
80
+ end
81
+
82
+ #
83
+ def spintax?
84
+ BlackStack::Strings::Spinning::spintax?(self.to_s)
85
+ end
86
+
87
+ #
88
+ def spintax?
89
+ BlackStack::Strings::Spinning::valid_spinning_syntax?(self.to_s) &&
90
+ BlackStack::Strings::Spinning::spintax?(self.to_s)
91
+ end
92
+
93
+ # Returns a random spin from a spintax
94
+ def spin
95
+ BlackStack::Strings::Spinning::random_spinning_variation(self.to_s)
96
+ end
97
+
98
+ # Then it makes it compatible with UTF-8.
99
+ # More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
100
+ def encode_string()
101
+ BlackStack::Strings::Encoding::encode_string(self.to_s)
102
+ end
103
+
104
+ # Escape the string to be shown into an HTML screen.
105
+ # Then it makes it compatible with UTF-8.
106
+ # More details here: https://bitbucket.org/leandro_sardi/blackstack/issues/961
107
+ def encode_html()
108
+ BlackStack::Strings::Encoding::encode_html(self.to_s)
109
+ end
110
+
111
+ end # class String
112
+
113
+ #i.to_label
114
+
115
+ #dt.to_sql
data/lib/time.rb ADDED
@@ -0,0 +1,6 @@
1
+ class Time
2
+ # Converts a time object to an SQL friendy string
3
+ def to_sql()
4
+ BlackStack::DateTime::Encoding::datetime_to_sql(self)
5
+ end
6
+ end # class DateTime
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blackstack_commons
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leandro Daniel Sardi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-06 00:00:00.000000000 Z
11
+ date: 2019-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: content_spinning
@@ -56,7 +56,16 @@ executables: []
56
56
  extensions: []
57
57
  extra_rdoc_files: []
58
58
  files:
59
+ - examples/example01.rb
60
+ - examples/example02.rb
59
61
  - lib/blackstack_commons.rb
62
+ - lib/datetime.rb
63
+ - lib/exception.rb
64
+ - lib/fixnum.rb
65
+ - lib/float.rb
66
+ - lib/functions.rb
67
+ - lib/string.rb
68
+ - lib/time.rb
60
69
  homepage: https://rubygems.org/gems/blackstack_commons
61
70
  licenses:
62
71
  - MIT