Initial commit - workspace setup

- AGENTS.md, SOUL.md, USER.md, IDENTITY.md
- ANAF monitor (declarații fiscale)
- Kanban board + Notes UI
- Email tools
- Memory system
This commit is contained in:
Echo
2026-01-29 13:11:59 +00:00
commit f9912e0081
52 changed files with 23148 additions and 0 deletions

193
anaf-monitor/monitor_v2.py Normal file
View File

@@ -0,0 +1,193 @@
#!/usr/bin/env python3
"""
ANAF Monitor v2 - Extrage și compară versiuni soft A/J din numele fișierelor
"""
import json
import re
import urllib.request
import ssl
from datetime import datetime
from pathlib import Path
SCRIPT_DIR = Path(__file__).parent
CONFIG_FILE = SCRIPT_DIR / "config.json"
VERSIONS_FILE = SCRIPT_DIR / "versions.json"
LOG_FILE = SCRIPT_DIR / "monitor.log"
SSL_CTX = ssl.create_default_context()
SSL_CTX.check_hostname = False
SSL_CTX.verify_mode = ssl.CERT_NONE
def log(msg):
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(LOG_FILE, "a") as f:
f.write(f"[{timestamp}] {msg}\n")
def load_json(path, default=None):
try:
with open(path) as f:
return json.load(f)
except:
return default if default is not None else {}
def save_json(path, data):
with open(path, "w") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def fetch_page(url, timeout=30):
try:
req = urllib.request.Request(url, headers={
'User-Agent': 'Mozilla/5.0 (compatible; ANAF-Monitor/2.0)'
})
with urllib.request.urlopen(req, timeout=timeout, context=SSL_CTX) as resp:
return resp.read().decode('utf-8', errors='ignore')
except Exception as e:
log(f"ERROR fetching {url}: {e}")
return None
def parse_date_from_filename(filename):
"""Extrage data din numele fișierului (ex: D394_26092025.pdf -> 26.09.2025)"""
# Pattern: _DDMMYYYY. sau _DDMMYYYY_ sau _YYYYMMDD
match = re.search(r'_(\d{8})[\._]', filename)
if match:
d = match.group(1)
# Verifică dacă e DDMMYYYY sau YYYYMMDD
if int(d[:2]) <= 31 and int(d[2:4]) <= 12:
return f"{d[:2]}.{d[2:4]}.{d[4:]}"
elif int(d[4:6]) <= 12 and int(d[6:]) <= 31:
return f"{d[6:]}.{d[4:6]}.{d[:4]}"
# Pattern: _DDMMYY
match = re.search(r'_(\d{6})[\._]', filename)
if match:
d = match.group(1)
if int(d[:2]) <= 31 and int(d[2:4]) <= 12:
return f"{d[:2]}.{d[2:4]}.20{d[4:]}"
return None
def extract_versions(html):
"""Extrage primul soft A și soft J din HTML"""
versions = {}
# Găsește primul link soft A (PDF)
soft_a_match = re.search(
r'<a[^>]+href=["\']([^"\']*\.pdf)["\'][^>]*>\s*soft\s*A\s*</a>',
html, re.IGNORECASE
)
if soft_a_match:
url = soft_a_match.group(1)
versions['soft_a_url'] = url
date = parse_date_from_filename(url)
if date:
versions['soft_a_date'] = date
# Găsește primul link soft J (ZIP)
soft_j_match = re.search(
r'<a[^>]+href=["\']([^"\']*\.zip)["\'][^>]*>\s*soft\s*J',
html, re.IGNORECASE
)
if soft_j_match:
url = soft_j_match.group(1)
versions['soft_j_url'] = url
date = parse_date_from_filename(url)
if date:
versions['soft_j_date'] = date
# Găsește data publicării din text
publish_match = re.search(
r'publicat\s+[îi]n\s*(?:data\s+de\s*)?(\d{2}[./]\d{2}[./]\d{4})',
html, re.IGNORECASE
)
if publish_match:
versions['published'] = publish_match.group(1).replace('/', '.')
return versions
def format_date(d):
"""Formatează data pentru afișare"""
if not d:
return "N/A"
return d
def compare_versions(old, new, page_name):
"""Compară versiunile și returnează diferențele"""
changes = []
fields = [
('soft_a_date', 'Soft A'),
('soft_j_date', 'Soft J'),
('published', 'Publicat')
]
for field, label in fields:
old_val = old.get(field)
new_val = new.get(field)
if new_val and old_val != new_val:
if old_val:
changes.append(f"{label}: {old_val}{new_val}")
else:
changes.append(f"{label}: {new_val} (nou)")
return changes
def check_page(page, saved_versions):
"""Verifică o pagină și returnează modificările"""
page_id = page["id"]
name = page["name"]
url = page["url"]
html = fetch_page(url)
if html is None:
return None
new_versions = extract_versions(html)
old_versions = saved_versions.get(page_id, {})
# Prima rulare - doar salvează, nu raportează
if not old_versions:
log(f"INIT: {page_id} - {new_versions}")
saved_versions[page_id] = new_versions
return None
changes = compare_versions(old_versions, new_versions, name)
saved_versions[page_id] = new_versions
if changes:
log(f"CHANGES in {page_id}: {changes}")
return {
"id": page_id,
"name": name,
"url": url,
"changes": changes,
"current": {
"soft_a": new_versions.get('soft_a_date', 'N/A'),
"soft_j": new_versions.get('soft_j_date', 'N/A')
}
}
else:
log(f"OK: {page_id}")
return None
def main():
log("=== Starting ANAF monitor v2 ===")
config = load_json(CONFIG_FILE, {"pages": []})
saved_versions = load_json(VERSIONS_FILE, {})
all_changes = []
for page in config["pages"]:
result = check_page(page, saved_versions)
if result:
all_changes.append(result)
save_json(VERSIONS_FILE, saved_versions)
log("=== Monitor complete ===")
print(json.dumps({"changes": all_changes}, ensure_ascii=False, indent=2))
return len(all_changes)
if __name__ == "__main__":
exit(main())