concurso_hub 0.1.0
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 +7 -0
- data/README.md +511 -0
- data/lib/concurso_hub/version.rb +5 -0
- data/lib/concurso_hub.rb +143 -0
- data/src/application/baixar_edital_request.rb +5 -0
- data/src/application/baixar_provas_request.rb +5 -0
- data/src/application/filtros_concurso.rb +16 -0
- data/src/application/ports/concurso_repository.rb +27 -0
- data/src/application/ports/file_downloader.rb +11 -0
- data/src/application/ports/presenter.rb +35 -0
- data/src/application/use_cases/baixar_edital.rb +43 -0
- data/src/application/use_cases/baixar_provas.rb +59 -0
- data/src/application/use_cases/listar_concursos.rb +89 -0
- data/src/application/use_cases/listar_provas.rb +32 -0
- data/src/application/use_cases/ver_edital.rb +21 -0
- data/src/application/ver_edital_request.rb +5 -0
- data/src/domain/entities/concurso.rb +24 -0
- data/src/domain/entities/edital.rb +21 -0
- data/src/infrastructure/http/http_client.rb +41 -0
- data/src/infrastructure/http/http_file_downloader.rb +44 -0
- data/src/infrastructure/parsers/pci_html_parser.rb +208 -0
- data/src/infrastructure/repositories/pci_concurso_repository.rb +49 -0
- data/src/presentation/cli/cli_controller.rb +35 -0
- data/src/presentation/cli/cli_options_parser.rb +121 -0
- data/src/presentation/formatters/terminal_presenter.rb +203 -0
- metadata +81 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'uri'
|
|
4
|
+
require_relative '../../application/ports/concurso_repository'
|
|
5
|
+
require_relative '../http/http_client'
|
|
6
|
+
require_relative '../parsers/pci_html_parser'
|
|
7
|
+
|
|
8
|
+
module Infrastructure
|
|
9
|
+
module Repositories
|
|
10
|
+
class PciConcursoRepository < Application::Ports::ConcursoRepository
|
|
11
|
+
ABERTOS_URL = 'https://www.pciconcursos.com.br/concursos/'
|
|
12
|
+
ENCERRADOS_URL = 'https://www.pciconcursos.com.br/pesquisa/'
|
|
13
|
+
|
|
14
|
+
def initialize(
|
|
15
|
+
http_client: Http::HttpClient.new,
|
|
16
|
+
parser: Parsers::PciHtmlParser.new
|
|
17
|
+
)
|
|
18
|
+
@http_client = http_client
|
|
19
|
+
@parser = parser
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def fetch_abertos
|
|
23
|
+
html = @http_client.get(ABERTOS_URL)
|
|
24
|
+
@parser.parse_abertos(html)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def fetch_encerrados(busca)
|
|
28
|
+
url = "#{ENCERRADOS_URL}?p=#{URI.encode_www_form_component(busca)}&tipopesquisa=1"
|
|
29
|
+
html = @http_client.get(url)
|
|
30
|
+
@parser.parse_encerrados(html)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def fetch_edital(url)
|
|
34
|
+
html = @http_client.get(url)
|
|
35
|
+
@parser.parse_edital(html, url)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def fetch_provas_listing(provas_url)
|
|
39
|
+
html = @http_client.get(provas_url)
|
|
40
|
+
@parser.parse_provas_listing(html)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def fetch_prova_pdfs(download_url)
|
|
44
|
+
html = @http_client.get(download_url)
|
|
45
|
+
@parser.parse_prova_download_page(html)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'cli_options_parser'
|
|
4
|
+
require_relative '../../application/ver_edital_request'
|
|
5
|
+
require_relative '../../application/baixar_edital_request'
|
|
6
|
+
require_relative '../../application/baixar_provas_request'
|
|
7
|
+
|
|
8
|
+
module Presentation
|
|
9
|
+
module Cli
|
|
10
|
+
class CliController
|
|
11
|
+
def initialize(use_case:, ver_edital:, baixar_edital:, baixar_provas:, options_parser: CliOptionsParser.new)
|
|
12
|
+
@use_case = use_case
|
|
13
|
+
@ver_edital = ver_edital
|
|
14
|
+
@baixar_edital = baixar_edital
|
|
15
|
+
@baixar_provas = baixar_provas
|
|
16
|
+
@options_parser = options_parser
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def run(args)
|
|
20
|
+
request = @options_parser.parse(args)
|
|
21
|
+
|
|
22
|
+
case request
|
|
23
|
+
when Application::BaixarProvasRequest
|
|
24
|
+
@baixar_provas.execute(request)
|
|
25
|
+
when Application::BaixarEditalRequest
|
|
26
|
+
@baixar_edital.execute(request)
|
|
27
|
+
when Application::VerEditalRequest
|
|
28
|
+
@ver_edital.execute(request)
|
|
29
|
+
else
|
|
30
|
+
@use_case.execute(request)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'optparse'
|
|
4
|
+
require_relative '../../application/filtros_concurso'
|
|
5
|
+
require_relative '../../application/ver_edital_request'
|
|
6
|
+
require_relative '../../application/baixar_edital_request'
|
|
7
|
+
require_relative '../../application/baixar_provas_request'
|
|
8
|
+
|
|
9
|
+
module Presentation
|
|
10
|
+
module Cli
|
|
11
|
+
class CliOptionsParser
|
|
12
|
+
ESTADOS_VALIDOS = %w[
|
|
13
|
+
NACIONAL AC AL AM AP BA CE DF ES GO MA MG MS MT PA PB PE PI PR
|
|
14
|
+
RJ RN RO RR RS SC SE SP TO
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
def parse(args)
|
|
18
|
+
options = {}
|
|
19
|
+
ver_url = nil
|
|
20
|
+
baixar_url = nil
|
|
21
|
+
baixar_provas_url = nil
|
|
22
|
+
dest_dir = nil
|
|
23
|
+
|
|
24
|
+
parser = OptionParser.new do |opts|
|
|
25
|
+
opts.banner = build_banner
|
|
26
|
+
opts.separator 'Opções:'
|
|
27
|
+
|
|
28
|
+
opts.on('--ver URL',
|
|
29
|
+
'Exibir o edital completo de um concurso pela URL') do |v|
|
|
30
|
+
ver_url = v
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
opts.on('--baixar URL',
|
|
34
|
+
'Baixar os PDFs do edital de um concurso pela URL') do |v|
|
|
35
|
+
baixar_url = v
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on('--baixar-provas URL',
|
|
39
|
+
'Baixar provas/gabaritos de uma página de provas do pciconcursos') do |v|
|
|
40
|
+
baixar_provas_url = v
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
opts.on('--dir PASTA',
|
|
44
|
+
'Pasta de destino para --baixar (padrão: ./editais/)') do |v|
|
|
45
|
+
dest_dir = v
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
opts.on('--estado ESTADO',
|
|
49
|
+
"Filtrar por estado/UF (#{ESTADOS_VALIDOS.join(', ')})") do |v|
|
|
50
|
+
options[:estado] = v.upcase
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
opts.on('--nivel NIVEL',
|
|
54
|
+
'Filtrar por escolaridade (ex: Superior, Médio, Técnico)') do |v|
|
|
55
|
+
options[:nivel] = v
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
opts.on('--busca TEXTO',
|
|
59
|
+
'Buscar texto no nome da instituição ou cargo') do |v|
|
|
60
|
+
options[:busca] = v
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
opts.on('--limite N', Integer,
|
|
64
|
+
'Limitar o número de resultados exibidos') do |v|
|
|
65
|
+
options[:limite] = v
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
opts.on('--ano ANO', Integer,
|
|
69
|
+
'Filtrar pelo ano no prazo de inscrição (ex: 2025, 2026)') do |v|
|
|
70
|
+
options[:ano] = v
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
opts.on('--abertos',
|
|
74
|
+
'Mostrar concursos com inscrições abertas (padrão)') do
|
|
75
|
+
options[:modo] = :abertos
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
opts.on('--encerrados',
|
|
79
|
+
'Mostrar concursos encerrados (requer --busca)') do
|
|
80
|
+
options[:modo] = :encerrados
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
opts.on('-h', '--help', 'Exibir esta ajuda') do
|
|
84
|
+
puts opts
|
|
85
|
+
exit
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
parser.parse!(args)
|
|
90
|
+
return Application::BaixarProvasRequest.new(url: baixar_provas_url, dest_dir: dest_dir) if baixar_provas_url
|
|
91
|
+
return Application::BaixarEditalRequest.new(url: baixar_url, dest_dir: dest_dir) if baixar_url
|
|
92
|
+
return Application::VerEditalRequest.new(url: ver_url) if ver_url
|
|
93
|
+
|
|
94
|
+
Application::FiltrosConcurso.new(**options)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
def build_banner
|
|
100
|
+
<<~BANNER
|
|
101
|
+
|
|
102
|
+
Uso:
|
|
103
|
+
ruby main.rb [opções]
|
|
104
|
+
|
|
105
|
+
Exemplos:
|
|
106
|
+
ruby main.rb # todos os abertos
|
|
107
|
+
ruby main.rb --estado SP # apenas SP
|
|
108
|
+
ruby main.rb --nivel Superior # nível superior
|
|
109
|
+
ruby main.rb --busca analista # busca por texto
|
|
110
|
+
ruby main.rb --estado MG --limite 10 # 10 primeiros de MG
|
|
111
|
+
ruby main.rb --encerrados --busca policia # encerrados sobre polícia
|
|
112
|
+
ruby main.rb --ver URL # edital completo de um concurso
|
|
113
|
+
ruby main.rb --baixar URL # baixar PDFs do edital
|
|
114
|
+
ruby main.rb --baixar URL --dir ~/Downloads
|
|
115
|
+
ruby main.rb --baixar-provas URL # baixar provas/gabaritos anteriores
|
|
116
|
+
|
|
117
|
+
BANNER
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../application/ports/presenter'
|
|
4
|
+
|
|
5
|
+
module Presentation
|
|
6
|
+
module Formatters
|
|
7
|
+
class TerminalPresenter < Application::Ports::Presenter
|
|
8
|
+
RESET = "\e[0m"
|
|
9
|
+
BOLD = "\e[1m"
|
|
10
|
+
DIM = "\e[2m"
|
|
11
|
+
RED = "\e[31m"
|
|
12
|
+
GREEN = "\e[32m"
|
|
13
|
+
YELLOW = "\e[33m"
|
|
14
|
+
BLUE = "\e[34m"
|
|
15
|
+
CYAN = "\e[36m"
|
|
16
|
+
WHITE = "\e[97m"
|
|
17
|
+
|
|
18
|
+
def show_loading
|
|
19
|
+
puts "#{CYAN}Conectando ao pciconcursos.com.br…#{RESET}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def show(concursos, metadata: {})
|
|
23
|
+
if concursos.empty?
|
|
24
|
+
puts "\n#{RED}Nenhum concurso encontrado com os filtros informados.#{RESET}\n"
|
|
25
|
+
return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
render_header(metadata)
|
|
29
|
+
render_concursos(concursos)
|
|
30
|
+
render_footer(concursos.size)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def error(message)
|
|
34
|
+
warn "#{RED}#{message}#{RESET}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def show_edital(edital)
|
|
38
|
+
puts
|
|
39
|
+
puts "#{BOLD}#{CYAN}╔══════════════════════════════════════════════════════════╗#{RESET}"
|
|
40
|
+
puts "#{BOLD}#{CYAN}║ EDITAL COMPLETO ║#{RESET}"
|
|
41
|
+
puts "#{BOLD}#{CYAN}╚══════════════════════════════════════════════════════════╝#{RESET}"
|
|
42
|
+
puts
|
|
43
|
+
puts "#{BOLD}#{WHITE}#{edital.titulo}#{RESET}"
|
|
44
|
+
puts
|
|
45
|
+
puts "#{DIM}#{edital.descricao}#{RESET}" unless edital.descricao.empty?
|
|
46
|
+
puts "#{DIM}Publicado em: #{edital.data_publicacao}#{RESET}" unless edital.data_publicacao.empty?
|
|
47
|
+
puts "#{DIM}Fonte: #{edital.url}#{RESET}"
|
|
48
|
+
puts
|
|
49
|
+
puts "#{DIM}#{'─' * 70}#{RESET}"
|
|
50
|
+
puts
|
|
51
|
+
|
|
52
|
+
edital.blocos.each do |bloco|
|
|
53
|
+
case bloco[:tipo]
|
|
54
|
+
when :secao
|
|
55
|
+
puts "\n#{BOLD}#{YELLOW}#{bloco[:texto]}#{RESET}\n"
|
|
56
|
+
when :paragrafo
|
|
57
|
+
puts wrap_text(bloco[:texto])
|
|
58
|
+
puts
|
|
59
|
+
when :item
|
|
60
|
+
puts " #{CYAN}•#{RESET} #{wrap_text(bloco[:texto], indent: 4)}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
unless edital.pdfs.empty?
|
|
65
|
+
puts
|
|
66
|
+
puts "#{BOLD}#{YELLOW}PDFs disponíveis:#{RESET}"
|
|
67
|
+
edital.pdfs.each_with_index do |pdf, i|
|
|
68
|
+
puts " #{CYAN}[#{i + 1}]#{RESET} #{pdf[:titulo]}"
|
|
69
|
+
puts " #{DIM}#{pdf[:url]}#{RESET}"
|
|
70
|
+
end
|
|
71
|
+
puts
|
|
72
|
+
puts "#{DIM}Use --baixar URL para fazer download dos PDFs.#{RESET}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if edital.provas_url
|
|
76
|
+
puts
|
|
77
|
+
puts "#{BOLD}#{YELLOW}Provas anteriores disponíveis:#{RESET}"
|
|
78
|
+
puts " #{DIM}#{edital.provas_url}#{RESET}"
|
|
79
|
+
puts "#{DIM}Use --baixar-provas #{edital.provas_url} para baixar todas as provas.#{RESET}"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def show_provas(provas)
|
|
84
|
+
if provas.empty?
|
|
85
|
+
puts "\n#{RED}Nenhuma prova encontrada.#{RESET}\n"
|
|
86
|
+
return
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
puts
|
|
90
|
+
puts "#{BOLD}#{CYAN}Provas e gabaritos disponíveis:#{RESET}"
|
|
91
|
+
puts
|
|
92
|
+
provas.each do |prova|
|
|
93
|
+
puts "#{BOLD}#{YELLOW}#{prova[:cargo]}#{RESET}"
|
|
94
|
+
prova[:pdfs].each_with_index do |pdf, i|
|
|
95
|
+
puts " #{CYAN}[#{i + 1}]#{RESET} #{pdf[:titulo]}"
|
|
96
|
+
puts " #{DIM}#{pdf[:url]}#{RESET}"
|
|
97
|
+
end
|
|
98
|
+
puts
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
puts
|
|
102
|
+
puts "#{DIM}#{'═' * 70}#{RESET}"
|
|
103
|
+
puts
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def show_download_start(titulo, index, total)
|
|
107
|
+
puts " #{CYAN}[#{index}/#{total}]#{RESET} #{titulo}…"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def show_download_done(paths)
|
|
111
|
+
puts
|
|
112
|
+
puts "#{GREEN}#{BOLD}#{paths.size} arquivo(s) baixado(s) com sucesso:#{RESET}"
|
|
113
|
+
paths.each { |p| puts " #{DIM}#{p}#{RESET}" }
|
|
114
|
+
puts
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
private
|
|
118
|
+
|
|
119
|
+
def render_header(metadata)
|
|
120
|
+
total_vagas = metadata[:total_vagas] || ''
|
|
121
|
+
total_scraped = metadata[:total_scraped]
|
|
122
|
+
encerrados = metadata[:modo] == :encerrados
|
|
123
|
+
busca = metadata[:busca]
|
|
124
|
+
|
|
125
|
+
titulo = encerrados ? 'CONCURSOS ENCERRADOS' : 'CONCURSOS PÚBLICOS ABERTOS'
|
|
126
|
+
|
|
127
|
+
puts
|
|
128
|
+
puts "#{BOLD}#{CYAN}╔══════════════════════════════════════════════════════════╗#{RESET}"
|
|
129
|
+
puts "#{BOLD}#{CYAN}║ #{titulo.ljust(54)} ║#{RESET}"
|
|
130
|
+
puts "#{BOLD}#{CYAN}║ #{Time.now.strftime('%d/%m/%Y').ljust(54)} ║#{RESET}"
|
|
131
|
+
puts "#{BOLD}#{CYAN}╚══════════════════════════════════════════════════════════╝#{RESET}"
|
|
132
|
+
puts
|
|
133
|
+
puts "#{DIM}Busca: \"#{busca}\"#{RESET}" if busca
|
|
134
|
+
puts "#{DIM}Fonte: pciconcursos.com.br | #{total_vagas}#{RESET}" unless total_vagas.empty?
|
|
135
|
+
puts "#{DIM}#{total_scraped} resultado(s) encontrado(s).#{RESET}" if total_scraped
|
|
136
|
+
puts
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def render_concursos(concursos)
|
|
140
|
+
puts "#{GREEN}#{BOLD}Exibindo #{concursos.size} concurso(s)#{RESET}"
|
|
141
|
+
puts
|
|
142
|
+
|
|
143
|
+
current_state = nil
|
|
144
|
+
concursos.each do |c|
|
|
145
|
+
if c.estado != current_state
|
|
146
|
+
current_state = c.estado
|
|
147
|
+
puts "\n#{BOLD}#{BLUE}▶ #{current_state}#{RESET}"
|
|
148
|
+
puts "#{DIM}#{'-' * 62}#{RESET}"
|
|
149
|
+
end
|
|
150
|
+
render_entry(c)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def render_entry(concurso)
|
|
155
|
+
puts
|
|
156
|
+
puts " #{BOLD}#{WHITE}#{concurso.instituicao}#{RESET}"
|
|
157
|
+
|
|
158
|
+
vagas_line = if concurso.salario.empty?
|
|
159
|
+
concurso.vagas
|
|
160
|
+
else
|
|
161
|
+
"#{concurso.vagas} #{YELLOW}#{concurso.salario}#{RESET}"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
puts " #{YELLOW}Vagas :#{RESET} #{vagas_line}"
|
|
165
|
+
puts " #{YELLOW}Cargo :#{RESET} #{concurso.cargos}" unless concurso.cargos.empty?
|
|
166
|
+
puts " #{YELLOW}Nível :#{RESET} #{concurso.nivel}" unless concurso.nivel.empty?
|
|
167
|
+
puts " #{YELLOW}Prazo :#{RESET} #{RED}#{concurso.prazo}#{RESET}" unless concurso.prazo.empty?
|
|
168
|
+
puts " #{DIM}#{concurso.url}#{RESET}" if concurso.url
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def render_footer(count)
|
|
172
|
+
puts
|
|
173
|
+
puts "#{DIM}#{'═' * 62}#{RESET}"
|
|
174
|
+
puts "#{GREEN}#{BOLD}Total exibido: #{count} concurso(s)#{RESET}"
|
|
175
|
+
puts
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def wrap_text(text, width: 72, indent: 0)
|
|
179
|
+
words = text.split(' ')
|
|
180
|
+
prefix = ' ' * indent
|
|
181
|
+
lines = []
|
|
182
|
+
line = ''
|
|
183
|
+
|
|
184
|
+
words.each do |word|
|
|
185
|
+
if line.empty?
|
|
186
|
+
line = word
|
|
187
|
+
elsif (line.length + 1 + word.length) <= (width - indent)
|
|
188
|
+
line += " #{word}"
|
|
189
|
+
else
|
|
190
|
+
lines << line
|
|
191
|
+
line = word
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
lines << line unless line.empty?
|
|
195
|
+
|
|
196
|
+
first = lines.shift || ''
|
|
197
|
+
return first if lines.empty?
|
|
198
|
+
|
|
199
|
+
([first] + lines.map { |l| prefix + l }).join("\n")
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: concurso_hub
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Felipe
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-22 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: nokogiri
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.16'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.16'
|
|
27
|
+
description: Gem Ruby para buscar concursos públicos brasileiros a partir do PCI Concursos.
|
|
28
|
+
Retorna listagens, editais e provas em estruturas de dados prontas para APIs backend.
|
|
29
|
+
email: ''
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- README.md
|
|
35
|
+
- lib/concurso_hub.rb
|
|
36
|
+
- lib/concurso_hub/version.rb
|
|
37
|
+
- src/application/baixar_edital_request.rb
|
|
38
|
+
- src/application/baixar_provas_request.rb
|
|
39
|
+
- src/application/filtros_concurso.rb
|
|
40
|
+
- src/application/ports/concurso_repository.rb
|
|
41
|
+
- src/application/ports/file_downloader.rb
|
|
42
|
+
- src/application/ports/presenter.rb
|
|
43
|
+
- src/application/use_cases/baixar_edital.rb
|
|
44
|
+
- src/application/use_cases/baixar_provas.rb
|
|
45
|
+
- src/application/use_cases/listar_concursos.rb
|
|
46
|
+
- src/application/use_cases/listar_provas.rb
|
|
47
|
+
- src/application/use_cases/ver_edital.rb
|
|
48
|
+
- src/application/ver_edital_request.rb
|
|
49
|
+
- src/domain/entities/concurso.rb
|
|
50
|
+
- src/domain/entities/edital.rb
|
|
51
|
+
- src/infrastructure/http/http_client.rb
|
|
52
|
+
- src/infrastructure/http/http_file_downloader.rb
|
|
53
|
+
- src/infrastructure/parsers/pci_html_parser.rb
|
|
54
|
+
- src/infrastructure/repositories/pci_concurso_repository.rb
|
|
55
|
+
- src/presentation/cli/cli_controller.rb
|
|
56
|
+
- src/presentation/cli/cli_options_parser.rb
|
|
57
|
+
- src/presentation/formatters/terminal_presenter.rb
|
|
58
|
+
homepage: https://github.com/seu-usuario/concurso_hub
|
|
59
|
+
licenses:
|
|
60
|
+
- MIT
|
|
61
|
+
metadata: {}
|
|
62
|
+
post_install_message:
|
|
63
|
+
rdoc_options: []
|
|
64
|
+
require_paths:
|
|
65
|
+
- lib
|
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '3.1'
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
requirements: []
|
|
77
|
+
rubygems_version: 3.5.11
|
|
78
|
+
signing_key:
|
|
79
|
+
specification_version: 4
|
|
80
|
+
summary: Busca e extração de dados de concursos públicos brasileiros
|
|
81
|
+
test_files: []
|