arquivo 0.2.2 → 0.2.3
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/lib/arquivo.rb +1 -1
- data/lib/arquivo/dir.rb +17 -28
- data/lib/arquivo/extrato.rb +1 -1
- data/lib/arquivo/jpg.rb +22 -21
- data/lib/arquivo/mp3.rb +1 -1
- data/lib/arquivo/noise.rb +65 -31
- data/lib/arquivo/pdf.rb +2 -1
- data/lib/arquivo/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cb7ecf71153002b263d88303a43e2c298d9afc9a25bf1ff996c18016c60dc6eb
|
|
4
|
+
data.tar.gz: 9304605a85684d6572891709c48082bf730d38ddc8c273a614ad5052a04596c3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00aaddf208d5ab5123858c2ea52105b2c18495e35e398059c17b982a082fcdc80762a5d6d8f75bfa43e2cc5faeb6b0b68fc7ec05c91934e1620e35f6eec4a36f
|
|
7
|
+
data.tar.gz: 2c5f2f72098327bc4fee7df75281e5a55ded17058af3af633527750ecc04250ede81f4b06bb575d2be9b0854b73834ec10d44dfa2f1b1ed142d2c7eb02a9cc6e
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
arquivo (0.2.
|
|
4
|
+
arquivo (0.2.3)
|
|
5
5
|
fastimage (~> 2.1)
|
|
6
6
|
google-api-client (~> 0.34)
|
|
7
7
|
pdf-reader (~> 2.3)
|
|
@@ -49,7 +49,7 @@ GEM
|
|
|
49
49
|
hashery (~> 2.0)
|
|
50
50
|
ruby-rc4
|
|
51
51
|
ttfunk
|
|
52
|
-
public_suffix (4.0.
|
|
52
|
+
public_suffix (4.0.2)
|
|
53
53
|
rake (10.5.0)
|
|
54
54
|
representable (3.0.4)
|
|
55
55
|
declarative (< 0.1.0)
|
data/lib/arquivo.rb
CHANGED
data/lib/arquivo/dir.rb
CHANGED
|
@@ -7,21 +7,15 @@ require 'googleauth/stores/file_token_store'
|
|
|
7
7
|
require 'arquivo/noise'
|
|
8
8
|
|
|
9
9
|
module Arquivo
|
|
10
|
-
# O1 = '2>/dev/null'
|
|
11
|
-
# O2 = '1>/dev/null 2>&1'
|
|
12
|
-
O1 = ''
|
|
13
|
-
O2 = ''
|
|
14
|
-
AT = ['.mp3', '.m4a', '.wav', '.sox'].freeze
|
|
15
|
-
|
|
16
10
|
# permite processar e arquivar pasta com documentos c118
|
|
17
11
|
class C118dir < Enumerator
|
|
18
12
|
# @!group processamento
|
|
19
|
-
# processa items duma pasta
|
|
13
|
+
# processa items duma pasta
|
|
20
14
|
def processa_items
|
|
21
15
|
n = 0
|
|
22
16
|
while next_item
|
|
23
17
|
if File.ftype(item) == 'directory'
|
|
24
|
-
C118dir.new(item, opcoes).processa_pasta
|
|
18
|
+
C118dir.new(item, opcoes).processa_pasta
|
|
25
19
|
else
|
|
26
20
|
processa_file(File.extname(item).downcase)
|
|
27
21
|
n += 1
|
|
@@ -36,16 +30,16 @@ module Arquivo
|
|
|
36
30
|
def processa_fim(num)
|
|
37
31
|
return unless num.positive?
|
|
38
32
|
|
|
39
|
-
cmd = if
|
|
40
|
-
"rm -f #{
|
|
33
|
+
cmd = if contem == :fsg
|
|
34
|
+
"rm -f #{nome}.*;sox tmp/zip/* #{nome}.mp3"
|
|
41
35
|
else
|
|
42
|
-
"rm -f #{
|
|
36
|
+
"rm -f #{nome}.*;pdftk tmp/stamped* cat output #{nome}.pdf"
|
|
43
37
|
end
|
|
44
|
-
system cmd + ";cd tmp/zip;tar cf ../../#{
|
|
45
|
-
";cd ../..;gzip --best #{
|
|
46
|
-
'
|
|
38
|
+
system cmd + ";cd tmp/zip;tar cf ../../#{nome}.tar *" \
|
|
39
|
+
";cd ../..;gzip --best #{nome}.tar" \
|
|
40
|
+
';rm -rf tmp'
|
|
47
41
|
|
|
48
|
-
puts "#{
|
|
42
|
+
puts "#{nome} (#{num})"
|
|
49
43
|
end
|
|
50
44
|
|
|
51
45
|
# processa ficheiro JPG, PDF ou AUDIO
|
|
@@ -63,13 +57,11 @@ module Arquivo
|
|
|
63
57
|
end
|
|
64
58
|
|
|
65
59
|
# processa conteudo duma pasta
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def processa_pasta(pasta)
|
|
69
|
-
unless File.ftype(items.peek) == 'directory'
|
|
60
|
+
def processa_pasta
|
|
61
|
+
if contem
|
|
70
62
|
system 'mkdir -p tmp/zip'
|
|
71
|
-
obtem_dados
|
|
72
|
-
obtem_noiseprof
|
|
63
|
+
obtem_dados
|
|
64
|
+
obtem_noiseprof
|
|
73
65
|
end
|
|
74
66
|
processa_items
|
|
75
67
|
end
|
|
@@ -82,19 +74,16 @@ module Arquivo
|
|
|
82
74
|
end
|
|
83
75
|
|
|
84
76
|
# @!group dados online
|
|
85
|
-
# @param pasta (see CLI#dir)
|
|
86
77
|
# @return [Hash] dados oficiais para reclassificacao de faturas e recibos
|
|
87
|
-
def obtem_dados
|
|
78
|
+
def obtem_dados
|
|
88
79
|
@dados = {}
|
|
89
80
|
# somente faturas e recibos necessitam reclassificacao
|
|
90
|
-
return unless
|
|
81
|
+
return unless %i[fft frc].include?(contem)
|
|
91
82
|
|
|
92
83
|
# sheet c118-contas
|
|
93
84
|
dg = '1PbiMrtTtqGztZMhe3AiJbDS6NQE9o3hXebnQEFdt954'
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
@dados = c118_sheets.get_spreadsheet_values(dg, sh).values
|
|
97
|
-
.group_by { |k| k[0][/\w+/] }
|
|
85
|
+
@dados = c118_sheets.get_spreadsheet_values(dg, contem.to_s + '!A2:E')
|
|
86
|
+
.values.group_by { |k| k[0][/\w+/] }
|
|
98
87
|
rescue StandardError
|
|
99
88
|
@dados = {}
|
|
100
89
|
end
|
data/lib/arquivo/extrato.rb
CHANGED
data/lib/arquivo/jpg.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require 'fastimage'
|
|
4
4
|
|
|
5
5
|
module Arquivo
|
|
6
|
-
#
|
|
6
|
+
# tipos de audio que consigo processa
|
|
7
7
|
LT = 9000
|
|
8
8
|
|
|
9
9
|
# A4 page (8.27x11.69) inches
|
|
@@ -54,18 +54,28 @@ module Arquivo
|
|
|
54
54
|
apara.pdf.final(dad[id]).marca
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
# @return [C118jpg] jpg com melhor
|
|
57
|
+
# @return [C118jpg] jpg com melhor aparo
|
|
58
58
|
def apara
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
m[1]
|
|
59
|
+
system cmd_apara(opcoes[:fuzz], '')
|
|
60
|
+
melhor_aparo
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @return (see #apara)
|
|
64
|
+
def melhor_aparo
|
|
65
|
+
m = Dir.glob("tmp/#{id}-*.jpg")
|
|
66
|
+
.map { |s| [s, File.size(s)] }
|
|
67
|
+
.min_by { |_, v| v.between?(LT, size) ? v : size }
|
|
68
|
+
m[1] < size ? C118jpg.new(m[0], opcoes) : self
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @return [String] comando para aparar imagem
|
|
72
|
+
def cmd_apara(fuzz, cmd)
|
|
73
|
+
return cmd[1..-1] unless fuzz >= 1
|
|
74
|
+
|
|
75
|
+
cmd += ";convert \"#{file}\" -fuzz #{fuzz}% -trim +repage " \
|
|
76
|
+
"#{oqualidade} tmp/#{id}-#{fuzz}.jpg #{O2}"
|
|
77
|
+
|
|
78
|
+
cmd_apara(fuzz - 4, cmd)
|
|
69
79
|
end
|
|
70
80
|
|
|
71
81
|
# @return [C118pdf] pdf com jpg processada dentro
|
|
@@ -76,15 +86,6 @@ module Arquivo
|
|
|
76
86
|
C118pdf.new("tmp/#{id}-trimed.pdf", opcoes)
|
|
77
87
|
end
|
|
78
88
|
|
|
79
|
-
# @param [Numeric] fuzz fuzziness actual em processamento
|
|
80
|
-
# @param [String] out jpg aparada
|
|
81
|
-
# @return [Numeric] tamanho da jpg aparada
|
|
82
|
-
def size_aparado(fuzz, out)
|
|
83
|
-
system "convert \"#{file}\" -fuzz #{fuzz}% -trim +repage " \
|
|
84
|
-
"#{oqualidade} #{out} #{O2}"
|
|
85
|
-
File.size(out)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
89
|
# @return [String] opcoes comprimir jpg
|
|
89
90
|
def oqualidade
|
|
90
91
|
"-quality #{opcoes[:quality]}% -compress jpeg"
|
data/lib/arquivo/mp3.rb
CHANGED
|
@@ -60,7 +60,7 @@ module Arquivo
|
|
|
60
60
|
# @param [Integer] pse numero do segmento em processamento
|
|
61
61
|
# @return [String] nome do segmento
|
|
62
62
|
def nome_segmento(pse)
|
|
63
|
-
"
|
|
63
|
+
"sg#{format('%<v>02d', v: pse)}-#{base[/\d{8}/]}#{base[/-\w+/]}"
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# @param tempos (see #segmenta_minuta)
|
data/lib/arquivo/noise.rb
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Arquivo
|
|
4
|
+
O1 = '2>/dev/null'
|
|
5
|
+
O2 = '1>/dev/null 2>&1'
|
|
6
|
+
# tipos de audio que consigo processar
|
|
7
|
+
AT = %w[.mp3 .m4a .wav .sox].freeze
|
|
8
|
+
# tipos de documentos validos
|
|
9
|
+
# @example contem (see C118dir#obtem_conteudo)
|
|
10
|
+
DT = %i[fsc fsg frc fft fex].freeze
|
|
11
|
+
|
|
4
12
|
# permite processar e arquivar pasta com documentos c118
|
|
5
13
|
class C118dir < Enumerator
|
|
14
|
+
# @return [String] local da pasta
|
|
15
|
+
attr_reader :local
|
|
6
16
|
# @return [Enumerator] items dentro duma pasta
|
|
7
17
|
attr_reader :items
|
|
8
|
-
# @return [String]
|
|
9
|
-
attr_reader :
|
|
18
|
+
# @return [String] nome ficheiro de arquivo
|
|
19
|
+
attr_reader :nome
|
|
10
20
|
# @return [Hash] parametrizar JPG, MINUTA
|
|
11
21
|
attr_reader :opcoes
|
|
22
|
+
# @return [Symbol] conteudo da pasta
|
|
23
|
+
attr_reader :contem
|
|
24
|
+
|
|
12
25
|
# @return [String] documento c118
|
|
13
26
|
attr_reader :item
|
|
14
|
-
|
|
15
27
|
# @return (see #obtem_dados)
|
|
16
28
|
attr_reader :dados
|
|
17
29
|
# @return (see #obtem_noiseprof)
|
|
@@ -30,54 +42,77 @@ module Arquivo
|
|
|
30
42
|
# @option opt [Numeric] :rate (16) sample rate - radio-16k, CD-44.1k,
|
|
31
43
|
# PC-48k, pro-96k
|
|
32
44
|
# @return [C118dir] pasta de documentos c118
|
|
33
|
-
def initialize(
|
|
34
|
-
|
|
35
|
-
@
|
|
45
|
+
def initialize(dir, opt)
|
|
46
|
+
c = Dir.glob(File.join(dir, '*'))
|
|
47
|
+
@local = dir
|
|
48
|
+
@items = c.each
|
|
49
|
+
@nome = File.basename(dir, File.extname(dir)) + '-' +
|
|
36
50
|
Date.today.strftime('%Y%m%d')
|
|
37
51
|
@opcoes = opt
|
|
52
|
+
@contem = obtem_conteudo(c)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Agrupa conteudo duma pasta segundo tipos de documentos validos
|
|
56
|
+
#
|
|
57
|
+
# @param [Array] fls lista items duma pasta
|
|
58
|
+
# @return [Symbol] tipo de conteudo
|
|
59
|
+
# @example contem
|
|
60
|
+
# :fsc scq
|
|
61
|
+
# :fsg minutas
|
|
62
|
+
# :frc recibos
|
|
63
|
+
# :fft faturas
|
|
64
|
+
# :fex extratos
|
|
65
|
+
def obtem_conteudo(fls)
|
|
66
|
+
t = fls.group_by { |f| File.ftype(f)[0] + File.basename(f)[0, 2] }.keys
|
|
67
|
+
return unless t.size == 1 && DT.include?(t[0].to_sym)
|
|
68
|
+
|
|
69
|
+
t[0].to_sym
|
|
38
70
|
end
|
|
39
71
|
|
|
40
72
|
# @!group perfil silencio
|
|
41
|
-
# @param pasta (see CLI#dir)
|
|
42
73
|
# @return [String] perfil do maior silencio inicial de todos segmentos audio
|
|
43
|
-
def obtem_noiseprof
|
|
44
|
-
return unless
|
|
74
|
+
def obtem_noiseprof
|
|
75
|
+
return unless contem == :fsg
|
|
45
76
|
|
|
46
|
-
l = obtem_segmentos
|
|
77
|
+
l = obtem_segmentos
|
|
47
78
|
return unless l.size.positive?
|
|
48
79
|
|
|
49
80
|
t = -1
|
|
50
81
|
m = ['', 0]
|
|
51
|
-
m =
|
|
82
|
+
m = maximo_silencio(l, t += 1) while noisy?(m[1], t)
|
|
52
83
|
|
|
53
84
|
cria_noiseprof(m)
|
|
54
85
|
end
|
|
55
86
|
|
|
56
|
-
# @param [
|
|
57
|
-
# @param thr (see #
|
|
87
|
+
# @param [Float] duracao silencio
|
|
88
|
+
# @param thr (see #maximo_silencio)
|
|
58
89
|
# @return [Boolean] segmento audio tem som ou silencio no inicio
|
|
59
|
-
def noisy?(
|
|
60
|
-
thr < opcoes[:threshold] &&
|
|
90
|
+
def noisy?(sin, thr)
|
|
91
|
+
thr < opcoes[:threshold] && sin <= opcoes[:sound]
|
|
61
92
|
end
|
|
62
93
|
|
|
63
|
-
# @param [Array] lsg lista segmentos audio com duracoes
|
|
94
|
+
# @param [Array] lsg lista segmentos audio com duracoes e file silencio
|
|
64
95
|
# @param [Numeric] thr limiar para silencio em processamento
|
|
65
96
|
# @return [Array<String, Float>] segmento com maior duracao silencio inicial
|
|
66
|
-
def
|
|
67
|
-
lsg.
|
|
97
|
+
def maximo_silencio(lsg, thr)
|
|
98
|
+
system lsg.inject('') { |s, e| s + cmd_silencio(e, thr) }[1..-1]
|
|
99
|
+
lsg.map { |e| [e[0], duracao_silencio(e)] }.max_by { |_, s| s }
|
|
68
100
|
end
|
|
69
101
|
|
|
70
|
-
# @param [Array<String, Float>] seg segmento
|
|
71
|
-
# @param thr (see #
|
|
72
|
-
# @return [
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
|
|
102
|
+
# @param [Array<String, Float, String>] seg segmento, duracao, file silencio
|
|
103
|
+
# @param thr (see #maximo_silencio)
|
|
104
|
+
# @return [String] comando para cortar silencio inicial sum segmento
|
|
105
|
+
def cmd_silencio(seg, thr)
|
|
106
|
+
";sox #{seg[0]} #{seg[2]} silence 1 #{opcoes[:sound]}t #{thr}% #{O2}"
|
|
107
|
+
end
|
|
76
108
|
|
|
77
|
-
|
|
109
|
+
# @param seg (see #cmd_silencio)
|
|
110
|
+
# @return [Float] duracao silencio em segundos
|
|
111
|
+
def duracao_silencio(seg)
|
|
112
|
+
(seg[1] - duracao(seg[2])).round(2, half: :down)
|
|
78
113
|
end
|
|
79
114
|
|
|
80
|
-
# @param seg
|
|
115
|
+
# @param [Array<String, Float>] seg segmento, duracao silencio inicial
|
|
81
116
|
# @return [String] perfil sonoro do silencio inicial dum segmento
|
|
82
117
|
def cria_noiseprof(seg)
|
|
83
118
|
return unless seg[1] > opcoes[:sound]
|
|
@@ -90,11 +125,10 @@ module Arquivo
|
|
|
90
125
|
@noiseprof = File.size?(o).positive? ? o : nil
|
|
91
126
|
end
|
|
92
127
|
|
|
93
|
-
# @
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.map { |s| [s, duracao(s)] }
|
|
128
|
+
# @return [Array] lista segmentos audio com duracoes e file silencio
|
|
129
|
+
def obtem_segmentos
|
|
130
|
+
AT.map { |e| Dir.glob(File.join(local, 'sg*' + e)) }.flatten
|
|
131
|
+
.map { |s| [s, duracao(s), "tmp/thr-#{File.basename(s)}"] }
|
|
98
132
|
end
|
|
99
133
|
|
|
100
134
|
# @param [String] audio ficheiro de audio
|
data/lib/arquivo/pdf.rb
CHANGED
|
@@ -121,7 +121,7 @@ module Arquivo
|
|
|
121
121
|
return false if id[0] == 'r'
|
|
122
122
|
|
|
123
123
|
o = "tmp/#{id}.txt"
|
|
124
|
-
# se pdf contem texto -> not scanned
|
|
124
|
+
# se pdf contem texto -> not scanned pdf
|
|
125
125
|
system "pdftotext -q -eol unix -nopgbrk \"#{file}\" #{o}"
|
|
126
126
|
return false if File.size?(o)
|
|
127
127
|
|
|
@@ -129,6 +129,7 @@ module Arquivo
|
|
|
129
129
|
# utilizar somente 1 imagem, comvertida em jpg
|
|
130
130
|
system "convert #{Dir.glob("tmp/#{id}-???.???")[0]} #{jpg} #{O2}"
|
|
131
131
|
|
|
132
|
+
# jpg demasiado pequeno -> not scanned pdf
|
|
132
133
|
File.size?(jpg) > LT
|
|
133
134
|
end
|
|
134
135
|
|
data/lib/arquivo/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: arquivo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hernâni Rodrigues Vaz
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-12-
|
|
11
|
+
date: 2019-12-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|