Skip to content

Commit

Permalink
add NautaAuthApi
Browse files Browse the repository at this point in the history
  • Loading branch information
lesclaz committed Dec 1, 2023
1 parent 27f1ba2 commit 99f04d0
Show file tree
Hide file tree
Showing 48 changed files with 2,062 additions and 155 deletions.
9 changes: 9 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
"version" : "5.8.1"
}
},
{
"identity" : "cryptoswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/krzyzanowskim/CryptoSwift.git",
"state" : {
"revision" : "db51c407d3be4a051484a141bf0bff36c43d3b1e",
"version" : "1.8.0"
}
},
{
"identity" : "swiftsoup",
"kind" : "remoteSourceControl",
Expand Down
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.6.4")),
.package(url: "https://github.com/scinfu/SwiftSoup.git", from: "2.6.0"),
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMajor(from: "1.7.2")),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "SuitEtecsaSdk", dependencies: ["Alamofire", "SwiftSoup"]),
name: "SuitEtecsaSdk", dependencies: ["Alamofire", "SwiftSoup", "CryptoSwift"]),
.testTarget(
name: "SuitEtecsaSdkTests",
dependencies: ["SuitEtecsaSdk"]),
Expand Down
97 changes: 42 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,98 +1,85 @@
# SuitEtecsaSdk
Una librería para SuitETECSA escrita en Swift

`SuitEtecsaSdk` es una herramienta diseñada para interactuar con los servicios de [ETECSA](https://www.etecsa.cu/). La librería utiliza técnicas de scraping para acceder a los portales de [acceso a internet](https://secure.etecsa.net:8443/) y de [usuario](https://www.portal.nauta.cu/) de Nauta.
Por ahora, solo hay soporte para el portal cautivo ([el portal de acceso a internet](https://secure.etecsa.net:8443/)); poco a poco se irá añadiendo la interacción con más portales, como: [el portal de usuario](https://www.portal.nauta.cu/) de Nauta, [el portal Nauta](https://www.nauta.cu/) y [el portal de servicios en línea](https://www.tienda.etecsa.cu/).

## Funciones implementadas
- [x] [Secure Etecsa](https://secure.etecsa.net:8443/)

- [x] Iniciar sesión.
- [x] Cerrar sesión.
- [x] Obtener el tiempo disponible en la cuenta.
- [x] Obtener la información de la cuenta.

- [ ] [Portal de Usuario](https://www.portal.nauta.cu/)

- [ ] Iniciar sesión.

- [ ] Obtener información de la cuenta.

- [ ] Recargar la cuenta.

- [ ] Transferir saldo a otra cuenta Nauta.

- [ ] Transferir saldo para el pago de cuota (solo para cuentas Nauta Hogar).

- [ ] Cambiar la contraseña de la cuenta de acceso.

- [ ] Cambiar la contraseña de la cuenta de correo asociada.

- [ ] Obtener las conexiones realizadas en el período `año-mes` especificado.

- [ ] Obtener las recargas realizadas en el período `año-mes` especificado.

- [ ] Obtener las transferencias realizadas en el período `año-mes` especificado.

- [ ] Obtener los pagos de cuotas realizados en el período `año-mes` especificado (solo para cuentas Nauta Hogar).

## Descripción
`SuitEtecsaSdk` es una librería desarrollada en Swift, diseñada para facilitar la interacción con los servicios de la empresa de telecomunicaciones [ETECSA](https://www.etecsa.cu/).

## Características
- **Scraping Avanzado**: Utiliza técnicas de scraping para acceder eficientemente a los portales de [acceso a internet](https://secure.etecsa.net:8443/) y de [usuario de Nauta](https://www.portal.nauta.cu/).
- **Integración con API de Nauta**: Permite la interacción con el [portal Nauta](https://www.nauta.cu/) a través de su API, proporcionando un cliente robusto y fácil de usar.

# Uso
## Instalación
Importa `SuitEtecsaSdk` en tu proyecto

```swift
dependencies: [
.package(url: "https://github.com/suitetecsa/sdk-swift/.git", from: "1.0.0-alpha01")
]
```

Importa `SuitEtecsaSdk`

```swift
import SuitEtecsaSdk
```
## Uso

Conéctate a internet desde la wifi o Nauta Hogar

```swift
switch await ConnectApi.connect(username: "user.name@nauta.com.cu", password: "somePassword") {
case .failure(_): print("Hubo un error")
case .success(let dataSession): print(dataSession)
case .failure(_): print("Hubo un error")
case .success(let dataSession): print(dataSession)
}
```

Obtén el tiempo restante de la cuenta (solo puede hacerse cuando hay una conexión abierta y se poseen los datos de la sesión).

```swift
switch await ConnectApi.getLeftTime(dataSession) {
case .failure(_): print("Hubo un error")
case .success(let time): print(time)
case .failure(_): print("Hubo un error")
case .success(let time): print(time)
}
```

Desconéctate de internet

```swift
switch await ConnectApi.disconnect(dataSession) {
case .failure(_): print("Hubo un error")
case .success(_): print("Sesión cerrada!")
case .failure(_): print("Hubo un error")
case .success(_): print("Sesión cerrada!")
}
```

Obtén la información de la cuenta

```swift
switch await ConnectApi.getInfo(username: "user.name@nauta.com.cu", password: "somePassword") {
case .failure(_): print("Hubo un error")
case .success(let accountInfo): print(accountInfo)
case .failure(_): print("Hubo un error")
case .success(let accountInfo): print(accountInfo)
}
```

Obten la informacion necesaria para iniciar sesion en el portal Nauta

```swift
switch await NautaAuthApi.getCaptcha() {
case .failure(_): print("Hubo un error")
case .success(let cresp):
print(cresp.idRequest)
print(cresp.data)
}
```

Inicia sesion en el portal Nauta

```swift
switch await NautaAuthApi.login(
username: "+5350000000", password: "somePassword", captchaCode: "CAPTCHACODE",
idRequest: cresp.idRequest)
{
case .failure(let err): throw err
case .success(let lresp): print(lresp)
}
```

# Contribución
## Contribución

¡Gracias por tu interés en colaborar con nuestro proyecto! Nos encanta recibir contribuciones de la comunidad y valoramos mucho tu tiempo y esfuerzo.

## Cómo contribuir
### Cómo contribuir

Si estás interesado en contribuir, por favor sigue los siguientes pasos:

Expand All @@ -102,7 +89,7 @@ Si estás interesado en contribuir, por favor sigue los siguientes pasos:
4. Cuando hayas terminado de trabajar en la tarea, crea un pull request explicando los cambios que has realizado y asegurándote de que el código cumple con nuestras directrices de estilo y calidad.
5. Espera a que uno de nuestros colaboradores revise el pull request y lo apruebe o sugiera cambios adicionales.

## Directrices de contribución
### Directrices de contribución

Por favor, asegúrate de seguir nuestras directrices de contribución para que podamos revisar y aprobar tus cambios de manera efectiva:

Expand Down
11 changes: 11 additions & 0 deletions Sources/SuitEtecsaSdk/apps.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
struct ConnectApp {
struct Server {
static let baseUrl = "https://\(connectDomain):8443"
}
}

struct NautaApp {
struct Server {
static let baseURL = "https://www.nauta.cu:5002"
}
}
85 changes: 42 additions & 43 deletions Sources/SuitEtecsaSdk/constants.swift
Original file line number Diff line number Diff line change
@@ -1,48 +1,47 @@

let connectDomain = "secure.etecsa.net"

struct ConnectApp {
struct Server {
static let baseUrl = "https://\(connectDomain):8443"
}
enum HTTPHeaderField: String {
case Authorization = "Authorization"
case Accept = "Accept"
case AcceptLanguage = "Accept-Language"
case AcceptEncoding = "Accept-Encoding"
case ContentType = "Content-Type"
case Connection = "Connection"
case Host = "Host"
case IfNoneMatch = "If-None-Match"
case Origin = "Origin"
case Referer = "Referer"
case SecFetchDest = "Sec-Fetch-Dest"
case SecFetchMode = "Sec-Fetch-Mode"
case SecFetchSite = "Sec-Fetch-Site"
case TE = "TE"
case UserAgent = "User-Agent"
case secChUa = "sec-ch-ua"
case secChUaMobile = "sec-ch-ua-mobile"
case secChUaPlatform = "sec-ch-ua-platform"
case usernameApp = "usernameApp"
case passwordApp = "passwordApp"
}

let userPortalUrlBase = "https://www.portal.nauta.cu/"
let connectPortalUrlBase = "https://\(connectDomain):8443/"

let userPortalUrls: [Action : Any] = [
Action.Login: "user/login/es-es",
Action.LoadUserInformation: "useraaa/user_info",
Action.Recharge: "useraaa/recharge_account",
Action.Transfer: "useraaa/transfer_balance",
Action.PayNautaHome: "useraaa/transfer_nautahogarpaid",
Action.ChangePassword: "useraaa/change_password",
Action.ChangeEmailPassword: "mail/change_password",
Action.GetConnections : [
"base": "useraaa/service_detail/",
"summary": "useraaa/service_detail_summary/",
"list": "useraaa/service_detail_list/"
],
Action.GetRecharges: [
"base": "useraaa/recharge_detail/",
"summary": "useraaa/recharge_detail_summary/",
"list": "useraaa/recharge_detail_list/"
],
Action.GetTransfers: [
"base": "useraaa/transfer_detail/",
"summary": "useraaa/transfer_detail_summary/",
"list": "useraaa/transfer_detail_list/"
],
Action.GetQuotesPaid: [
"base": "useraaa/nautahogarpaid_detail/",
"summary": "useraaa/nautahogarpaid_detail_summary/",
"list": "useraaa/nautahogarpaid_detail_list/"
],
Action.Logout: "user/logout"
]

let connectPortalUrls = [
Action.Logout: "LogoutServlet",
Action.LoadUserInformation: "EtecsaQueryServlet",
Action.CheckConnection: "http://www.cubadebate.cu/"
]
enum HTTPHeaderFieldValues: String {
case Accept = "*/*"
case AcceptLanguage = "es,es-US;q=0.9,es-419;q=0.8,en;q=0.7"
case AcceptEncoding = "gzip, deflate, br"
case ContentType = "application/json"
case Connection = "keep-alive"
case HostNauta = "www.nauta.cu:5002"
case HostET = "www.tienda.etecsa.cu"
case IfNoneMatch = "W/\"4573-cba3C56jjnn1stlozXGQSy4RngA\""
case OriginNauta = "https://www.nauta.cu"
case OriginEtecsa = "https://www.tienda.etecsa.cu"
case SecFetchDest = "empty"
case SecFetchMode = "cors"
case SecFetchSite = "same-site"
case TE = "trailers"
case UserAgent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0"
case secChUa = "Not_A Brand\";v=\"99\", \"Google Chrome\";v=\"109\", \"Chromium\";v=\"109\""
case secChUaMobile = "?0"
case secChUaPlatform = "\"Windows\""
case usernameApp = "portal"
}
8 changes: 0 additions & 8 deletions Sources/SuitEtecsaSdk/entity/connection.swift

This file was deleted.

9 changes: 0 additions & 9 deletions Sources/SuitEtecsaSdk/entity/connection_summary.swift

This file was deleted.

8 changes: 8 additions & 0 deletions Sources/SuitEtecsaSdk/entity/etecsa_promos/promotion.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Foundation

public struct Promotion {
public let backgroundUrl: String
public let imageSvg: String
public let url: String
public var imageData: Data?
}
37 changes: 37 additions & 0 deletions Sources/SuitEtecsaSdk/entity/nauta/auth/JSONSchemaSupport.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Foundation

// MARK: - Helper functions for creating encoders and decoders

func newJSONDecoder() -> JSONDecoder {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
let container = try decoder.singleValueContainer()
let dateStr = try container.decode(String.self)

let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
if let date = formatter.date(from: dateStr) {
return date
}
throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not decode date"))
})
return decoder
}

func newJSONEncoder() -> JSONEncoder {
let encoder = JSONEncoder()
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
encoder.dateEncodingStrategy = .formatted(formatter)
return encoder
}
26 changes: 26 additions & 0 deletions Sources/SuitEtecsaSdk/entity/nauta/auth/captcha_response.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Foundation

// Define una estructura pública 'CaptchaResponse' que conforma al protocolo 'Codable'.
public struct CaptchaResponse: Codable {
// Propiedades públicas para almacenar la identificación de la solicitud y los datos de la respuesta.
public let idRequest: String
public let data: String

// Enumeración interna para definir las claves de codificación personalizadas.
enum CodingKeys: String, CodingKey {
// Asigna la clave 'text' del JSON a la propiedad 'idRequest'.
case idRequest = "text"
// Asigna la clave 'data' del JSON a la propiedad 'data'.
case data = "data"
}

// Inicializador personalizado para decodificar desde un tipo 'Decoder'.
public init(from decoder: Decoder) throws {
// Crea un contenedor de decodificación utilizando las claves definidas.
let container = try decoder.container(keyedBy: CodingKeys.self)
// Decodifica el valor asociado con la clave 'idRequest' (originalmente 'text' en JSON).
idRequest = try container.decode(String.self, forKey: .idRequest)
// Decodifica el valor asociado con la clave 'data'.
data = try container.decode(String.self, forKey: .data)
}
}
Loading

0 comments on commit 99f04d0

Please sign in to comment.