Subir archivos a "/"

This commit is contained in:
nico 2026-02-27 18:11:04 +00:00
commit 78c9f8831e
5 changed files with 2194 additions and 0 deletions

1910
Proyecto.py Normal file

File diff suppressed because it is too large Load Diff

BIN
alarm.mp3 Normal file

Binary file not shown.

44
backup_script.sh Normal file
View File

@ -0,0 +1,44 @@
#!/bin/bash
# backup_script.sh
# Script de Bash para simular una copia de seguridad en Linux.
# Directorio de destino para el backup y logs
BACKUP_DIR="/tmp/BackupData"
mkdir -p $BACKUP_DIR
# Obtener la fecha y hora actual
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
LOG_FILE="$BACKUP_DIR/backup_log_$TIMESTAMP.txt"
echo "--- Script de Copia de Seguridad Iniciado ($TIMESTAMP) ---" > $LOG_FILE
echo "Creando directorio de destino: $BACKUP_DIR" >> $LOG_FILE
# Simular el proceso de copia de seguridad (ejemplo: comprimir /var/log)
# Nota: Esto puede requerir permisos de sudo si /var/log no es accesible para tu usuario.
# Usaremos /tmp para un ejemplo más seguro.
echo "Simulando compresión de archivos de ejemplo..." >> $LOG_FILE
# Creamos un archivo de ejemplo para copiar si no existe
if [ ! -f "/tmp/archivos_a_copiar.txt" ]; then
echo "Contenido de prueba" > /tmp/archivos_a_copiar.txt
fi
# Simulación de la copia real (usando tar para crear un archivo)
tar -czf "$BACKUP_DIR/backup_$TIMESTAMP.tar.gz" /tmp/archivos_a_copiar.txt >> $LOG_FILE 2>&1
# Simular la tarea con una pausa
sleep 3
# Verificar si el archivo de backup se creó
if [ -f "$BACKUP_DIR/backup_$TIMESTAMP.tar.gz" ]; then
echo "Copia de seguridad completada con éxito." >> $LOG_FILE
EXIT_CODE=0
else
echo "ERROR: Falló la creación del archivo de copia de seguridad." >> $LOG_FILE
EXIT_CODE=1
fi
echo "Log guardado en: $LOG_FILE" >> $LOG_FILE
echo "--- Script de Copia de Seguridad Finalizado ---" >> $LOG_FILE
# Devolver el código de salida
exit $EXIT_CODE

240
chat_client.py Normal file
View File

@ -0,0 +1,240 @@
import sys
import os
import tkinter as tk
from tkinter import ttk
import datetime
# ---------------------------------------------------------------------------
# 1. LECTURA DE ARGUMENTOS
# ---------------------------------------------------------------------------
if len(sys.argv) < 7:
print("Uso: python chat_client.py <mi_nombre> <otro_nombre> <f_salida> <f_entrada> <x> <y>")
sys.exit(1)
MY_NAME = sys.argv[1] # Nombre de este cliente (ej: "Cliente A")
OTHER_NAME = sys.argv[2] # Nombre del otro cliente (ej: "Cliente B")
FILE_OUT = sys.argv[3] # Fichero donde YO escribo mis mensajes
FILE_IN = sys.argv[4] # Fichero donde YO leo los mensajes del otro
X_POS = int(sys.argv[5]) # Posición horizontal de la ventana
Y_POS = int(sys.argv[6]) # Posición vertical de la ventana
# ---------------------------------------------------------------------------
# 2. COMUNICACIÓN IPC POR FICHERO
# ---------------------------------------------------------------------------
# Contador de líneas ya leídas. Así en cada polling solo procesamos
# las líneas NUEVAS, no releemos todo el fichero desde el principio.
lines_read = 0
def write_message(text):
"""
Escribe un mensaje en el fichero de salida (el que lee el otro cliente).
Formato de cada línea: HH:MM|texto\n
Usamos modo "a" (append) para no borrar mensajes anteriores.
"""
with open(FILE_OUT, "a", encoding="utf-8") as f:
timestamp = datetime.datetime.now().strftime("%H:%M")
f.write(f"{timestamp}|{text}\n")
def read_new_messages():
"""
Lee el fichero de entrada y devuelve SOLO las líneas nuevas
desde la última vez que se llamó a esta función.
Devuelve una lista de tuplas (timestamp, texto).
"""
global lines_read
new = []
try:
with open(FILE_IN, "r", encoding="utf-8") as f:
all_lines = f.readlines()
# Solo procesamos desde la línea lines_read en adelante
for line in all_lines[lines_read:]:
line = line.strip()
if line and "|" in line:
ts, msg = line.split("|", 1) # Separamos timestamp del texto
new.append((ts, msg))
# Actualizamos el contador para la próxima llamada
lines_read = len(all_lines)
except Exception:
pass # Si el fichero no existe aún, simplemente no hay mensajes
return new
# ---------------------------------------------------------------------------
# 3. INTERFAZ GRÁFICA (Tkinter)
# ---------------------------------------------------------------------------
COLOR_BG = "#F0F4F8" # Fondo general (gris claro)
COLOR_HEADER = "#2C3E50" # Cabecera (azul oscuro)
COLOR_MY_BG = "#DCF8C6" # Burbujas propias (verde tipo WhatsApp)
COLOR_OTHER_BG = "#FFFFFF" # Burbujas del otro (blanco)
COLOR_SEND_BTN = "#25D366" # Botón enviar (verde)
FONT_MSG = ("Segoe UI", 10)
FONT_HEADER = ("Segoe UI", 12, "bold")
root = tk.Tk()
root.title(f"Chat — {MY_NAME}")
root.geometry(f"500x700+{X_POS}+{Y_POS}") # Tamaño y posición inicial
root.minsize(360, 400) # Tamaño mínimo para que no se deforme
root.resizable(True, True)
root.configure(bg=COLOR_BG)
# --- Layout con grid: 3 filas ---
# fila 0 = cabecera (altura fija, weight=0)
# fila 1 = mensajes (crece/encoge, weight=1)
# fila 2 = input (altura fija, weight=0)
# Usar weight=0 en las filas del input y cabecera garantiza que
# siempre tienen su espacio reservado sin importar el tamaño de la ventana.
root.grid_rowconfigure(0, weight=0)
root.grid_rowconfigure(1, weight=1)
root.grid_rowconfigure(2, weight=0)
root.grid_columnconfigure(0, weight=1)
# --- FILA 0: Cabecera ---
header = tk.Frame(root, bg=COLOR_HEADER, pady=10)
header.grid(row=0, column=0, sticky="ew")
tk.Label(
header,
text=f"💬 {MY_NAME}{OTHER_NAME}",
bg=COLOR_HEADER, fg="white",
font=FONT_HEADER, anchor="w", padx=15
).pack(side="left")
tk.Label(
header, text="● Conectado",
bg=COLOR_HEADER, fg="#2ECC71",
font=("Segoe UI", 9)
).pack(side="right", padx=15)
# --- FILA 1: Área de mensajes (Canvas con scroll) ---
# Usamos un Canvas porque tk.Frame no tiene scrollbar nativa.
# El truco es poner un Frame dentro del Canvas y ajustar su ancho
# al del Canvas cada vez que este cambia de tamaño (on_canvas_configure).
messages_outer = tk.Frame(root, bg=COLOR_BG)
messages_outer.grid(row=1, column=0, sticky="nsew", padx=8, pady=(8, 4))
messages_outer.grid_rowconfigure(0, weight=1)
messages_outer.grid_columnconfigure(0, weight=1)
canvas_msgs = tk.Canvas(messages_outer, bg=COLOR_BG, highlightthickness=0)
canvas_msgs.grid(row=0, column=0, sticky="nsew")
scrollbar = ttk.Scrollbar(messages_outer, command=canvas_msgs.yview)
scrollbar.grid(row=0, column=1, sticky="ns")
canvas_msgs.configure(yscrollcommand=scrollbar.set)
# Frame real donde se añaden las burbujas de mensaje
messages_frame = tk.Frame(canvas_msgs, bg=COLOR_BG)
canvas_window = canvas_msgs.create_window((0, 0), window=messages_frame, anchor="nw")
def on_frame_configure(event):
"""Actualiza la zona de scroll cuando el frame de mensajes cambia de tamaño."""
canvas_msgs.configure(scrollregion=canvas_msgs.bbox("all"))
def on_canvas_configure(event):
"""Ajusta el ancho del frame interior al ancho del canvas (responsivo)."""
canvas_msgs.itemconfig(canvas_window, width=event.width)
messages_frame.bind("<Configure>", on_frame_configure)
canvas_msgs.bind("<Configure>", on_canvas_configure)
# Mensaje de sistema al inicio del chat
tk.Label(
messages_frame,
text=f"── Inicio del chat con {OTHER_NAME} ──",
bg=COLOR_BG, fg="#AAAAAA",
font=("Segoe UI", 9, "italic")
).pack(pady=(10, 5))
def add_bubble(text, is_mine, timestamp=None):
"""
Añade una burbuja de mensaje al área de chat.
- is_mine=True burbuja verde a la derecha (mensaje propio)
- is_mine=False burbuja blanca a la izquierda (mensaje recibido)
"""
if timestamp is None:
timestamp = datetime.datetime.now().strftime("%H:%M")
bg_color = COLOR_MY_BG if is_mine else COLOR_OTHER_BG
side = "right" if is_mine else "left"
anchor = "e" if is_mine else "w"
label = "" if is_mine else OTHER_NAME
# Fila contenedora (ocupa todo el ancho para poder alinear la burbuja)
row = tk.Frame(messages_frame, bg=COLOR_BG)
row.pack(fill="x", pady=3, padx=8)
# Burbuja real (solo tan ancha como su contenido)
bubble = tk.Frame(row, bg=bg_color, padx=10, pady=6)
bubble.pack(side=side, anchor=anchor)
tk.Label(bubble, text=label, bg=bg_color, fg="#888888",
font=("Segoe UI", 8, "bold")).pack(anchor="w")
tk.Label(bubble, text=text, bg=bg_color, fg="#222222",
font=FONT_MSG, wraplength=280, justify="left").pack(anchor="w")
tk.Label(bubble, text=timestamp, bg=bg_color, fg="#AAAAAA",
font=("Segoe UI", 7)).pack(anchor="e")
# Scroll automático al fondo al recibir/enviar un mensaje
root.after(50, lambda: canvas_msgs.yview_moveto(1.0))
# --- FILA 2: Área de entrada de texto ---
input_frame = tk.Frame(root, bg="#E8ECF0", pady=8, padx=8)
input_frame.grid(row=2, column=0, sticky="ew")
input_frame.grid_columnconfigure(0, weight=1)
text_entry = tk.Text(
input_frame,
height=3, # 3 líneas de alto
font=FONT_MSG,
bg="#FFFFFF", fg="#222222",
relief="flat", wrap="word",
padx=8, pady=6,
bd=1,
highlightbackground="#CCCCCC",
highlightthickness=1
)
text_entry.grid(row=0, column=0, sticky="ew", padx=(0, 8))
def send_message(event=None):
"""
Recoge el texto del entry, lo escribe en el fichero de salida
y añade la burbuja propia en pantalla.
Devuelve "break" para que el Enter no inserte un salto de línea.
"""
msg = text_entry.get("1.0", "end-1c").strip()
if not msg:
return "break"
write_message(msg) # Escribe en el fichero de cola
add_bubble(msg, is_mine=True) # Muestra la burbuja en nuestra ventana
text_entry.delete("1.0", "end") # Limpia el campo de texto
return "break"
# Enter envía el mensaje; Shift+Enter inserta salto de línea
text_entry.bind("<Return>", send_message)
text_entry.bind("<Shift-Return>", lambda e: None)
tk.Button(
input_frame,
text="Enviar ➤",
bg=COLOR_SEND_BTN, fg="white",
font=("Segoe UI", 10, "bold"),
relief="flat", padx=12, pady=8,
cursor="hand2",
command=send_message
).grid(row=0, column=1)
# ---------------------------------------------------------------------------
# 4. POLLING DE MENSAJES ENTRANTES
# ---------------------------------------------------------------------------
def poll_incoming():
new_msgs = read_new_messages()
for ts, msg in new_msgs:
add_bubble(msg, is_mine=False, timestamp=ts) # Burbuja del otro
root.after(300, poll_incoming) # Volvemos a llamarnos en 300ms
root.after(300, poll_incoming) # Primera llamada al arrancar
# ---------------------------------------------------------------------------
# 5. BUCLE PRINCIPAL
# ---------------------------------------------------------------------------
root.mainloop()

BIN
music.mp3 Normal file

Binary file not shown.