update tamaulipas
This commit is contained in:
parent
b61a638078
commit
c8426f005b
4
.obsidian/appearance.json
vendored
4
.obsidian/appearance.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"cssTheme": "",
|
||||
"baseFontSizeAction": true,
|
||||
"baseFontSize": 21,
|
||||
"theme": "obsidian"
|
||||
"baseFontSize": 30,
|
||||
"theme": "moonstone"
|
||||
}
|
4
.obsidian/core-plugins.json
vendored
4
.obsidian/core-plugins.json
vendored
@ -27,5 +27,7 @@
|
||||
"file-recovery": true,
|
||||
"publish": false,
|
||||
"sync": true,
|
||||
"webviewer": false
|
||||
"webviewer": false,
|
||||
"footnotes": false,
|
||||
"bases": true
|
||||
}
|
35
.obsidian/workspace.json
vendored
35
.obsidian/workspace.json
vendored
@ -53,7 +53,7 @@
|
||||
"state": {
|
||||
"type": "search",
|
||||
"state": {
|
||||
"query": "",
|
||||
"query": "pagos",
|
||||
"matchingCase": false,
|
||||
"explainSearch": false,
|
||||
"collapseAll": false,
|
||||
@ -160,6 +160,7 @@
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
"bases:Crear nueva base": false,
|
||||
"switcher:Abrir selector rápido": false,
|
||||
"graph:Abrir vista gráfica": false,
|
||||
"canvas:Crear nuevo lienzo": false,
|
||||
@ -168,12 +169,26 @@
|
||||
"command-palette:Abrir paleta de comandos": false
|
||||
}
|
||||
},
|
||||
"active": "5ff6ca2da58ba6f5",
|
||||
"active": "db862854e8b7e53a",
|
||||
"lastOpenFiles": [
|
||||
"ELIMINAR/FIVE_MUSEO.docx.md",
|
||||
"ELIMINAR/Sin título.md",
|
||||
"ELIMINAR/DOF_LINEAMIENTOS para el ciclo de gestión de los programas y proyectos de inversión, a cargo de las dependencias y entidades de la Administración Pública Federal..md",
|
||||
"DIX-Notes/Otras_varias/Pagos Jesús.md",
|
||||
"ELIMINAR",
|
||||
"eliminar.md",
|
||||
"Agencia_Espacial_Mexicana/Excel-Macros_AEM/Tabla de Excel a Markdown.md",
|
||||
"DIX-Notes/INSTALAR TESSERACT-OCT.md",
|
||||
"DIX-Notes/dns arrancar con el sistema.md",
|
||||
"DIX-Notes/notas_express.md",
|
||||
"DIX-Notes/bash profile.md",
|
||||
"Agencia_Espacial_Mexicana/Registro_Proyecto_Cartera_Inversion/1.- Análisis Financiero Sistema Satelital de Telecomunicaciones..md",
|
||||
"DIX-Notes/DDNS RASTREO CON CLOUDFLARE.md",
|
||||
"DIX-Notes/Wireguard con obfuscación.md",
|
||||
"DIX-Notes/script_bash_servers/crontab.md",
|
||||
"DIX-Notes/SERVERS - DIX/adjuntos/~$servers.xlsm",
|
||||
"DIX-Notes/SERVERS - DIX/adjuntos/C87ED000",
|
||||
"DIX-Notes/SERVERS - DIX/SERVERS DIX.md",
|
||||
"DIX-Notes/script_bash_servers/crontab.md",
|
||||
"DIX-Notes/script_bash_servers/scripts_linux/shutdown_weekends.sh",
|
||||
"DIX-Notes/script_bash_servers/scripts_linux/shutdown.sh",
|
||||
"DIX-Notes/script_bash_servers/scripts_linux/cron.log",
|
||||
@ -181,19 +196,13 @@
|
||||
"DIX-Notes/script_bash_servers/scripts_linux/history_log.txt",
|
||||
"DIX-Notes/script_bash_servers/scripts_linux",
|
||||
"DIX-Notes/script_bash_servers",
|
||||
"DIX-Notes/SERVERS - DIX/adjuntos/6C708000",
|
||||
"DIX-Notes/dns arrancar con el sistema.md",
|
||||
"Agencia_Espacial_Mexicana/notas_express.md",
|
||||
"DIX-Notes/Sin nombre",
|
||||
"Agencia_Espacial_Mexicana/ELIMINAR_NOTAS/3. Museo de las Telecomunicaciones - PPI_.md",
|
||||
"DIX-Notes/notas_express.md",
|
||||
"Agencia_Espacial_Mexicana/DEFINICIONES Y EXPLICACIONES PROYECTOS CARTERA DE INVERSIÓN.md",
|
||||
"DIX-Notes/Transcribir Videos (WSL).md",
|
||||
"DIX-Notes/DIX_Cluster.canvas",
|
||||
"Sin título.canvas",
|
||||
"DIX-Notes/DDNS RASTREO CON CLOUDFLARE.md",
|
||||
"DIX-Notes/corregir error ip.xala.dev vs dix-ip.duckdns.org.md",
|
||||
"Agencia_Espacial_Mexicana/Excel-Macros_AEM/Tabla de Excel a Markdown.md",
|
||||
"Agencia_Espacial_Mexicana/Excel-Macros_AEM/Prorrateo.md",
|
||||
"Agencia_Espacial_Mexicana/Estatuto Orgánico AEM/Estatuto Orgánico AEM.md",
|
||||
"trabajar_script_mc_backup.md",
|
||||
@ -201,14 +210,6 @@
|
||||
"Install_n8n.md",
|
||||
"bash profile.md",
|
||||
"DIX_Cluster.canvas",
|
||||
"Otras_varias/Jellyfin en ubuntu server 24.04.md",
|
||||
"Otras_varias/Notificaciones con ntfy.sh.md",
|
||||
"Otras_varias/Servidor SAMBA.md",
|
||||
"Otras_varias/Pagos Jesús.md",
|
||||
"Otras_varias/SSL red local con HAProxy.md",
|
||||
"Otras_varias/Visualización carga de trabajo servers.md",
|
||||
"Bash_functions/Script_sincronizar_obsidian.md",
|
||||
"Bash_functions/ip_device.md",
|
||||
"Agencia_Espacial_Mexicana/Cursos_Capacitación/Introducción a la Administración Pública Federal/adjuntos/Pasted image 20250801164816.png",
|
||||
"Agencia_Espacial_Mexicana/Cursos_Capacitación/Introducción a la Administración Pública Federal/adjuntos/Pasted image 20250801164759.png",
|
||||
"Agencia_Espacial_Mexicana/Cursos_Capacitación/Introducción a la Administración Pública Federal/adjuntos/Pasted image 20250801164742.png",
|
||||
|
@ -1,84 +1,84 @@
|
||||
Código de VBA para convertir una tabla de excel a un formato markdown
|
||||
|
||||
```vba
|
||||
' activar la referencia de Microsoft Forms 2.0 Object Library (solo la primera vez)
|
||||
|
||||
Option Explicit
|
||||
|
||||
Sub rangeToMarkDown()
|
||||
|
||||
Dim cell As Range
|
||||
Dim selectedRange As Range
|
||||
Set selectedRange = Application.Selection
|
||||
|
||||
If selectedRange Is Nothing Then
|
||||
MsgBox "Selecciona un rango antes de ejecutar la macro.", vbExclamation
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
Dim rowCounter As Integer
|
||||
Dim columnCounter As Integer
|
||||
Dim totalColumns As Integer
|
||||
Dim currentColumnWidth As Integer
|
||||
|
||||
totalColumns = selectedRange.Columns.Count
|
||||
|
||||
Dim columnWidth(1 To 50) As Integer ' Máximo 50 columnas
|
||||
Dim markdown As String
|
||||
Dim i As Integer, j As Integer, k As Integer
|
||||
Dim extraSpaces As Integer
|
||||
Dim currentLine As String
|
||||
|
||||
' Inicializa anchos de columna
|
||||
For i = 1 To totalColumns
|
||||
columnWidth(i) = 0
|
||||
Next i
|
||||
|
||||
' Calcular el ancho máximo de cada columna
|
||||
For Each Row In selectedRange.Rows
|
||||
columnCounter = 1
|
||||
For Each cell In Row.Cells
|
||||
currentColumnWidth = Len(CStr(cell.Text))
|
||||
If currentColumnWidth > columnWidth(columnCounter) Then
|
||||
columnWidth(columnCounter) = currentColumnWidth
|
||||
End If
|
||||
columnCounter = columnCounter + 1
|
||||
Next cell
|
||||
Next Row
|
||||
|
||||
' Construir tabla Markdown
|
||||
rowCounter = 0
|
||||
For Each Row In selectedRange.Rows
|
||||
columnCounter = 1
|
||||
currentLine = "|"
|
||||
For Each cell In Row.Cells
|
||||
currentColumnWidth = columnWidth(columnCounter)
|
||||
currentLine = currentLine & " " & cell.Text & _
|
||||
Space(currentColumnWidth - Len(CStr(cell.Text))) & " |"
|
||||
columnCounter = columnCounter + 1
|
||||
Next cell
|
||||
markdown = markdown & currentLine & vbCrLf
|
||||
|
||||
' Agrega línea separadora después del encabezado
|
||||
If rowCounter = 0 Then
|
||||
currentLine = "|"
|
||||
For j = 1 To totalColumns
|
||||
currentLine = currentLine & " " & String(columnWidth(j), "-") & " |"
|
||||
Next j
|
||||
markdown = markdown & currentLine & vbCrLf
|
||||
End If
|
||||
|
||||
rowCounter = rowCounter + 1
|
||||
Next Row
|
||||
|
||||
' Copiar al portapapeles
|
||||
Dim clipboard As New DataObject
|
||||
clipboard.SetText markdown
|
||||
clipboard.PutInClipboard
|
||||
|
||||
MsgBox "? Tabla Markdown copiada al portapapeles.", vbInformation
|
||||
|
||||
End Sub
|
||||
|
||||
```
|
||||
|
||||
Código de VBA para convertir una tabla de excel a un formato markdown
|
||||
|
||||
```vba
|
||||
' activar la referencia de Microsoft Forms 2.0 Object Library (solo la primera vez)
|
||||
|
||||
Option Explicit
|
||||
|
||||
Sub rangeToMarkDown()
|
||||
|
||||
Dim cell As Range
|
||||
Dim selectedRange As Range
|
||||
Set selectedRange = Application.Selection
|
||||
|
||||
If selectedRange Is Nothing Then
|
||||
MsgBox "Selecciona un rango antes de ejecutar la macro.", vbExclamation
|
||||
Exit Sub
|
||||
End If
|
||||
|
||||
Dim rowCounter As Integer
|
||||
Dim columnCounter As Integer
|
||||
Dim totalColumns As Integer
|
||||
Dim currentColumnWidth As Integer
|
||||
|
||||
totalColumns = selectedRange.Columns.Count
|
||||
|
||||
Dim columnWidth(1 To 50) As Integer ' Máximo 50 columnas
|
||||
Dim markdown As String
|
||||
Dim i As Integer, j As Integer, k As Integer
|
||||
Dim extraSpaces As Integer
|
||||
Dim currentLine As String
|
||||
|
||||
' Inicializa anchos de columna
|
||||
For i = 1 To totalColumns
|
||||
columnWidth(i) = 0
|
||||
Next i
|
||||
|
||||
' Calcular el ancho máximo de cada columna
|
||||
For Each Row In selectedRange.Rows
|
||||
columnCounter = 1
|
||||
For Each cell In Row.Cells
|
||||
currentColumnWidth = Len(CStr(cell.Text))
|
||||
If currentColumnWidth > columnWidth(columnCounter) Then
|
||||
columnWidth(columnCounter) = currentColumnWidth
|
||||
End If
|
||||
columnCounter = columnCounter + 1
|
||||
Next cell
|
||||
Next Row
|
||||
|
||||
' Construir tabla Markdown
|
||||
rowCounter = 0
|
||||
For Each Row In selectedRange.Rows
|
||||
columnCounter = 1
|
||||
currentLine = "|"
|
||||
For Each cell In Row.Cells
|
||||
currentColumnWidth = columnWidth(columnCounter)
|
||||
currentLine = currentLine & " " & cell.Text & _
|
||||
Space(currentColumnWidth - Len(CStr(cell.Text))) & " |"
|
||||
columnCounter = columnCounter + 1
|
||||
Next cell
|
||||
markdown = markdown & currentLine & vbCrLf
|
||||
|
||||
' Agrega línea separadora después del encabezado
|
||||
If rowCounter = 0 Then
|
||||
currentLine = "|"
|
||||
For j = 1 To totalColumns
|
||||
currentLine = currentLine & " " & String(columnWidth(j), "-") & " |"
|
||||
Next j
|
||||
markdown = markdown & currentLine & vbCrLf
|
||||
End If
|
||||
|
||||
rowCounter = rowCounter + 1
|
||||
Next Row
|
||||
|
||||
' Copiar al portapapeles
|
||||
Dim clipboard As New DataObject
|
||||
clipboard.SetText markdown
|
||||
clipboard.PutInClipboard
|
||||
|
||||
MsgBox "? Tabla Markdown copiada al portapapeles.", vbInformation
|
||||
|
||||
End Sub
|
||||
|
||||
```
|
||||
|
||||
|
@ -1,36 +1,36 @@
|
||||
|
||||
## 1.- Información del Proyecto
|
||||
|
||||
### 1.1.- Datos Generales
|
||||
|
||||
**Nombre del proyecto:** Sistema Satelital de Telecomunicaciones.
|
||||
**Descripción del Proyecto:** Renovar y fortalecer las capacidades satelitales nacionales mediante una coordinación integral de actividades relacionadas a las telecomunicaciones espaciales que permita desplegar un nuevo satélite de telecomunicaciones, ampliar su uso, así como garantizar su sostenibilidad operativa.
|
||||
**Presupuesto:** $13,785,000,000.00 (Trece mil setecientos ochenta y cinco millones de pesos 00/100 MXN)
|
||||
**Tiempo de vida del Proyecto (años):** 15 una vez que el satélite esté en órbita.
|
||||
**Tiempo inicial preparativos previo al lanzamiento (años):** 5 (2026 - 2030)
|
||||
**Monto a ejercer de forma anual:** $2,757,000,000.00 (Dos mil setecientos cincuenta y siete millones de pesos 00/100 MXN)
|
||||
|
||||
### 1.2.- Costos de Inversión Inicial
|
||||
|
||||
Para la estimación de los costos de inversión se toma como referencia los datos de los documentos: "Libro Blanco Mexsat.pdf" y "2013_0432_a.pdf" los cual está en la carpeta de "Anexos Proyecto 1", para la estimación presupuestal se consideran los siguientes conceptos mencionados en los documentos de referencia los cuales son costos al 2015:
|
||||
|
||||
Tabla 1.2.1
|
||||
|
||||
| Concepto de Gasto | Costo USD | Costo MXN |
|
||||
| ------------------------------------------ | ------------ | ------------ |
|
||||
| Fabricación del satélite | $292,200,000 | $0 |
|
||||
| Seguro en órbita (2016–2017) | $272,914,800 | $0 |
|
||||
| Lanzamiento del satélite (Atlas V - LMCLS) | $148,250,000 | $0 |
|
||||
| Seguro lanzamiento + primer año | $24,605,403 | $0 |
|
||||
| Terminales satelitales | $4,500,000 | $0 |
|
||||
| Mantenimiento y operación | $0 | $105,494,451 |
|
||||
| Consultoría técnica terminales móviles | $2,203,200 | $0 |
|
||||
| Desarrollo terminales aeronáuticas | $0 | $20,000,000 |
|
||||
| Almacenamiento | $5,400,000 | $0 |
|
||||
| Total | $750,073,403 | $125,494,451 |
|
||||
|
||||
Para actualizar los valores que se pagaron en USD, se le suma la tasa de inflación de 2015 al 2025 la cual puede ser consultada en
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 1.- Información del Proyecto
|
||||
|
||||
### 1.1.- Datos Generales
|
||||
|
||||
**Nombre del proyecto:** Sistema Satelital de Telecomunicaciones.
|
||||
**Descripción del Proyecto:** Renovar y fortalecer las capacidades satelitales nacionales mediante una coordinación integral de actividades relacionadas a las telecomunicaciones espaciales que permita desplegar un nuevo satélite de telecomunicaciones, ampliar su uso, así como garantizar su sostenibilidad operativa.
|
||||
**Presupuesto:** $13,785,000,000.00 (Trece mil setecientos ochenta y cinco millones de pesos 00/100 MXN)
|
||||
**Tiempo de vida del Proyecto (años):** 15 una vez que el satélite esté en órbita.
|
||||
**Tiempo inicial preparativos previo al lanzamiento (años):** 5 (2026 - 2030)
|
||||
**Monto a ejercer de forma anual:** $2,757,000,000.00 (Dos mil setecientos cincuenta y siete millones de pesos 00/100 MXN)
|
||||
|
||||
### 1.2.- Costos de Inversión Inicial
|
||||
|
||||
Para la estimación de los costos de inversión se toma como referencia los datos de los documentos: "Libro Blanco Mexsat.pdf" y "2013_0432_a.pdf" los cual está en la carpeta de "Anexos Proyecto 1", para la estimación presupuestal se consideran los siguientes conceptos mencionados en los documentos de referencia los cuales son costos al 2015:
|
||||
|
||||
Tabla 1.2.1
|
||||
|
||||
| Concepto de Gasto | Costo USD | Costo MXN |
|
||||
| ------------------------------------------ | ------------ | ------------ |
|
||||
| Fabricación del satélite | $292,200,000 | $0 |
|
||||
| Seguro en órbita (2016–2017) | $272,914,800 | $0 |
|
||||
| Lanzamiento del satélite (Atlas V - LMCLS) | $148,250,000 | $0 |
|
||||
| Seguro lanzamiento + primer año | $24,605,403 | $0 |
|
||||
| Terminales satelitales | $4,500,000 | $0 |
|
||||
| Mantenimiento y operación | $0 | $105,494,451 |
|
||||
| Consultoría técnica terminales móviles | $2,203,200 | $0 |
|
||||
| Desarrollo terminales aeronáuticas | $0 | $20,000,000 |
|
||||
| Almacenamiento | $5,400,000 | $0 |
|
||||
| Total | $750,073,403 | $125,494,451 |
|
||||
|
||||
Para actualizar los valores que se pagaron en USD, se le suma la tasa de inflación de 2015 al 2025 la cual puede ser consultada en
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,208 +1,208 @@
|
||||
Para crear un script que rastree nuestra ip pública con ayuda de cloudflare vamos a necesitar los siguientes datos:
|
||||
|
||||
```bash
|
||||
ZONE_ID=""
|
||||
RECORD_ID=""
|
||||
API_TOKEN=""
|
||||
EMAIL=""
|
||||
DOMAIN=""
|
||||
```
|
||||
|
||||
Para obtener el `ZONE_ID`, te recomiendo crear un registro de un subdominio en tu perfil de cloudflare, ejemplo registro:
|
||||
|
||||
Tipo: A
|
||||
Nombre: mi-ip
|
||||
Contenido: 187.123.32.45
|
||||
> En **contenido** va la ip pública.
|
||||
|
||||
|
||||
Una vez creado tu subdomino, debemos crear API Token, vamos a **Perfil > Tokens de API > Crear Token > Editar zona DNS > (sección Recursos de Zona) opción 1: Incluir, Opción 2: Zona específica, Opción 3: selecciona tu dominio > Ir a resumen**, eso te dará tu ==`API_TOKEN` ==,
|
||||
|
||||
Una Vez tengas el `API Token` vamos a obtener el `ZONE_ID`, en tu consola ejecuta el comando:
|
||||
```bash
|
||||
curl -X GET "https://api.cloudflare.com/client/v4/zones?name=TU-DOMINIO-NO-SUBDOMINIO.com" \
|
||||
-H "Authorization: Bearer TU-API-TOKEN" \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
Ejecuta ese comando en tu consola linux, la salida será algo como:
|
||||
|
||||
```bash
|
||||
{"result":[
|
||||
{"id":"TU-ZONE-ID","name":"TU-DOMINIO-NO-SUBDOMINIO.com","status":"active","paused":false, ... (más cosas)
|
||||
```
|
||||
|
||||
Del primer bloque verás un diccionario con una clave `id`, el valor es tu ==`ZONE_ID`==, para obtener el `RECORD_ID` es un poco similar al paso anterior, el comando a ejecutar es:
|
||||
```bash
|
||||
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/TU-ZONE-ID/dns_records?type=A&name=TU-SUBDOMINIO.COM" \
|
||||
-H "Authorization: Bearer TU-API-TOKEN" \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
Obtendrás una respuesta como esta:
|
||||
```bash
|
||||
{"result":[{"id":"TU-RECORD-ID","name":"TU-SUBDOMINIO.COM","type":"A", ... (más cosas)
|
||||
```
|
||||
Del primer bloque verás un diccionario, con una clave `id`, el valor es tu ==`RECORD_ID`==, en el valor de ==`EMAIL`==, coloca el email con el que inicias sesión en tu cuenta de cloudflare, y en ==`DOMAIN`== coloca el nombre de tu subdominio, una vez que ya tenemos esos datos podemos continuar con el script completo:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="abcdef1234567890abcdef1234567890"
|
||||
RECORD_ID="c3f9a7e6b24d48b2a6f481c2a9d2f9c1"
|
||||
API_TOKEN="e4b-2f6c9a81d4b87f0a927ec5b3c6a59f0e7a45b"
|
||||
EMAIL="tu.email@mail.com"
|
||||
DOMAIN="subdominio.dominio.com"
|
||||
|
||||
# Obtener IP actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP actual del DNS
|
||||
DNS_IP=$(dig +short $DOMAIN @1.1.1.1)
|
||||
|
||||
# Comparar
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
echo "La IP cambió: $DNS_IP → $IP. Actualizando en Cloudflare..."
|
||||
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":true}" | jq
|
||||
else
|
||||
echo "La IP no ha cambiado: $IP"
|
||||
fi
|
||||
```
|
||||
|
||||
==Versión Mejorada==
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="e70540b388ab9d20bfe27d9a31cd474b"
|
||||
RECORD_ID="5d05a48c9d76c7767302442fffa096bd"
|
||||
API_TOKEN="9BD-GB7PtGd5pgXTEBxnv3k1eJlJYJoIWx9HgLLs"
|
||||
DOMAIN="ip.xala.dev"
|
||||
|
||||
# Obtener IP pública actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP configurada en Cloudflare (usando la API)
|
||||
DNS_IP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" | jq -r '.result.content')
|
||||
|
||||
# Comparar
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
echo "La IP cambió: $DNS_IP → $IP. Actualizando en Cloudflare..."
|
||||
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":true}" | jq
|
||||
else
|
||||
echo "La IP no ha cambiado: $IP"
|
||||
fi
|
||||
```
|
||||
|
||||
==LA MEJOR VERSIÓN==
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# echo "[$(date '+%Y-%m-%d %H:%M:%S')] Ejecutando actualización de IP..."
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="e70540b388ab9d20bfe27d9a31cd474b"
|
||||
RECORD_ID="5d05a48c9d76c7767302442fffa096bd"
|
||||
API_TOKEN="9BD-GB7PtGd5pgXTEBxnv3k1eJlJYJoIWx9HgLLs"
|
||||
DOMAIN="ip.xala.dev"
|
||||
|
||||
|
||||
# Obtener IP pública actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP registrada en Cloudflare
|
||||
DNS_IP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" | jq -r '.result.content')
|
||||
|
||||
# Comparar
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
echo "La IP cambió: $DNS_IP → $IP. Actualizando en Cloudflare..."
|
||||
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":true}" | jq
|
||||
else
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] La IP no ha cambiado: $IP"
|
||||
fi
|
||||
|
||||
# echo "[$(date '+%Y-%m-%d %H:%M:%S')] Fin de ejecución."
|
||||
```
|
||||
|
||||
**integra ntfy, que llegue un mensaje cuando cambie la ip**
|
||||
|
||||
|
||||
==MEJORADO, CON PROXIED FALSE==
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="e70540b388ab9d20bfe27d9a31cd474b"
|
||||
RECORD_ID="5d05a48c9d76c7767302442fffa096bd"
|
||||
API_TOKEN="9BD-GB7PtGd5pgXTEBxnv3k1eJlJYJoIWx9HgLLs"
|
||||
DOMAIN="ip.xala.dev"
|
||||
|
||||
|
||||
# Obtener IP pública actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP registrada actualmente en Cloudflare
|
||||
DNS_RECORD=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json")
|
||||
|
||||
DNS_IP=$(echo "$DNS_RECORD" | jq -r '.result.content')
|
||||
|
||||
# validaciones
|
||||
if [ -z "$IP" ]; then
|
||||
# Notificación vía ntfy
|
||||
# curl -d "🌎 [$(date '+%Y-%m-%d %H:%M:%S')] IP actualizada: $DNS_IP → $IP" ntfy.xala.dev/alerts
|
||||
curl -d "🚨 [$(date '+%Y-%m-%d %H:%M:%S')] No se pudo obtener la IP pública." ntfy.xala.dev/alerts
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
curl -d "🌐 La IP ha cambiado: $DNS_IP → $IP. Actualizando en Cloudflare..." ntfy.xala.dev/alerts
|
||||
|
||||
UPDATE_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{
|
||||
\"type\": \"A\",
|
||||
\"name\": \"$DOMAIN\",
|
||||
\"content\": \"$IP\",
|
||||
\"ttl\": 1,
|
||||
\"proxied\": false
|
||||
}")
|
||||
|
||||
SUCCESS=$(echo "$UPDATE_RESPONSE" | jq -r '.success')
|
||||
|
||||
if [ "$SUCCESS" == "true" ]; then
|
||||
curl -d "🌎 [$(date '+%Y-%m-%d %H:%M:%S')] IP actualizada: $DNS_IP → $IP" ntfy.xala.dev/alerts
|
||||
else
|
||||
curl -d "🚨 [$(date '+%Y-%m-%d %H:%M:%S')] Falló la actualización en Cloudflare." ntfy.xala.dev/alerts
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ [$(date '+%Y-%m-%d %H:%M:%S')] La IP no ha cambiado: $IP"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Para crear un script que rastree nuestra ip pública con ayuda de cloudflare vamos a necesitar los siguientes datos:
|
||||
|
||||
```bash
|
||||
ZONE_ID=""
|
||||
RECORD_ID=""
|
||||
API_TOKEN=""
|
||||
EMAIL=""
|
||||
DOMAIN=""
|
||||
```
|
||||
|
||||
Para obtener el `ZONE_ID`, te recomiendo crear un registro de un subdominio en tu perfil de cloudflare, ejemplo registro:
|
||||
|
||||
Tipo: A
|
||||
Nombre: mi-ip
|
||||
Contenido: 187.123.32.45
|
||||
> En **contenido** va la ip pública.
|
||||
|
||||
|
||||
Una vez creado tu subdomino, debemos crear API Token, vamos a **Perfil > Tokens de API > Crear Token > Editar zona DNS > (sección Recursos de Zona) opción 1: Incluir, Opción 2: Zona específica, Opción 3: selecciona tu dominio > Ir a resumen**, eso te dará tu ==`API_TOKEN` ==,
|
||||
|
||||
Una Vez tengas el `API Token` vamos a obtener el `ZONE_ID`, en tu consola ejecuta el comando:
|
||||
```bash
|
||||
curl -X GET "https://api.cloudflare.com/client/v4/zones?name=TU-DOMINIO-NO-SUBDOMINIO.com" \
|
||||
-H "Authorization: Bearer TU-API-TOKEN" \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
Ejecuta ese comando en tu consola linux, la salida será algo como:
|
||||
|
||||
```bash
|
||||
{"result":[
|
||||
{"id":"TU-ZONE-ID","name":"TU-DOMINIO-NO-SUBDOMINIO.com","status":"active","paused":false, ... (más cosas)
|
||||
```
|
||||
|
||||
Del primer bloque verás un diccionario con una clave `id`, el valor es tu ==`ZONE_ID`==, para obtener el `RECORD_ID` es un poco similar al paso anterior, el comando a ejecutar es:
|
||||
```bash
|
||||
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/TU-ZONE-ID/dns_records?type=A&name=TU-SUBDOMINIO.COM" \
|
||||
-H "Authorization: Bearer TU-API-TOKEN" \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
Obtendrás una respuesta como esta:
|
||||
```bash
|
||||
{"result":[{"id":"TU-RECORD-ID","name":"TU-SUBDOMINIO.COM","type":"A", ... (más cosas)
|
||||
```
|
||||
Del primer bloque verás un diccionario, con una clave `id`, el valor es tu ==`RECORD_ID`==, en el valor de ==`EMAIL`==, coloca el email con el que inicias sesión en tu cuenta de cloudflare, y en ==`DOMAIN`== coloca el nombre de tu subdominio, una vez que ya tenemos esos datos podemos continuar con el script completo:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="abcdef1234567890abcdef1234567890"
|
||||
RECORD_ID="c3f9a7e6b24d48b2a6f481c2a9d2f9c1"
|
||||
API_TOKEN="e4b-2f6c9a81d4b87f0a927ec5b3c6a59f0e7a45b"
|
||||
EMAIL="tu.email@mail.com"
|
||||
DOMAIN="subdominio.dominio.com"
|
||||
|
||||
# Obtener IP actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP actual del DNS
|
||||
DNS_IP=$(dig +short $DOMAIN @1.1.1.1)
|
||||
|
||||
# Comparar
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
echo "La IP cambió: $DNS_IP → $IP. Actualizando en Cloudflare..."
|
||||
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":true}" | jq
|
||||
else
|
||||
echo "La IP no ha cambiado: $IP"
|
||||
fi
|
||||
```
|
||||
|
||||
==Versión Mejorada==
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="e70540b388ab9d20bfe27d9a31cd474b"
|
||||
RECORD_ID="5d05a48c9d76c7767302442fffa096bd"
|
||||
API_TOKEN="9BD-GB7PtGd5pgXTEBxnv3k1eJlJYJoIWx9HgLLs"
|
||||
DOMAIN="ip.xala.dev"
|
||||
|
||||
# Obtener IP pública actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP configurada en Cloudflare (usando la API)
|
||||
DNS_IP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" | jq -r '.result.content')
|
||||
|
||||
# Comparar
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
echo "La IP cambió: $DNS_IP → $IP. Actualizando en Cloudflare..."
|
||||
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":true}" | jq
|
||||
else
|
||||
echo "La IP no ha cambiado: $IP"
|
||||
fi
|
||||
```
|
||||
|
||||
==LA MEJOR VERSIÓN==
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# echo "[$(date '+%Y-%m-%d %H:%M:%S')] Ejecutando actualización de IP..."
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="e70540b388ab9d20bfe27d9a31cd474b"
|
||||
RECORD_ID="5d05a48c9d76c7767302442fffa096bd"
|
||||
API_TOKEN="9BD-GB7PtGd5pgXTEBxnv3k1eJlJYJoIWx9HgLLs"
|
||||
DOMAIN="ip.xala.dev"
|
||||
|
||||
|
||||
# Obtener IP pública actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP registrada en Cloudflare
|
||||
DNS_IP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" | jq -r '.result.content')
|
||||
|
||||
# Comparar
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
echo "La IP cambió: $DNS_IP → $IP. Actualizando en Cloudflare..."
|
||||
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$IP\",\"ttl\":120,\"proxied\":true}" | jq
|
||||
else
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] La IP no ha cambiado: $IP"
|
||||
fi
|
||||
|
||||
# echo "[$(date '+%Y-%m-%d %H:%M:%S')] Fin de ejecución."
|
||||
```
|
||||
|
||||
**integra ntfy, que llegue un mensaje cuando cambie la ip**
|
||||
|
||||
|
||||
==MEJORADO, CON PROXIED FALSE==
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
# Configuración
|
||||
ZONE_ID="e70540b388ab9d20bfe27d9a31cd474b"
|
||||
RECORD_ID="5d05a48c9d76c7767302442fffa096bd"
|
||||
API_TOKEN="9BD-GB7PtGd5pgXTEBxnv3k1eJlJYJoIWx9HgLLs"
|
||||
DOMAIN="ip.xala.dev"
|
||||
|
||||
|
||||
# Obtener IP pública actual
|
||||
IP=$(curl -s https://api.ipify.org)
|
||||
|
||||
# Obtener IP registrada actualmente en Cloudflare
|
||||
DNS_RECORD=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json")
|
||||
|
||||
DNS_IP=$(echo "$DNS_RECORD" | jq -r '.result.content')
|
||||
|
||||
# validaciones
|
||||
if [ -z "$IP" ]; then
|
||||
# Notificación vía ntfy
|
||||
# curl -d "🌎 [$(date '+%Y-%m-%d %H:%M:%S')] IP actualizada: $DNS_IP → $IP" ntfy.xala.dev/alerts
|
||||
curl -d "🚨 [$(date '+%Y-%m-%d %H:%M:%S')] No se pudo obtener la IP pública." ntfy.xala.dev/alerts
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$IP" != "$DNS_IP" ]; then
|
||||
curl -d "🌐 La IP ha cambiado: $DNS_IP → $IP. Actualizando en Cloudflare..." ntfy.xala.dev/alerts
|
||||
|
||||
UPDATE_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||
-H "Authorization: Bearer $API_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data "{
|
||||
\"type\": \"A\",
|
||||
\"name\": \"$DOMAIN\",
|
||||
\"content\": \"$IP\",
|
||||
\"ttl\": 1,
|
||||
\"proxied\": false
|
||||
}")
|
||||
|
||||
SUCCESS=$(echo "$UPDATE_RESPONSE" | jq -r '.success')
|
||||
|
||||
if [ "$SUCCESS" == "true" ]; then
|
||||
curl -d "🌎 [$(date '+%Y-%m-%d %H:%M:%S')] IP actualizada: $DNS_IP → $IP" ntfy.xala.dev/alerts
|
||||
else
|
||||
curl -d "🚨 [$(date '+%Y-%m-%d %H:%M:%S')] Falló la actualización en Cloudflare." ntfy.xala.dev/alerts
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ [$(date '+%Y-%m-%d %H:%M:%S')] La IP no ha cambiado: $IP"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,129 +1,129 @@
|
||||
```bash
|
||||
# instalar tesseract-ocr
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
sudo apt install tesseract-ocr tesseract-ocr-spa poppler-utils
|
||||
sudo apt install tesseract-ocr-all poppler-utils
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
|
||||
function getTxtFromPdf() {
|
||||
local pdf_path="$1"
|
||||
local base_name=$(basename "$pdf_path" .pdf)
|
||||
local tmp_prefix="pagina"
|
||||
|
||||
# Limpiar residuos anteriores
|
||||
rm -f ${tmp_prefix}-*.png ${tmp_prefix}-*.txt salida_${base_name}.txt
|
||||
|
||||
# Convertir PDF a PNG por página
|
||||
pdftoppm "$pdf_path" "$tmp_prefix" -png
|
||||
|
||||
# OCR cada imagen y concatenar en un solo archivo de salida
|
||||
for img in ${tmp_prefix}-*.png; do
|
||||
echo "Procesando $img..."
|
||||
tesseract "$img" temp -l spa
|
||||
cat temp.txt >> salida_${base_name}.txt
|
||||
echo -e "\n\n---- FIN DE PÁGINA ----\n\n" >> salida_${base_name}.txt
|
||||
done
|
||||
|
||||
rm -f temp.txt
|
||||
echo "OCR completado. Archivo final: salida_${base_name}.txt"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
getHighQualityTxtFromPdf() {
|
||||
# Verificar que se proporcionó al menos un argumento
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Error: Debes especificar la ruta del archivo PDF." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local pdf_path="$1"
|
||||
local base_name
|
||||
base_name=$(basename "$pdf_path" .pdf)
|
||||
local output_file="${2:-salida_hq_${base_name}.txt}" # Permitir archivo de salida opcional
|
||||
local tmp_prefix="hq_pagina"
|
||||
local lang="spa"
|
||||
local dpi=1000
|
||||
local oem=1
|
||||
local psm=6
|
||||
|
||||
# Verificar existencia del archivo
|
||||
if [[ ! -f "$pdf_path" ]]; then
|
||||
echo "Error: El archivo '$pdf_path' no existe." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verificar dependencias
|
||||
if ! command -v pdftoppm &> /dev/null || ! command -v tesseract &> /dev/null; then
|
||||
echo "Error: Se requieren 'pdftoppm' y 'tesseract'." >&2
|
||||
echo "Instala con: sudo apt install poppler-utils tesseract-ocr tesseract-ocr-spa" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Limpiar residuos anteriores
|
||||
rm -f "${tmp_prefix}-"*.png "$output_file" 2>/dev/null
|
||||
|
||||
echo "Convirtiendo PDF a imágenes de alta calidad (${dpi} DPI)..."
|
||||
if ! pdftoppm -png -r "$dpi" -aa yes -aaVector yes "$pdf_path" "$tmp_prefix"; then
|
||||
echo "Error al convertir PDF a imágenes." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Contar número total de páginas generadas
|
||||
local page_imgs=("${tmp_prefix}-"*.png)
|
||||
local total_pages=${#page_imgs[@]}
|
||||
if [[ $total_pages -eq 0 ]]; then
|
||||
echo "Error: No se generaron imágenes del PDF." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "" > "$output_file"
|
||||
|
||||
local page_count=0
|
||||
for img in "${page_imgs[@]}"; do
|
||||
((page_count++))
|
||||
echo "Procesando página $page_count: $img"
|
||||
|
||||
# Crear archivo temporal para esta página
|
||||
local tmp_txt_file
|
||||
tmp_txt_file=$(mktemp --suffix=.txt)
|
||||
|
||||
# OCR con configuraciones avanzadas
|
||||
if ! tesseract "$img" "$tmp_txt_file" -l "$lang" --dpi "$dpi" --oem "$oem" --psm "$psm" \
|
||||
-c tessedit_pageseg_mode=$psm \
|
||||
-c preserve_interword_spaces=1 \
|
||||
-c textord_debug_tabfind=0 \
|
||||
-c textord_min_linesize=2.5 2>/dev/null; then
|
||||
echo "Advertencia: OCR falló en $img. Reintentando con configuración básica..." >&2
|
||||
tesseract "$img" "$tmp_txt_file" -l "$lang" --dpi "$dpi" 2>/dev/null || continue
|
||||
fi
|
||||
|
||||
# Agregar texto al archivo final
|
||||
cat "${tmp_txt_file}.txt" >> "$output_file"
|
||||
|
||||
# Separador de página
|
||||
if [[ $page_count -lt $total_pages ]]; then
|
||||
echo -e "\n\n---- FIN DE PÁGINA $page_count ----\n\n" >> "$output_file"
|
||||
fi
|
||||
|
||||
# Limpieza
|
||||
rm -f "$img" "${tmp_txt_file}.txt"
|
||||
done
|
||||
|
||||
echo "Realizando post-procesamiento..."
|
||||
sed -i 's/fi/fi/g; s/fl/fl/g; s/ff/ff/g; s/ffi/ffi/g; s/ffl/ffl/g' "$output_file"
|
||||
sed -i '/^[[:space:]]*$/d' "$output_file"
|
||||
sed -i 's/[[:space:]]\+/ /g' "$output_file"
|
||||
|
||||
echo -e "\n=============================="
|
||||
echo " OCR COMPLETADO EXITOSAMENTE "
|
||||
echo "=============================="
|
||||
echo "Archivo final: $output_file"
|
||||
echo "Páginas procesadas: $page_count"
|
||||
echo "Tamaño final: $(du -h "$output_file" | cut -f1)"
|
||||
}
|
||||
```bash
|
||||
# instalar tesseract-ocr
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
sudo apt install tesseract-ocr tesseract-ocr-spa poppler-utils
|
||||
sudo apt install tesseract-ocr-all poppler-utils
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
|
||||
function getTxtFromPdf() {
|
||||
local pdf_path="$1"
|
||||
local base_name=$(basename "$pdf_path" .pdf)
|
||||
local tmp_prefix="pagina"
|
||||
|
||||
# Limpiar residuos anteriores
|
||||
rm -f ${tmp_prefix}-*.png ${tmp_prefix}-*.txt salida_${base_name}.txt
|
||||
|
||||
# Convertir PDF a PNG por página
|
||||
pdftoppm "$pdf_path" "$tmp_prefix" -png
|
||||
|
||||
# OCR cada imagen y concatenar en un solo archivo de salida
|
||||
for img in ${tmp_prefix}-*.png; do
|
||||
echo "Procesando $img..."
|
||||
tesseract "$img" temp -l spa
|
||||
cat temp.txt >> salida_${base_name}.txt
|
||||
echo -e "\n\n---- FIN DE PÁGINA ----\n\n" >> salida_${base_name}.txt
|
||||
done
|
||||
|
||||
rm -f temp.txt
|
||||
echo "OCR completado. Archivo final: salida_${base_name}.txt"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```bash
|
||||
getHighQualityTxtFromPdf() {
|
||||
# Verificar que se proporcionó al menos un argumento
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Error: Debes especificar la ruta del archivo PDF." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local pdf_path="$1"
|
||||
local base_name
|
||||
base_name=$(basename "$pdf_path" .pdf)
|
||||
local output_file="${2:-salida_hq_${base_name}.txt}" # Permitir archivo de salida opcional
|
||||
local tmp_prefix="hq_pagina"
|
||||
local lang="spa"
|
||||
local dpi=1000
|
||||
local oem=1
|
||||
local psm=6
|
||||
|
||||
# Verificar existencia del archivo
|
||||
if [[ ! -f "$pdf_path" ]]; then
|
||||
echo "Error: El archivo '$pdf_path' no existe." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Verificar dependencias
|
||||
if ! command -v pdftoppm &> /dev/null || ! command -v tesseract &> /dev/null; then
|
||||
echo "Error: Se requieren 'pdftoppm' y 'tesseract'." >&2
|
||||
echo "Instala con: sudo apt install poppler-utils tesseract-ocr tesseract-ocr-spa" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Limpiar residuos anteriores
|
||||
rm -f "${tmp_prefix}-"*.png "$output_file" 2>/dev/null
|
||||
|
||||
echo "Convirtiendo PDF a imágenes de alta calidad (${dpi} DPI)..."
|
||||
if ! pdftoppm -png -r "$dpi" -aa yes -aaVector yes "$pdf_path" "$tmp_prefix"; then
|
||||
echo "Error al convertir PDF a imágenes." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Contar número total de páginas generadas
|
||||
local page_imgs=("${tmp_prefix}-"*.png)
|
||||
local total_pages=${#page_imgs[@]}
|
||||
if [[ $total_pages -eq 0 ]]; then
|
||||
echo "Error: No se generaron imágenes del PDF." >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "" > "$output_file"
|
||||
|
||||
local page_count=0
|
||||
for img in "${page_imgs[@]}"; do
|
||||
((page_count++))
|
||||
echo "Procesando página $page_count: $img"
|
||||
|
||||
# Crear archivo temporal para esta página
|
||||
local tmp_txt_file
|
||||
tmp_txt_file=$(mktemp --suffix=.txt)
|
||||
|
||||
# OCR con configuraciones avanzadas
|
||||
if ! tesseract "$img" "$tmp_txt_file" -l "$lang" --dpi "$dpi" --oem "$oem" --psm "$psm" \
|
||||
-c tessedit_pageseg_mode=$psm \
|
||||
-c preserve_interword_spaces=1 \
|
||||
-c textord_debug_tabfind=0 \
|
||||
-c textord_min_linesize=2.5 2>/dev/null; then
|
||||
echo "Advertencia: OCR falló en $img. Reintentando con configuración básica..." >&2
|
||||
tesseract "$img" "$tmp_txt_file" -l "$lang" --dpi "$dpi" 2>/dev/null || continue
|
||||
fi
|
||||
|
||||
# Agregar texto al archivo final
|
||||
cat "${tmp_txt_file}.txt" >> "$output_file"
|
||||
|
||||
# Separador de página
|
||||
if [[ $page_count -lt $total_pages ]]; then
|
||||
echo -e "\n\n---- FIN DE PÁGINA $page_count ----\n\n" >> "$output_file"
|
||||
fi
|
||||
|
||||
# Limpieza
|
||||
rm -f "$img" "${tmp_txt_file}.txt"
|
||||
done
|
||||
|
||||
echo "Realizando post-procesamiento..."
|
||||
sed -i 's/fi/fi/g; s/fl/fl/g; s/ff/ff/g; s/ffi/ffi/g; s/ffl/ffl/g' "$output_file"
|
||||
sed -i '/^[[:space:]]*$/d' "$output_file"
|
||||
sed -i 's/[[:space:]]\+/ /g' "$output_file"
|
||||
|
||||
echo -e "\n=============================="
|
||||
echo " OCR COMPLETADO EXITOSAMENTE "
|
||||
echo "=============================="
|
||||
echo "Archivo final: $output_file"
|
||||
echo "Páginas procesadas: $page_count"
|
||||
echo "Tamaño final: $(du -h "$output_file" | cut -f1)"
|
||||
}
|
||||
```
|
@ -1,6 +1,9 @@
|
||||
11/02/2025 10,000
|
||||
17/03/2025 7,500
|
||||
30/03/2025 1,000
|
||||
17/07/2025 16,500
|
||||
|
||||
60,000 - 18,500 = 25,000
|
||||
11/02/2025 10,000
|
||||
17/03/2025 7,500
|
||||
30/03/2025 1,000
|
||||
17/07/2025 16,500
|
||||
|
||||
|
||||
60,000 - 18,500 = 25,000
|
||||
|
||||
costco 3,800
|
||||
|
@ -1,132 +1,132 @@
|
||||
¡Claro! Configurar un túnel WireGuard con **obfs4proxy** es una excelente manera de evitar que el tráfico VPN sea detectado, ya que `obfs4proxy` es un protocolo de ofuscación diseñado específicamente para ocultar el tráfico VPN y hacerlo parecer tráfico normal HTTPS.
|
||||
|
||||
A continuación, te guiaré a través de los pasos básicos para configurar esto. Aquí tienes un esquema general para hacerlo:
|
||||
|
||||
### **1. Instalar WireGuard y obfs4proxy en el servidor**
|
||||
|
||||
1. **Instalar WireGuard**:
|
||||
Si no tienes WireGuard instalado en tu servidor, primero instálalo:
|
||||
|
||||
En **Ubuntu/Debian**:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install wireguard
|
||||
```
|
||||
|
||||
2. **Instalar obfs4proxy**:
|
||||
`obfs4proxy` se utiliza para ofuscar el tráfico VPN. Puedes instalarlo en el servidor y el cliente.
|
||||
|
||||
En **Ubuntu/Debian**:
|
||||
|
||||
```bash
|
||||
sudo apt install obfs4proxy
|
||||
```
|
||||
|
||||
|
||||
### **2. Configurar WireGuard en el servidor**
|
||||
|
||||
Ya que tienes WireGuard instalado, tendrás que configurar la parte básica de la VPN. Aquí te dejo un ejemplo de configuración de servidor WireGuard (`/etc/wireguard/wg0.conf`):
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
Address = 10.10.10.1/24 # Dirección IP del servidor WireGuard
|
||||
ListenPort = 51820 # Puerto para WireGuard (por defecto 51820)
|
||||
PrivateKey = <private-key>
|
||||
|
||||
[Peer]
|
||||
PublicKey = <peer-public-key>
|
||||
AllowedIPs = 10.10.10.2/32 # IP del cliente
|
||||
```
|
||||
|
||||
Asegúrate de generar las claves privadas y públicas con `wg genkey` y `wg pubkey`, como se indica en la documentación de WireGuard.
|
||||
|
||||
### **3. Configurar `obfs4proxy`**
|
||||
|
||||
El siguiente paso es configurar `obfs4proxy` para usarlo con WireGuard. Vamos a usar el puerto 443 para hacer que el tráfico de WireGuard se vea como HTTPS.
|
||||
|
||||
1. **Generar un "bridge" de `obfs4proxy`**:
|
||||
|
||||
Primero, necesitarás crear un "bridge" para `obfs4proxy`. Esto se hace ejecutando el siguiente comando en tu servidor para obtener un identificador único de obfs4 (también conocido como bridge):
|
||||
|
||||
```bash
|
||||
obfs4proxy -generate
|
||||
```
|
||||
|
||||
Esto generará algo como:
|
||||
|
||||
```
|
||||
Bridge obfs4 <IP:Puerto> <identificador-obfs4>
|
||||
```
|
||||
|
||||
Guarda esta información porque la necesitarás en el cliente.
|
||||
|
||||
2. **Configurar el `obfs4proxy` en el servidor**:
|
||||
|
||||
Una vez que tengas el "bridge", puedes configurar `obfs4proxy` para que actúe como un "proxy" en el servidor de WireGuard. Para hacerlo, necesitas ejecutar `obfs4proxy` y asociarlo con el puerto 443.
|
||||
|
||||
Para hacerlo, puedes usar este comando en el servidor:
|
||||
|
||||
```bash
|
||||
obfs4proxy -enableServer -listenAddr 0.0.0.0:443
|
||||
```
|
||||
|
||||
Esto hará que el servidor WireGuard pase su tráfico por el `obfs4proxy`, y lo hará parecer tráfico HTTPS.
|
||||
|
||||
|
||||
### **4. Configurar WireGuard en el cliente**
|
||||
|
||||
En el lado del cliente, deberás configurar WireGuard para que se conecte al servidor, pero a través del túnel ofuscado. Aquí está un ejemplo de cómo hacerlo:
|
||||
|
||||
1. **Configurar WireGuard**:
|
||||
|
||||
El archivo de configuración del cliente (`wg0-client.conf`) se verá de esta forma:
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
PrivateKey = <private-key>
|
||||
Address = 10.10.10.2/32
|
||||
|
||||
[Peer]
|
||||
PublicKey = <server-public-key>
|
||||
Endpoint = <IP-del-servidor>:443 # Usa el puerto 443 (HTTPS) para la conexión
|
||||
AllowedIPs = 0.0.0.0/0, ::/0
|
||||
PersistentKeepalive = 25
|
||||
```
|
||||
|
||||
2. **Configurar `obfs4proxy` en el cliente**:
|
||||
|
||||
En el lado del cliente, también tendrás que usar `obfs4proxy`. Puedes instalarlo de la misma manera que en el servidor.
|
||||
|
||||
Una vez instalado, ejecuta `obfs4proxy` en el cliente:
|
||||
|
||||
```bash
|
||||
obfs4proxy -proxy <bridge-del-servidor>
|
||||
```
|
||||
|
||||
El `bridge-del-servidor` es la información que obtuviste del paso de configuración del servidor.
|
||||
|
||||
|
||||
### **5. Verificar la conexión**
|
||||
|
||||
Finalmente, verifica que la conexión está funcionando. Si todo está configurado correctamente, el tráfico de WireGuard se verá como tráfico HTTPS y debería ser mucho más difícil de bloquear.
|
||||
|
||||
Para verificar:
|
||||
|
||||
1. Asegúrate de que el servicio de WireGuard y `obfs4proxy` esté activo en ambos lados (`sudo systemctl status wg-quick@wg0`).
|
||||
|
||||
2. Realiza una conexión desde el cliente al servidor usando WireGuard, y asegúrate de que se esté enrutando correctamente a través de `obfs4proxy`.
|
||||
|
||||
|
||||
### **Resumen de pasos clave:**
|
||||
|
||||
- Instalar y configurar **WireGuard** en el servidor y cliente.
|
||||
|
||||
- Instalar y ejecutar **obfs4proxy** en el servidor y cliente, usando el puerto 443 para pasar por tráfico HTTPS.
|
||||
|
||||
- Configurar la VPN para usar la ofuscación, de modo que el tráfico de WireGuard sea indetectable.
|
||||
|
||||
|
||||
---
|
||||
|
||||
¡Claro! Configurar un túnel WireGuard con **obfs4proxy** es una excelente manera de evitar que el tráfico VPN sea detectado, ya que `obfs4proxy` es un protocolo de ofuscación diseñado específicamente para ocultar el tráfico VPN y hacerlo parecer tráfico normal HTTPS.
|
||||
|
||||
A continuación, te guiaré a través de los pasos básicos para configurar esto. Aquí tienes un esquema general para hacerlo:
|
||||
|
||||
### **1. Instalar WireGuard y obfs4proxy en el servidor**
|
||||
|
||||
1. **Instalar WireGuard**:
|
||||
Si no tienes WireGuard instalado en tu servidor, primero instálalo:
|
||||
|
||||
En **Ubuntu/Debian**:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install wireguard
|
||||
```
|
||||
|
||||
2. **Instalar obfs4proxy**:
|
||||
`obfs4proxy` se utiliza para ofuscar el tráfico VPN. Puedes instalarlo en el servidor y el cliente.
|
||||
|
||||
En **Ubuntu/Debian**:
|
||||
|
||||
```bash
|
||||
sudo apt install obfs4proxy
|
||||
```
|
||||
|
||||
|
||||
### **2. Configurar WireGuard en el servidor**
|
||||
|
||||
Ya que tienes WireGuard instalado, tendrás que configurar la parte básica de la VPN. Aquí te dejo un ejemplo de configuración de servidor WireGuard (`/etc/wireguard/wg0.conf`):
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
Address = 10.10.10.1/24 # Dirección IP del servidor WireGuard
|
||||
ListenPort = 51820 # Puerto para WireGuard (por defecto 51820)
|
||||
PrivateKey = <private-key>
|
||||
|
||||
[Peer]
|
||||
PublicKey = <peer-public-key>
|
||||
AllowedIPs = 10.10.10.2/32 # IP del cliente
|
||||
```
|
||||
|
||||
Asegúrate de generar las claves privadas y públicas con `wg genkey` y `wg pubkey`, como se indica en la documentación de WireGuard.
|
||||
|
||||
### **3. Configurar `obfs4proxy`**
|
||||
|
||||
El siguiente paso es configurar `obfs4proxy` para usarlo con WireGuard. Vamos a usar el puerto 443 para hacer que el tráfico de WireGuard se vea como HTTPS.
|
||||
|
||||
1. **Generar un "bridge" de `obfs4proxy`**:
|
||||
|
||||
Primero, necesitarás crear un "bridge" para `obfs4proxy`. Esto se hace ejecutando el siguiente comando en tu servidor para obtener un identificador único de obfs4 (también conocido como bridge):
|
||||
|
||||
```bash
|
||||
obfs4proxy -generate
|
||||
```
|
||||
|
||||
Esto generará algo como:
|
||||
|
||||
```
|
||||
Bridge obfs4 <IP:Puerto> <identificador-obfs4>
|
||||
```
|
||||
|
||||
Guarda esta información porque la necesitarás en el cliente.
|
||||
|
||||
2. **Configurar el `obfs4proxy` en el servidor**:
|
||||
|
||||
Una vez que tengas el "bridge", puedes configurar `obfs4proxy` para que actúe como un "proxy" en el servidor de WireGuard. Para hacerlo, necesitas ejecutar `obfs4proxy` y asociarlo con el puerto 443.
|
||||
|
||||
Para hacerlo, puedes usar este comando en el servidor:
|
||||
|
||||
```bash
|
||||
obfs4proxy -enableServer -listenAddr 0.0.0.0:443
|
||||
```
|
||||
|
||||
Esto hará que el servidor WireGuard pase su tráfico por el `obfs4proxy`, y lo hará parecer tráfico HTTPS.
|
||||
|
||||
|
||||
### **4. Configurar WireGuard en el cliente**
|
||||
|
||||
En el lado del cliente, deberás configurar WireGuard para que se conecte al servidor, pero a través del túnel ofuscado. Aquí está un ejemplo de cómo hacerlo:
|
||||
|
||||
1. **Configurar WireGuard**:
|
||||
|
||||
El archivo de configuración del cliente (`wg0-client.conf`) se verá de esta forma:
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
PrivateKey = <private-key>
|
||||
Address = 10.10.10.2/32
|
||||
|
||||
[Peer]
|
||||
PublicKey = <server-public-key>
|
||||
Endpoint = <IP-del-servidor>:443 # Usa el puerto 443 (HTTPS) para la conexión
|
||||
AllowedIPs = 0.0.0.0/0, ::/0
|
||||
PersistentKeepalive = 25
|
||||
```
|
||||
|
||||
2. **Configurar `obfs4proxy` en el cliente**:
|
||||
|
||||
En el lado del cliente, también tendrás que usar `obfs4proxy`. Puedes instalarlo de la misma manera que en el servidor.
|
||||
|
||||
Una vez instalado, ejecuta `obfs4proxy` en el cliente:
|
||||
|
||||
```bash
|
||||
obfs4proxy -proxy <bridge-del-servidor>
|
||||
```
|
||||
|
||||
El `bridge-del-servidor` es la información que obtuviste del paso de configuración del servidor.
|
||||
|
||||
|
||||
### **5. Verificar la conexión**
|
||||
|
||||
Finalmente, verifica que la conexión está funcionando. Si todo está configurado correctamente, el tráfico de WireGuard se verá como tráfico HTTPS y debería ser mucho más difícil de bloquear.
|
||||
|
||||
Para verificar:
|
||||
|
||||
1. Asegúrate de que el servicio de WireGuard y `obfs4proxy` esté activo en ambos lados (`sudo systemctl status wg-quick@wg0`).
|
||||
|
||||
2. Realiza una conexión desde el cliente al servidor usando WireGuard, y asegúrate de que se esté enrutando correctamente a través de `obfs4proxy`.
|
||||
|
||||
|
||||
### **Resumen de pasos clave:**
|
||||
|
||||
- Instalar y configurar **WireGuard** en el servidor y cliente.
|
||||
|
||||
- Instalar y ejecutar **obfs4proxy** en el servidor y cliente, usando el puerto 443 para pasar por tráfico HTTPS.
|
||||
|
||||
- Configurar la VPN para usar la ofuscación, de modo que el tráfico de WireGuard sea indetectable.
|
||||
|
||||
|
||||
---
|
||||
|
||||
Este proceso es un poco más avanzado debido a la necesidad de configurar `obfs4proxy` y combinarlo con WireGuard, pero definitivamente vale la pena si las restricciones de red son severas. Si necesitas más detalles o tienes alguna pregunta durante la configuración, no dudes en preguntar.
|
@ -1,46 +1,46 @@
|
||||
```bash
|
||||
# speedtest: https://www.speedtest.net/es/apps/cli
|
||||
# calendar: https://hijosdeinit.gitlab.io/howto_instalacion_cal_debian11_y_derivados/
|
||||
|
||||
# dix_zip() {
|
||||
# # sudo apt install zip -y
|
||||
# # sudo apt install unzip
|
||||
# # https://www.tecmint.com/install-zip-and-unzip-in-linux/
|
||||
# name=$1
|
||||
# fecha=$(date +'%d.%m.%Y')
|
||||
# hora=$(date +'%H-%M-%S')
|
||||
# full_name="${name}_date_${fecha}_time_${hora}.zip"
|
||||
# zip -r $full_name . -i ".*" "*" -x "./.venv/*"
|
||||
# }
|
||||
|
||||
ip_device=$(ip addr show | grep -w 'inet' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1 | head -n 1)
|
||||
|
||||
declare -A ip_icon=(
|
||||
['192.168.10.40']='uk'
|
||||
['192.168.10.234']='lb'
|
||||
['192.168.10.44']='db'
|
||||
['192.168.10.122']='mb'
|
||||
['192.168.10.37']='web1'
|
||||
['192.168.10.245']='web2'
|
||||
['192.168.10.232']='web3'
|
||||
['192.168.10.42']='web5'
|
||||
['192.168.10.43']='web5'
|
||||
['192.168.10.59']='web6'
|
||||
)
|
||||
|
||||
# Asignar el nombre del servidor o un valor por defecto
|
||||
if [[ -n "${ip_icon[$ip_device]}" ]]; then
|
||||
n_server="${ip_icon[$ip_device]}"
|
||||
else
|
||||
n_server="WSL"
|
||||
fi
|
||||
|
||||
export PS1="\[\e[31m\][\[\e[38;5;214m\]$n_server\[\e[31m\]]\[\e[0m\] 📂 > \[\033[01;32m\]\W \[\033[00m\]\n 💀 > "
|
||||
|
||||
|
||||
echo ""
|
||||
# sudo apt install fastfetch -y
|
||||
fastfetch
|
||||
echo ""
|
||||
|
||||
```bash
|
||||
# speedtest: https://www.speedtest.net/es/apps/cli
|
||||
# calendar: https://hijosdeinit.gitlab.io/howto_instalacion_cal_debian11_y_derivados/
|
||||
|
||||
# dix_zip() {
|
||||
# # sudo apt install zip -y
|
||||
# # sudo apt install unzip
|
||||
# # https://www.tecmint.com/install-zip-and-unzip-in-linux/
|
||||
# name=$1
|
||||
# fecha=$(date +'%d.%m.%Y')
|
||||
# hora=$(date +'%H-%M-%S')
|
||||
# full_name="${name}_date_${fecha}_time_${hora}.zip"
|
||||
# zip -r $full_name . -i ".*" "*" -x "./.venv/*"
|
||||
# }
|
||||
|
||||
ip_device=$(ip addr show | grep -w 'inet' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1 | head -n 1)
|
||||
|
||||
declare -A ip_icon=(
|
||||
['192.168.10.40']='uk'
|
||||
['192.168.10.234']='lb'
|
||||
['192.168.10.44']='db'
|
||||
['192.168.10.122']='mb'
|
||||
['192.168.10.37']='web1'
|
||||
['192.168.10.245']='web2'
|
||||
['192.168.10.232']='web3'
|
||||
['192.168.10.42']='web5'
|
||||
['192.168.10.43']='web5'
|
||||
['192.168.10.59']='web6'
|
||||
)
|
||||
|
||||
# Asignar el nombre del servidor o un valor por defecto
|
||||
if [[ -n "${ip_icon[$ip_device]}" ]]; then
|
||||
n_server="${ip_icon[$ip_device]}"
|
||||
else
|
||||
n_server="WSL"
|
||||
fi
|
||||
|
||||
export PS1="\[\e[31m\][\[\e[38;5;214m\]$n_server\[\e[31m\]]\[\e[0m\] 📂 > \[\033[01;32m\]\W \[\033[00m\]\n 💀 > "
|
||||
|
||||
|
||||
echo ""
|
||||
# sudo apt install fastfetch -y
|
||||
fastfetch
|
||||
echo ""
|
||||
|
||||
```
|
@ -1,22 +1,22 @@
|
||||
Reunión en instalaciones de la SHCP 05/08/2025 11:00 am
|
||||
|
||||
|
||||
|
||||
Temas vistos:
|
||||
|
||||
- Revisión de cada uno de los proyectos de inversión para ver los estudios de preinversión que les aplican.
|
||||
|
||||
- Aclaración de dudas relacionados con los proyectos por parte de la Lic. María Asereth.
|
||||
|
||||
|
||||
Acuerdos:
|
||||
|
||||
- Se designan a las contadoras Lic. Guadalupe y Lic. Alba como enlaces con la Lic. María Asereth para asesorías en el desarrollo de los estudios de preinversión.
|
||||
|
||||
- La Lic. María Asereth gestionará apartar una sala de reuniones para permitir que podamos trabajar en las instalaciones de la SHCP a fin de facilitar y atender dudas y aclaraciones en el desarrollo de los estudios de preinversión, para ello hay que compartir mediante los enlaces los nombres de los que estarán yendo a las instalaciones.
|
||||
|
||||
- La Lic. María Asereth compartirá un ejemplo de cartera de inversión.
|
||||
|
||||
- Los estudios de preinversión deben ser entregados a más tardar el 20 de agosto.
|
||||
|
||||
Reunión en instalaciones de la SHCP 05/08/2025 11:00 am
|
||||
|
||||
|
||||
|
||||
Temas vistos:
|
||||
|
||||
- Revisión de cada uno de los proyectos de inversión para ver los estudios de preinversión que les aplican.
|
||||
|
||||
- Aclaración de dudas relacionados con los proyectos por parte de la Lic. María Asereth.
|
||||
|
||||
|
||||
Acuerdos:
|
||||
|
||||
- Se designan a las contadoras Lic. Guadalupe y Lic. Alba como enlaces con la Lic. María Asereth para asesorías en el desarrollo de los estudios de preinversión.
|
||||
|
||||
- La Lic. María Asereth gestionará apartar una sala de reuniones para permitir que podamos trabajar en las instalaciones de la SHCP a fin de facilitar y atender dudas y aclaraciones en el desarrollo de los estudios de preinversión, para ello hay que compartir mediante los enlaces los nombres de los que estarán yendo a las instalaciones.
|
||||
|
||||
- La Lic. María Asereth compartirá un ejemplo de cartera de inversión.
|
||||
|
||||
- Los estudios de preinversión deben ser entregados a más tardar el 20 de agosto.
|
||||
|
||||
- IMPORTANTE: decidir si se debe involucrar al nuevo Director General Satelital de la AEM.
|
Loading…
x
Reference in New Issue
Block a user