csc-cia-stne 0.0.64__py3-none-any.whl → 0.0.65__py3-none-any.whl

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.
csc_cia_stne/bc_sta.py CHANGED
@@ -2,8 +2,52 @@ from requests.auth import HTTPBasicAuth
2
2
  import requests
3
3
  import xml.etree.ElementTree as ET
4
4
  import hashlib
5
- from pydantic import BaseModel, ValidationError, field_validator
5
+ from pydantic import BaseModel, ValidationError, field_validator, Field, HttpUrl
6
6
  from typing import Literal, Dict, Union, Optional
7
+ import json
8
+
9
+ def xml_to_dict(element):
10
+ """Converte um elemento XML recursivamente para um dicionário."""
11
+ if not list(element): # Se não tem filhos, retorna apenas o texto
12
+ return element.text.strip() if element.text else ""
13
+
14
+ result = {}
15
+ for child in element:
16
+ child_data = xml_to_dict(child)
17
+ if child.tag in result:
18
+ if isinstance(result[child.tag], list):
19
+ result[child.tag].append(child_data)
20
+ else:
21
+ result[child.tag] = [result[child.tag], child_data]
22
+ else:
23
+ result[child.tag] = child_data
24
+
25
+ if element.attrib:
26
+ result["@atributos"] = element.attrib # Adiciona atributos XML se existirem
27
+
28
+ return result
29
+
30
+ def xml_response_to_json(response_text):
31
+ """Converte a resposta XML para um dicionário JSON válido."""
32
+
33
+ root = ET.fromstring(response_text)
34
+ lista = xml_to_dict(root)
35
+ if not isinstance(lista, dict):
36
+ return []
37
+ return list(lista.values())[0] # Agora retorna um dicionário em vez de uma string JSON
38
+
39
+ def print_element(element, indent=0):
40
+ """Função recursiva para exibir campos e subcampos"""
41
+ prefix = " " * (indent * 2) # Indentação para visualização hierárquica
42
+ print(f"{prefix}- {element.tag}: {element.text.strip() if element.text else ''}")
43
+
44
+ # Se o elemento tiver atributos, exibir
45
+ if element.attrib:
46
+ print(f"{prefix} Atributos: {element.attrib}")
47
+
48
+ # Percorrer subelementos
49
+ for child in element:
50
+ print_element(child, indent + 1)
7
51
 
8
52
  # Validações dos inputs
9
53
  class InitParamsValidator(BaseModel):
@@ -118,7 +162,34 @@ class EnviarArquivoValidator(BaseModel):
118
162
  raise ValueError("Cada destinatário deve conter as chaves 'unidade', 'dependencia' e 'operador'. Verifique a documentação da API BC STA para entender o que colocar cada campo")
119
163
 
120
164
  return value
121
-
165
+
166
+ class ListarArquivosParams(BaseModel):
167
+ """
168
+ Parâmetros para listar arquivos disponíveis na API STA.
169
+
170
+ Atributos:
171
+ nivel (str): Nível de detalhe da consulta. Aceita apenas 'RES', 'BAS' ou 'COMPL'.
172
+ inicio (str): Data e hora de início no formato ISO 8601 (yyyy-MM-ddTHH:mm:ss).
173
+ situacao (Optional[str]): Situação da transmissão, podendo ser 'REC' ou 'A_REC'.
174
+ identificadorDocumento (Optional[str]): Identificador do documento, se aplicável.
175
+ qtd (int): Quantidade máxima de resultados (valor padrão: 100, máximo permitido: 100).
176
+ """
177
+ nivel: Literal['RES', 'BAS', 'COMPL']
178
+ #inicio: str = Field(..., regex=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$")
179
+ inicio: str = Field(..., pattern=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$")
180
+ situacao: Optional[Literal['REC', 'A_REC']] = None
181
+ identificadorDocumento: Optional[str] = None
182
+ qtd: int = Field(default=100, le=100)
183
+
184
+ class DownloadArquivoParams(BaseModel):
185
+ protocolo: str = Field(..., min_length=1, description="Código do protocolo")
186
+ filename: Optional[str] = Field(None, description="Nome e caminho do arquivo")
187
+
188
+ class DownloadArquivoResponse(BaseModel):
189
+ success: bool = Field(..., description="Indica se o download foi bem-sucedido")
190
+ status_code: int = Field(..., ge=100, le=599, description="Código de status HTTP")
191
+ content: Union[bytes, str] = Field(..., description="Conteúdo do arquivo (em bytes se sucesso, em string se erro)")
192
+
122
193
  class BC_STA:
123
194
 
124
195
  def __init__(self, usuario:str, senha:str, ambiente:str):
@@ -414,3 +485,131 @@ class BC_STA:
414
485
  #return f"Failed to create protocol. Status code: {response.status_code}, Reason: {response.reason}"
415
486
  return resposta
416
487
 
488
+ def listar_arquivos_old(self, nivel: Literal['RES', 'BAS', 'COMPL'], inicio: str, situacao: Optional[Literal['REC', 'A_REC']] = None, identificadorDocumento: Optional[str] = None, qtd: int = 100):
489
+ """
490
+ Lista os arquivos disponíveis na API STA.
491
+
492
+ Args:
493
+ nivel (str): Nível de detalhe da consulta ('RES', 'BAS' ou 'COMPL').
494
+ inicio (str): Data e hora de início no formato ISO 8601 (yyyy-MM-ddTHH:mm:ss).
495
+ situacao (Optional[str]): Situação da transmissão ('REC' ou 'A_REC').
496
+ identificadorDocumento (Optional[str]): Identificador do documento.
497
+ qtd (int): Quantidade máxima de resultados (padrão: 100, máximo: 100).
498
+
499
+ Returns:
500
+ dict: Resposta da API em formato JSON.
501
+ """
502
+ params = ListarArquivosParams(nivel=nivel, inicio=inicio, situacao=situacao, identificadorDocumento=identificadorDocumento, qtd=qtd)
503
+
504
+ url = f"{self.base_url}/arquivos?tipoConsulta=AVANC&nivelDetalhe={params.nivel}"
505
+ url += f"&dataHoraInicio={params.inicio}&situacaoTransmissao={params.situacao}" if params.situacao else ""
506
+ url += f"&identificadorDocumento={params.identificadorDocumento}" if params.identificadorDocumento else ""
507
+ url += f"&qtdMaxResultados={params.qtd}"
508
+
509
+ response = requests.get(
510
+ url,
511
+ headers=self.headers,
512
+ auth=self.auth,
513
+ timeout=60,
514
+ )
515
+
516
+ if response.status_code == 200:
517
+ return xml_response_to_json(response.text) # Retorna um dicionário
518
+
519
+
520
+ else:
521
+ print(f"Erro ao listar arquivos: {response.status_code}")
522
+ return None
523
+
524
+ def listar_arquivos(self, nivel: Literal['RES', 'BAS', 'COMPL'], inicio: str, situacao: Optional[Literal['REC', 'A_REC']] = None, identificadorDocumento: Optional[str] = None, qtd: int = 100):
525
+ resultados = []
526
+ ultima_data = inicio
527
+
528
+ while True:
529
+ params = ListarArquivosParams(nivel=nivel, inicio=ultima_data, situacao=situacao, identificadorDocumento=identificadorDocumento, qtd=qtd)
530
+
531
+ url = f"{self.base_url}/arquivos?tipoConsulta=AVANC&nivelDetalhe={params.nivel}"
532
+ url += f"&dataHoraInicio={params.inicio}&situacaoTransmissao={params.situacao}" if params.situacao else ""
533
+ url += f"&identificadorDocumento={params.identificadorDocumento}" if params.identificadorDocumento else ""
534
+ url += f"&qtdMaxResultados={params.qtd}"
535
+
536
+ response = requests.get(
537
+ url,
538
+ headers=self.headers,
539
+ auth=self.auth,
540
+ timeout=60,
541
+ )
542
+
543
+ if response.status_code == 200:
544
+ try:
545
+ dados = xml_response_to_json(response.text)
546
+ #print(dados)
547
+ #print(type(dados))
548
+
549
+ if not dados: # Verifica se a lista está vazia
550
+ #print("lista ta vaziaaaa")
551
+ break # Sai do loop se não houver mais dados
552
+ resultados.extend(dados)
553
+ # Verifica se o campo 'DataHoraDisponibilizacao' existe no último registro
554
+ if dados and isinstance(dados, list) and 'DataHoraDisponibilizacao' in dados[-1]:
555
+ ultima_data = dados[-1]['DataHoraDisponibilizacao'] # Atualiza a data para a próxima requisição
556
+ else:
557
+ print("Campo 'DataHoraDisponibilizacao' não encontrado ou estrutura inesperada.")
558
+ break
559
+ except ET.ParseError as e:
560
+ print(f"Erro ao processar XML: {e}")
561
+ break
562
+ else:
563
+ print(f"Erro ao listar arquivos: {response.status_code}")
564
+ break
565
+ return resultados
566
+
567
+ def download_arquivo(self,protocolo:str,filename:str=None):
568
+ """Faz o download de um arquivo de um protocolo especifico
569
+
570
+ Args:
571
+ protocolo (str): protocolo
572
+ filename (str): path+nome do arquivo
573
+
574
+ Returns:
575
+ dict: {"success": bool, "status_code": int, "content": bytes/str}
576
+ """
577
+
578
+ # Validação dos parâmetros
579
+ try:
580
+
581
+ params = DownloadArquivoParams(protocolo=protocolo, filename=filename)
582
+
583
+ except ValidationError as e:
584
+
585
+ return Exception(str(e))
586
+
587
+ url = f"/arquivos/{protocolo}/conteudo"
588
+ response = requests.get(
589
+ self.base_url + url,
590
+ auth=self.auth,
591
+ timeout=60,
592
+ headers={"Connection": "keep-alive"},
593
+ )
594
+
595
+ if response.status_code == 200:
596
+
597
+ if filename is not None:
598
+
599
+ try:
600
+
601
+ with open(filename, "wb") as arquivo:
602
+
603
+ arquivo.write(response.content)
604
+
605
+ except Exception as e:
606
+
607
+ raise Exception(f"Falha ao salvar o arquivo em disco\n{str(e)}")
608
+
609
+ return {"success": True, "status_code": int(response.status_code), "content": response.content }
610
+
611
+ else:
612
+
613
+ return {"success": False, "status_code": int(response.status_code), "content": response.text}
614
+
615
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: csc_cia_stne
3
- Version: 0.0.64
3
+ Version: 0.0.65
4
4
  Summary: Biblioteca do time CSC-CIA utilizada no desenvolvimento de RPAs
5
5
  License: MIT
6
6
  Keywords: karavela,csc,cia,stone,rpa,botcity,stne
@@ -1,6 +1,6 @@
1
1
  csc_cia_stne/__init__.py,sha256=Io-gKis1evws5cHUqyOrcsZKNCQRviYj3zbp__5lgKU,2512
2
2
  csc_cia_stne/bc_correios.py,sha256=pQAnRrcXEMrx3N1MWydZVIhEQLerh3x8-0B045zZIzk,24174
3
- csc_cia_stne/bc_sta.py,sha256=f75HJ7FLIDSJFLDTvvSvCYo9z0HchzP7rDY5WIdiKXY,16830
3
+ csc_cia_stne/bc_sta.py,sha256=bVj7o2oOrAR3V_fSD9ex0CGahLc1U6EgeYetQGUw1-0,25282
4
4
  csc_cia_stne/email.py,sha256=RK_TzWBVnUfpP-s5NvjTJJjzhICy8e2fME9EuaiySMY,8162
5
5
  csc_cia_stne/gcp_bigquery.py,sha256=jYxvqrWDOPkxc05U4aef7V5lL8ptqsE93lfn0dLFyvc,7385
6
6
  csc_cia_stne/google_drive.py,sha256=lgcOd27vk2Mb_wP_fAWIbec-S3MIBKyh4TpRth6REXc,12788
@@ -26,8 +26,8 @@ csc_cia_stne/utilitarios/validations/GoogleDriveValidator.py,sha256=PBo-AV2bjR__
26
26
  csc_cia_stne/utilitarios/validations/ServiceNowValidator.py,sha256=yleKUIo1ZfyloP9fDPNjv3JJXdLcocT81WIgRSYmqEA,14423
27
27
  csc_cia_stne/utilitarios/validations/__init__.py,sha256=O_qyEU2ji3u6LHUXZCXvUFsMpoMWL625qqHTXyXivTA,106
28
28
  csc_cia_stne/utilitarios/validations/web_validator.py,sha256=HYKYSpDv1RvRjZIuwTPt-AbEz-9392MxM_O329iYuSA,5722
29
- csc_cia_stne-0.0.64.dist-info/LICENCE,sha256=LPGMtgKki2C3KEZP7hDhA1HBrlq5JCHkIeStUCLEMx4,1073
30
- csc_cia_stne-0.0.64.dist-info/METADATA,sha256=KYbJwXirJeL6A39Cz8ohmuBV8BD7y_M2E4bCVs3yBBY,1312
31
- csc_cia_stne-0.0.64.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
32
- csc_cia_stne-0.0.64.dist-info/top_level.txt,sha256=ldo7GVv3tQx5KJvwBzdZzzQmjPys2NDVVn1rv0BOF2Q,13
33
- csc_cia_stne-0.0.64.dist-info/RECORD,,
29
+ csc_cia_stne-0.0.65.dist-info/LICENCE,sha256=LPGMtgKki2C3KEZP7hDhA1HBrlq5JCHkIeStUCLEMx4,1073
30
+ csc_cia_stne-0.0.65.dist-info/METADATA,sha256=hq9XBuN_o_bOOi8jaqlctvRBd6Ej8MZ3sZ3gXOJiELQ,1312
31
+ csc_cia_stne-0.0.65.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
32
+ csc_cia_stne-0.0.65.dist-info/top_level.txt,sha256=ldo7GVv3tQx5KJvwBzdZzzQmjPys2NDVVn1rv0BOF2Q,13
33
+ csc_cia_stne-0.0.65.dist-info/RECORD,,