arquivo 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|