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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed65dd3f514e1950093d139e190ba9104037dc1637f4aa63a879aa5a26e7707f
4
- data.tar.gz: 75603c49ac01b58575ad63bba4aee0cf5265594fa41a95407aaa10125a717cf4
3
+ metadata.gz: cb7ecf71153002b263d88303a43e2c298d9afc9a25bf1ff996c18016c60dc6eb
4
+ data.tar.gz: 9304605a85684d6572891709c48082bf730d38ddc8c273a614ad5052a04596c3
5
5
  SHA512:
6
- metadata.gz: 2440e3fa68fbc48bc7e34432bcbb0d832d6c530c3dbbe872b649cb9f7c6d830b7e04034621b8dbbc8a2ad506abce5587394b6334c324f9c1932fd0f09cdca2d4
7
- data.tar.gz: dc20b52f6c192f51922637b96ebc8cc063178ce5812a8947aa0cc1f13c395cbba8698a0810d4269e70af9693cbbaf72ce54905726a46c74c8c958e7615a9a536
6
+ metadata.gz: 00aaddf208d5ab5123858c2ea52105b2c18495e35e398059c17b982a082fcdc80762a5d6d8f75bfa43e2cc5faeb6b0b68fc7ec05c91934e1620e35f6eec4a36f
7
+ data.tar.gz: 2c5f2f72098327bc4fee7df75281e5a55ded17058af3af633527750ecc04250ede81f4b06bb575d2be9b0854b73834ec10d44dfa2f1b1ed142d2c7eb02a9cc6e
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- arquivo (0.2.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.1)
52
+ public_suffix (4.0.2)
53
53
  rake (10.5.0)
54
54
  representable (3.0.4)
55
55
  declarative (< 0.1.0)
@@ -76,7 +76,7 @@ module Arquivo
76
76
  def dir(pasta)
77
77
  return unless File.ftype(pasta) == 'directory'
78
78
 
79
- C118dir.new(pasta, options).processa_pasta(pasta)
79
+ C118dir.new(pasta, options).processa_pasta
80
80
  end
81
81
  end
82
82
  end
@@ -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 - sub-pastas recursivamente
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(item)
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 /minuta/i.match?(base)
40
- "rm -f #{base}.*"
33
+ cmd = if contem == :fsg
34
+ "rm -f #{nome}.*;sox tmp/zip/* #{nome}.mp3"
41
35
  else
42
- "rm -f #{base}.*;pdftk tmp/stamped*.pdf cat output #{base}.pdf"
36
+ "rm -f #{nome}.*;pdftk tmp/stamped* cat output #{nome}.pdf"
43
37
  end
44
- system cmd + ";cd tmp/zip;tar cf ../../#{base}.tar *" \
45
- ";cd ../..;gzip --best #{base}.tar" \
46
- '' # ';rm -rf tmp'
38
+ system cmd + ";cd tmp/zip;tar cf ../../#{nome}.tar *" \
39
+ ";cd ../..;gzip --best #{nome}.tar" \
40
+ ';rm -rf tmp'
47
41
 
48
- puts "#{base} (#{num})"
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
- # @param pasta (see CLI#dir)
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(pasta)
72
- obtem_noiseprof(pasta)
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(pasta)
78
+ def obtem_dados
88
79
  @dados = {}
89
80
  # somente faturas e recibos necessitam reclassificacao
90
- return unless /fac?tura/i.match?(pasta) || /recibo/i.match?(pasta)
81
+ return unless %i[fft frc].include?(contem)
91
82
 
92
83
  # sheet c118-contas
93
84
  dg = '1PbiMrtTtqGztZMhe3AiJbDS6NQE9o3hXebnQEFdt954'
94
- # range dos dados (faturas/recibos)
95
- sh = (/fac?tura/i.match?(pasta) ? 'rft' : 'rrc') + '!A2:E'
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
@@ -101,7 +101,7 @@ module Arquivo
101
101
 
102
102
  @paginas = []
103
103
  n = pagina.scan(%r{N\. *(\d+)/(\d+)}).flatten
104
- @nome = n.empty? ? nil : "ex#{n[0][/\d{2}$/]}#{n[1]}"
104
+ @nome = n.empty? ? nil : "ex#{n[1]}-#{n[0]}"
105
105
  rescue StandardError
106
106
  @nome = nil
107
107
  end
@@ -3,7 +3,7 @@
3
3
  require 'fastimage'
4
4
 
5
5
  module Arquivo
6
- # size limit after trim attempt
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 aparado
57
+ # @return [C118jpg] jpg com melhor aparo
58
58
  def apara
59
- f = opcoes[:fuzz]
60
- h = {}
61
- # aparar borders ao maximo
62
- while f >= 1
63
- o = "tmp/#{id}-#{f}.jpg"
64
- h[o] = size_aparado(f, o)
65
- f -= 4
66
- end
67
- m = h.min_by { |_, v| v }
68
- m[1].between?(LT, size) ? C118jpg.new(m[0], opcoes) : self
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"
@@ -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
- "s#{format('%<v>02d', v: pse)}-#{base[/\d{8}/]}#{base[/-\w+/]}"
63
+ "sg#{format('%<v>02d', v: pse)}-#{base[/\d{8}/]}#{base[/-\w+/]}"
64
64
  end
65
65
 
66
66
  # @param tempos (see #segmenta_minuta)
@@ -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] base nome ficheiros para arquivo (pdf, tar.gz)
9
- attr_reader :base
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(pasta, opt)
34
- @items = Dir.glob(File.join(pasta, '*')).each
35
- @base = File.basename(pasta, File.extname(pasta)) + '-' +
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(pasta)
44
- return unless /minuta/i.match?(pasta)
74
+ def obtem_noiseprof
75
+ return unless contem == :fsg
45
76
 
46
- l = obtem_segmentos(pasta)
77
+ l = obtem_segmentos
47
78
  return unless l.size.positive?
48
79
 
49
80
  t = -1
50
81
  m = ['', 0]
51
- m = obtem_maximo_silencio(l, t += 1) while noisy?(m, t)
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 [Array<String, Float>] seg segmento, duracao silencio inicial
57
- # @param thr (see #obtem_maximo_silencio)
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?(seg, thr)
60
- thr < opcoes[:threshold] && seg[1] <= opcoes[:sound]
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 obtem_maximo_silencio(lsg, thr)
67
- lsg.sort.map { |e| obtem_silencio(e, thr) }.max_by { |_, s| s }
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 audio, duracao
71
- # @param thr (see #obtem_maximo_silencio)
72
- # @return [Array<String, Float>] segmento audio, duracao silencio inicial
73
- def obtem_silencio(seg, thr)
74
- o = "tmp/thr-#{File.basename(seg[0])}"
75
- system "sox #{seg[0]} #{o} silence 1 #{opcoes[:sound]}t #{thr}% #{O2}"
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
- [seg[0], (seg[1] - duracao(o)).round(2, half: :down)]
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 (see #noisy?)
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
- # @param pasta (see CLI#dir)
94
- # @return [Array] lista segmentos audio com duracoes
95
- def obtem_segmentos(pasta)
96
- AT.map { |e| Dir.glob(File.join(pasta, 's[0-9][0-9]-*' + e)) }.flatten
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
@@ -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
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Arquivo
4
- VERSION = '0.2.2'
4
+ VERSION = '0.2.3'
5
5
  end
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.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-28 00:00:00.000000000 Z
11
+ date: 2019-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler