automatic
This commit is contained in:
@@ -109,7 +109,7 @@
|
||||
"949388626146517022"
|
||||
],
|
||||
"user_name": "Marius",
|
||||
"default_voice": "M2",
|
||||
"default_voice": "F1",
|
||||
"auto_leave_minutes": 5
|
||||
},
|
||||
"paths": {
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
"report_on": "changes",
|
||||
"timeout": 120,
|
||||
"enabled": true,
|
||||
"last_run": "2026-05-28T16:00:00.002254+00:00",
|
||||
"last_run": "2026-05-29T10:00:00.003600+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-05-29T10:00:00+00:00"
|
||||
"next_run": "2026-05-29T16:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "security-audit-daily",
|
||||
@@ -39,9 +39,9 @@
|
||||
"report_on": "changes",
|
||||
"timeout": 180,
|
||||
"enabled": true,
|
||||
"last_run": "2026-05-28T03:00:00.003748+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-05-29T03:00:00+00:00"
|
||||
"last_run": "2026-05-29T03:00:00.002043+00:00",
|
||||
"last_status": "error",
|
||||
"next_run": "2026-05-30T03:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "kb-index-refresh",
|
||||
@@ -55,9 +55,9 @@
|
||||
"report_on": "never",
|
||||
"timeout": 120,
|
||||
"enabled": true,
|
||||
"last_run": "2026-05-28T03:30:00.003004+00:00",
|
||||
"last_run": "2026-05-29T03:30:00.002139+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-05-29T03:30:00+00:00"
|
||||
"next_run": "2026-05-30T03:30:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "archive-tasks-daily",
|
||||
@@ -71,9 +71,9 @@
|
||||
"report_on": "changes",
|
||||
"timeout": 60,
|
||||
"enabled": true,
|
||||
"last_run": "2026-05-28T03:00:00.003258+00:00",
|
||||
"last_run": "2026-05-29T03:00:00.001515+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-05-29T03:00:00+00:00"
|
||||
"next_run": "2026-05-30T03:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "backup-config",
|
||||
@@ -87,9 +87,9 @@
|
||||
"report_on": "never",
|
||||
"timeout": 120,
|
||||
"enabled": true,
|
||||
"last_run": "2026-05-28T02:00:00.003039+00:00",
|
||||
"last_run": "2026-05-29T02:00:00.002948+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-05-29T02:00:00+00:00"
|
||||
"next_run": "2026-05-30T02:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "insights-extract",
|
||||
@@ -255,9 +255,9 @@
|
||||
"prompt": "Heartbeat check. Rulează src/heartbeat.py printr-un scurt raport de status.\nDacă nu e nimic de raportat (email=0, calendar nu are evenimente <2h, kb ok), răspunde doar cu HEARTBEAT_OK și oprește-te — nu trimite mesaj.\nDacă e ceva: raport scurt pe Discord #echo-work.",
|
||||
"allowed_tools": [],
|
||||
"enabled": true,
|
||||
"last_run": "2026-05-28T18:00:00.001555+00:00",
|
||||
"last_run": "2026-05-29T12:00:00.002840+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-05-29T06:00:00+00:00"
|
||||
"next_run": "2026-05-29T14:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "night-execute",
|
||||
@@ -271,8 +271,8 @@
|
||||
"Read",
|
||||
"Write"
|
||||
],
|
||||
"last_run": "2026-05-27T23:00:00.001391+00:00",
|
||||
"last_run": "2026-05-28T23:00:00.002106+00:00",
|
||||
"last_status": "ok",
|
||||
"next_run": "2026-05-28T23:00:00+00:00"
|
||||
"next_run": "2026-05-29T23:00:00+00:00"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
{
|
||||
"notes": [
|
||||
{
|
||||
"file": "notes-data/emails/2026-05-29_fwd-invitatie-festivalul-luminii-brasov-2026.md",
|
||||
"title": "***SPAM*** Fwd: Invitație – Festivalul Luminii Brașov 2026",
|
||||
"date": "2026-05-29",
|
||||
"tags": [],
|
||||
"domains": [],
|
||||
"types": [],
|
||||
"category": "emails",
|
||||
"project": null,
|
||||
"subdir": null,
|
||||
"video": "",
|
||||
"tldr": "<!-- Echo: completează cu rezumat -->"
|
||||
},
|
||||
{
|
||||
"file": "notes-data/emails/2026-05-28_fwd-newsletter-20-din-2026.md",
|
||||
"title": "Newsletter 20 din 2026",
|
||||
"date": "2026-05-28",
|
||||
"tags": [],
|
||||
"domains": [],
|
||||
"types": [],
|
||||
"category": "emails",
|
||||
"project": null,
|
||||
"subdir": null,
|
||||
"video": "",
|
||||
"tldr": "<!-- Echo: completează cu rezumat -->"
|
||||
},
|
||||
{
|
||||
"file": "notes-data/facebook/2026-05-26_500k-views-4-8k-reactions.md",
|
||||
"title": "500K views · 4.8K reactions",
|
||||
@@ -9157,8 +9183,8 @@
|
||||
"title": "Proiect: Vending Master - Integrare Website → ROA",
|
||||
"date": "2026-01-30",
|
||||
"tags": [
|
||||
"vending-master",
|
||||
"integrare"
|
||||
"integrare",
|
||||
"vending-master"
|
||||
],
|
||||
"domains": [
|
||||
"work"
|
||||
@@ -9638,7 +9664,7 @@
|
||||
}
|
||||
],
|
||||
"stats": {
|
||||
"total": 556,
|
||||
"total": 558,
|
||||
"by_domain": {
|
||||
"work": 182,
|
||||
"health": 100,
|
||||
@@ -9650,7 +9676,7 @@
|
||||
"articole": 1,
|
||||
"coaching": 51,
|
||||
"conversations": 0,
|
||||
"emails": 22,
|
||||
"emails": 24,
|
||||
"exercitii": 4,
|
||||
"facebook": 8,
|
||||
"health": 6,
|
||||
|
||||
@@ -889,6 +889,25 @@ def create_bot(config: Config) -> discord.Client:
|
||||
f"Error reading logs: {e}", ephemeral=True
|
||||
)
|
||||
|
||||
def _wav_to_ogg(wav_path: str) -> str:
|
||||
"""Convertește WAV → OGG Opus pentru upload Discord (10x mai mic). Returnează path-ul OGG."""
|
||||
import subprocess, tempfile
|
||||
ogg_path = wav_path.replace(".wav", ".ogg")
|
||||
if not ogg_path.endswith(".ogg"):
|
||||
ogg_path = wav_path + ".ogg"
|
||||
try:
|
||||
subprocess.run(
|
||||
[
|
||||
"/home/moltbot/.local/bin/ffmpeg", "-y", "-i", wav_path,
|
||||
"-c:a", "libopus", "-b:a", "24k", "-ar", "24000", ogg_path,
|
||||
],
|
||||
capture_output=True,
|
||||
timeout=30,
|
||||
)
|
||||
return ogg_path if os.path.exists(ogg_path) else wav_path
|
||||
except Exception:
|
||||
return wav_path
|
||||
|
||||
@tree.command(name="audio", description="TTS: convertește text sau URL în voice note")
|
||||
@app_commands.describe(
|
||||
voce="Voce (M1-M5 masculin, F1-F5 feminin; default M2)",
|
||||
@@ -930,17 +949,20 @@ def create_bot(config: Config) -> discord.Client:
|
||||
result = await asyncio.to_thread(fast_dispatch, "audio", [voice, chunk])
|
||||
if result and result.startswith("__AUDIO__:"):
|
||||
wav_path = result[len("__AUDIO__:"):]
|
||||
ogg_path = await asyncio.to_thread(_wav_to_ogg, wav_path)
|
||||
try:
|
||||
filename = f"echo-audio-{i}din{total}.wav" if total > 1 else "echo-audio.wav"
|
||||
ext = "ogg" if ogg_path.endswith(".ogg") else "wav"
|
||||
filename = f"echo-audio-{i}din{total}.{ext}" if total > 1 else f"echo-audio.{ext}"
|
||||
await interaction.followup.send(
|
||||
content=f"Bucata {i}/{total}" if total > 1 else None,
|
||||
file=discord.File(wav_path, filename=filename),
|
||||
file=discord.File(ogg_path, filename=filename),
|
||||
)
|
||||
finally:
|
||||
try:
|
||||
os.unlink(wav_path)
|
||||
except OSError:
|
||||
pass
|
||||
for p in {wav_path, ogg_path}:
|
||||
try:
|
||||
os.unlink(p)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
await interaction.followup.send(result or f"Eroare TTS la bucata {i}.")
|
||||
return
|
||||
@@ -957,15 +979,18 @@ def create_bot(config: Config) -> discord.Client:
|
||||
result = await asyncio.to_thread(fast_dispatch, "audio", args)
|
||||
if result and result.startswith("__AUDIO__:"):
|
||||
wav_path = result[len("__AUDIO__:"):]
|
||||
ogg_path = await asyncio.to_thread(_wav_to_ogg, wav_path)
|
||||
try:
|
||||
ext = "ogg" if ogg_path.endswith(".ogg") else "wav"
|
||||
await interaction.followup.send(
|
||||
file=discord.File(wav_path, filename="echo-audio.wav")
|
||||
file=discord.File(ogg_path, filename=f"echo-audio.{ext}")
|
||||
)
|
||||
finally:
|
||||
try:
|
||||
os.unlink(wav_path)
|
||||
except OSError:
|
||||
pass
|
||||
for p in {wav_path, ogg_path}:
|
||||
try:
|
||||
os.unlink(p)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
await interaction.followup.send(result or "Eroare TTS.")
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"D100": "126ebae8fc65d7ae19c9fe14e755c6421152aac16b19abf7fafeaa34aa87cafe",
|
||||
"D100": "27cf97a4d10c8529669d95b2d96ca3c9b41f7e4e50091dce19cf8af117f0ac4a",
|
||||
"D101": "f72fc1c29657ea11e0238806a28f6abccf5b00e45904e1e0c9385cc64491fcaf",
|
||||
"D300": "cb7b55b568ab893024884971eac0367fb6fe487c297e355d64258dae437f6ddd",
|
||||
"D394": "c4c4e62bda30032f12c17edf9a5087b6173a350ccb1fd750158978b3bd0acb7d",
|
||||
|
||||
@@ -62,7 +62,7 @@ valabil începand cu
|
||||
01/2024 - publicat în data de 09.02.2024
|
||||
soft A
|
||||
actualizat în data de
|
||||
22.05.2026
|
||||
29.05.2026
|
||||
soft J*
|
||||
actualizat în data de
|
||||
25.05.2026
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"D100": {
|
||||
"soft_a_url": "http://static.anaf.ro/static/10/Anaf/Declaratii_R/AplicatiiDec/D100_710_XML_0126_220526.pdf",
|
||||
"soft_a_date": "22.05.2026",
|
||||
"soft_a_url": "http://static.anaf.ro/static/10/Anaf/Declaratii_R/AplicatiiDec/D100_710_XML_0126_290526.pdf",
|
||||
"soft_a_date": "29.05.2026",
|
||||
"soft_j_url": "http://static.anaf.ro/static/10/Anaf/Declaratii_R/AplicatiiDec/D100_22052026.zip",
|
||||
"soft_j_date": "22.05.2026"
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ def get_owner_jid() -> str:
|
||||
return f"{owner}@s.whatsapp.net"
|
||||
|
||||
|
||||
def fetch_unread_emails() -> list[dict]:
|
||||
def fetch_unread_emails(skip_whitelist: bool = False) -> list[dict]:
|
||||
"""Preia emailurile necitite din inbox fără a salva KB notes."""
|
||||
mail = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT)
|
||||
mail.login(IMAP_USER, IMAP_PASS)
|
||||
@@ -66,7 +66,7 @@ def fetch_unread_emails() -> list[dict]:
|
||||
from_addr = decode_mime_header(msg['From'])
|
||||
sender_email = extract_sender_email(from_addr)
|
||||
|
||||
if sender_email not in WHITELIST:
|
||||
if not skip_whitelist and sender_email not in WHITELIST:
|
||||
continue
|
||||
|
||||
attachment_data = {}
|
||||
@@ -197,7 +197,7 @@ def send_whatsapp_document(to: str, filename: str, data: bytes) -> bool:
|
||||
|
||||
def run_digest():
|
||||
print("Verific emailuri necitite...")
|
||||
emails = fetch_unread_emails()
|
||||
emails = fetch_unread_emails(skip_whitelist=True)
|
||||
|
||||
owner_jid = get_owner_jid()
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ def send_whatsapp_document(to: str, filename: str, data: bytes) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def fetch_unread_emails():
|
||||
def fetch_unread_emails(skip_whitelist: bool = False):
|
||||
"""Preia emailurile necitite din inbox fără a le salva sau marca ca citite."""
|
||||
mail = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT)
|
||||
mail.login(IMAP_USER, IMAP_PASS)
|
||||
@@ -171,7 +171,7 @@ def fetch_unread_emails():
|
||||
from_addr = decode_mime_header(msg['From'])
|
||||
sender_email = extract_sender_email(from_addr)
|
||||
|
||||
if sender_email not in WHITELIST:
|
||||
if not skip_whitelist and sender_email not in WHITELIST:
|
||||
continue
|
||||
|
||||
# Extract attachment data (name → bytes)
|
||||
@@ -216,7 +216,7 @@ def mark_as_seen(email_ids: list[str]) -> None:
|
||||
|
||||
def run_forward():
|
||||
print("Verific emailuri necitite...")
|
||||
emails = fetch_unread_emails()
|
||||
emails = fetch_unread_emails(skip_whitelist=True)
|
||||
|
||||
owner_jid = get_owner_jid()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user