Index: sctry.py
===================================================================
--- sctry.py	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ sctry.py	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 """
-POPRAVEN CLIENT со фикс за Sysmon
+netIntel Client (Fixed + more reliable)
+- Sends payload to /receive with X-Env-Token header
 """
 
@@ -9,14 +10,43 @@
 import json
 import requests
-from datetime import datetime, timedelta
+from datetime import datetime
 import psutil
 import time
 import subprocess
-import re
-from collections import defaultdict
-
-
+import getpass
+
+
+# ----------------------------
+# Helpers
+# ----------------------------
+def safe_username():
+    try:
+        return os.getlogin()
+    except Exception:
+        return getpass.getuser()
+
+
+def get_local_ip_fallback():
+    """
+    More reliable local IP than socket.gethostbyname(hostname).
+    """
+    try:
+        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+        s.connect(("8.8.8.8", 80))
+        ip = s.getsockname()[0]
+        s.close()
+        return ip
+    except Exception:
+        try:
+            return socket.gethostbyname(socket.gethostname())
+        except Exception:
+            return "127.0.0.1"
+
+
+# ----------------------------
+# Sysmon-like collector (simulated)
+# ----------------------------
 class FixedSysmonCollector:
-    """Симплифициран колектор што работи без инсталиран Sysmon"""
+    """Simplified collector - works even without Sysmon installed"""
 
     def __init__(self):
@@ -24,24 +54,24 @@
 
     def collect_sysmon_events(self, limit=50):
-        """Симулирај Sysmon настани од процеси и мрежа"""
         events = []
-
-        try:
-            # 1. Процес настани (Event ID 1 = Process Creation)
+        now = datetime.now()
+
+        try:
+            # 1) Process events (Event ID 1)
             for proc in psutil.process_iter(['pid', 'name', 'create_time', 'username']):
                 try:
                     pinfo = proc.info
-                    if pinfo['create_time']:
-                        create_time = datetime.fromtimestamp(pinfo['create_time'])
-                        # Додади само процеси креирани во последните 5 минути
-                        if not self.last_collection or create_time > self.last_collection:
+                    ct = pinfo.get('create_time')
+                    if ct:
+                        create_time = datetime.fromtimestamp(ct)
+                        if (not self.last_collection) or (create_time > self.last_collection):
                             events.append({
                                 "event_id": 1,
                                 "event_type": "Process Creation",
-                                "message": f"Process created: {pinfo['name']} (PID: {pinfo['pid']}, User: {pinfo['username']})",
+                                "message": f"Process created: {pinfo.get('name')} (PID: {pinfo.get('pid')}, User: {pinfo.get('username')})",
                                 "timestamp": create_time.isoformat(),
-                                "process_name": pinfo['name'],
-                                "pid": pinfo['pid'],
-                                "user": pinfo['username']
+                                "process_name": pinfo.get('name'),
+                                "pid": pinfo.get('pid'),
+                                "user": pinfo.get('username'),
                             })
                 except (psutil.NoSuchProcess, psutil.AccessDenied):
@@ -51,5 +81,5 @@
                     break
 
-            # 2. Мрежни конекции (Event ID 3 = Network Connection)
+            # 2) Network connections (Event ID 3)
             for conn in psutil.net_connections(kind='inet'):
                 try:
@@ -59,11 +89,13 @@
                             "event_id": 3,
                             "event_type": "Network Connection",
-                            "message": f"Network {conn.status}: {conn.laddr.ip if conn.laddr else 'N/A'}:{conn.laddr.port if conn.laddr else 'N/A'} -> {conn.raddr.ip}:{conn.raddr.port}",
-                            "timestamp": datetime.now().isoformat(),
+                            "message": f"Network {conn.status}: "
+                                       f"{conn.laddr.ip if conn.laddr else 'N/A'}:{conn.laddr.port if conn.laddr else 'N/A'} "
+                                       f"-> {conn.raddr.ip}:{conn.raddr.port}",
+                            "timestamp": now.isoformat(),
                             "local_address": f"{conn.laddr.ip}:{conn.laddr.port}" if conn.laddr else None,
                             "remote_address": f"{conn.raddr.ip}:{conn.raddr.port}",
                             "status": conn.status,
                             "pid": conn.pid,
-                            "process_name": proc.name() if proc else "Unknown"
+                            "process_name": proc.name() if proc else "Unknown",
                         })
                 except (psutil.NoSuchProcess, psutil.AccessDenied):
@@ -73,5 +105,5 @@
                     break
 
-            # 3. Системски перформанси настани
+            # 3) Performance alerts (optional)
             cpu = psutil.cpu_percent(interval=0.1)
             if cpu > 80:
@@ -80,5 +112,5 @@
                     "event_type": "High CPU Usage",
                     "message": f"High CPU usage detected: {cpu:.1f}%",
-                    "timestamp": datetime.now().isoformat(),
+                    "timestamp": now.isoformat(),
                     "cpu_percent": cpu
                 })
@@ -90,5 +122,5 @@
                     "event_type": "High Memory Usage",
                     "message": f"High RAM usage: {ram.percent:.1f}%",
-                    "timestamp": datetime.now().isoformat(),
+                    "timestamp": now.isoformat(),
                     "ram_percent": ram.percent
                 })
@@ -97,15 +129,15 @@
             print(f"FixedSysmon error: {e}")
 
-        self.last_collection = datetime.now()
+        self.last_collection = now
         return events
 
-    def collect_network_connections_detailed(self):
-        """Детални мрежни конекции"""
+    def collect_network_connections_detailed(self, limit=30):
         connections = []
+        now = datetime.now().isoformat()
+
         try:
             for conn in psutil.net_connections(kind='inet'):
                 try:
                     proc = psutil.Process(conn.pid) if conn.pid else None
-
                     conn_info = {
                         "pid": conn.pid,
@@ -113,5 +145,5 @@
                         "family": str(conn.family),
                         "type": str(conn.type),
-                        "timestamp": datetime.now().isoformat()
+                        "timestamp": now
                     }
 
@@ -127,9 +159,14 @@
 
                     if proc:
-                        conn_info.update({
-                            "process_name": proc.name(),
-                            "process_cmdline": ' '.join(proc.cmdline()) if proc.cmdline() else None,
-                            "process_username": proc.username() if hasattr(proc, 'username') else None
-                        })
+                        conn_info["process_name"] = proc.name()
+                        try:
+                            cmd = proc.cmdline()
+                            conn_info["process_cmdline"] = " ".join(cmd) if cmd else None
+                        except Exception:
+                            conn_info["process_cmdline"] = None
+                        try:
+                            conn_info["process_username"] = proc.username()
+                        except Exception:
+                            conn_info["process_username"] = None
 
                     connections.append(conn_info)
@@ -138,5 +175,5 @@
                     continue
 
-                if len(connections) >= 30:
+                if len(connections) >= limit:
                     break
 
@@ -147,13 +184,15 @@
 
     def collect_all_security_data(self):
-        """Собери сите безбедносни податоци (очекуваниот метод!)"""
         return {
             "sysmon_events": self.collect_sysmon_events(limit=50),
-            "network_connections": self.collect_network_connections_detailed(),
-            "file_changes": [],  # Празен лист, можеш да го имплементираш подоцна
+            "network_connections": self.collect_network_connections_detailed(limit=30),
+            "file_changes": [],
             "collection_time": datetime.now().isoformat()
         }
 
 
+# ----------------------------
+# Client
+# ----------------------------
 class EnhancedFixedClient:
     def __init__(self, server_ip="192.168.1.13", port=5555, env_token=None):
@@ -161,28 +200,15 @@
         self.port = port
         self.computer_name = socket.gethostname()
-        self.user = os.getlogin()
+        self.user = safe_username()
         self.sysmon_collector = FixedSysmonCollector()
         self.env_token = env_token
-        # Користи поправената верзија
-
-    def get_detailed_info(self):
-        """Собирај подробни податоци"""
-        info = {
-            "computer_name": self.computer_name,
-            "user": self.user,
-            "ip_address": socket.gethostbyname(self.computer_name),
-            "os": f"{platform.system()} {platform.release()} {platform.version()}",
-            "architecture": platform.architecture()[0],
-            "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
-            "is_sysmon_available": self._check_sysmon_installed()
-        }
-
-        info.update(self.get_performance_metrics())
-        info.update(self.get_hardware_info())
-
-        return info
+
+        # warmup cpu_percent so it doesn't start at 0
+        try:
+            psutil.cpu_percent(interval=None)
+        except Exception:
+            pass
 
     def _check_sysmon_installed(self):
-        """Провери дали Sysmon е инсталиран"""
         try:
             if platform.system() == "Windows":
@@ -192,20 +218,16 @@
                 )
                 return result.returncode == 0
-        except:
+        except Exception:
             pass
         return False
 
     def get_performance_metrics(self):
-        """Метрики за перформанси - ПОПРАВЕНО БЕЗ DEPRECATION WARNING"""
-        try:
-            cpu_percent = psutil.cpu_percent(interval=1)
+        try:
+            cpu_percent = psutil.cpu_percent(interval=0.5)
             cpu_freq = psutil.cpu_freq()
-
             ram = psutil.virtual_memory()
             swap = psutil.swap_memory()
-
             disk = psutil.disk_usage("C:/" if platform.system() == "Windows" else "/")
 
-            # ДОБАВИ TRY-EXCEPT за disk_io_counters
             disk_read_mb = 0
             disk_write_mb = 0
@@ -215,8 +237,11 @@
                     disk_read_mb = round(disk_io.read_bytes / (1024 ** 2), 2)
                     disk_write_mb = round(disk_io.write_bytes / (1024 ** 2), 2)
-            except:
+            except Exception:
                 pass
 
             net_io = psutil.net_io_counters()
+
+            boot_dt = datetime.fromtimestamp(psutil.boot_time())
+            uptime_hours = round((datetime.now() - boot_dt).total_seconds() / 3600, 2)
 
             return {
@@ -237,6 +262,6 @@
                 "network_packets_sent": net_io.packets_sent,
                 "network_packets_recv": net_io.packets_recv,
-                "boot_time": datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S"),
-                "uptime_hours": round((datetime.now() - datetime.fromtimestamp(psutil.boot_time())).seconds / 3600, 2)
+                "boot_time": boot_dt.strftime("%Y-%m-%d %H:%M:%S"),
+                "uptime_hours": uptime_hours
             }
         except Exception as e:
@@ -245,5 +270,4 @@
 
     def get_hardware_info(self):
-        """Хардвер информации"""
         try:
             partitions = []
@@ -260,8 +284,7 @@
                         "percent_used": usage.percent
                     })
-                except:
-                    continue
-
-            # Мрежни интерфејси
+                except Exception:
+                    continue
+
             net_if_addrs = psutil.net_if_addrs()
             interfaces = {}
@@ -271,8 +294,15 @@
                         "family": str(addr.family),
                         "address": addr.address,
-                        "netmask": addr.netmask if hasattr(addr, 'netmask') else None
+                        "netmask": getattr(addr, "netmask", None)
                     }
-                    for addr in addrs if addr.address
+                    for addr in addrs if getattr(addr, "address", None)
                 ]
+
+            batt = None
+            try:
+                b = psutil.sensors_battery()
+                batt = b.percent if b else None
+            except Exception:
+                batt = None
 
             return {
@@ -281,6 +311,5 @@
                 "disks": partitions,
                 "network_interfaces": interfaces,
-                "battery_percent": psutil.sensors_battery().percent if hasattr(psutil.sensors_battery(),
-                                                                               'percent') else None,
+                "battery_percent": batt,
                 "temperatures": self._get_temperatures()
             }
@@ -290,8 +319,7 @@
 
     def _get_temperatures(self):
-        """Добиј температури на системот"""
         try:
             temps = {}
-            if hasattr(psutil, 'sensors_temperatures'):
+            if hasattr(psutil, "sensors_temperatures"):
                 sensors = psutil.sensors_temperatures()
                 for name, entries in sensors.items():
@@ -299,38 +327,36 @@
                         temps[name] = entries[0].current
             return temps
-        except:
+        except Exception:
             return {}
 
-    def get_detailed_processes(self):
-        """Детални информации за процесите - ПОПРАВЕНО БЕЗ DEPRECATION WARNING"""
+    def get_detailed_processes(self, limit=100):
         processes = []
         try:
-            for proc in psutil.process_iter(['pid', 'name', 'username', 'cpu_percent',
-                                             'memory_percent', 'create_time', 'status']):
+            for proc in psutil.process_iter(['pid', 'name', 'username', 'cpu_percent', 'memory_percent',
+                                             'create_time', 'status']):
                 try:
                     pinfo = proc.info
-
-                    # КОРИСТИ psutil.Process() за да добиеш дополнителни информации
                     with proc.oneshot():
                         processes.append({
-                            "pid": pinfo['pid'],
-                            "name": pinfo['name'],
-                            "user": pinfo['username'],
-                            "cpu_percent": pinfo['cpu_percent'],
+                            "pid": pinfo.get("pid"),
+                            "name": pinfo.get("name"),
+                            "user": pinfo.get("username"),
+                            "cpu_percent": pinfo.get("cpu_percent"),
                             "memory_mb": round(proc.memory_info().rss / (1024 ** 2), 2),
-                            "memory_percent": pinfo['memory_percent'],
-                            "create_time": datetime.fromtimestamp(pinfo['create_time']).strftime("%Y-%m-%d %H:%M:%S") if
-                            pinfo['create_time'] else None,
-                            "status": pinfo['status'],
-                            "exe": proc.exe() if hasattr(proc, 'exe') else None,
-                            "cmdline": ' '.join(proc.cmdline()) if hasattr(proc, 'cmdline') else None,
-                            "num_threads": proc.num_threads() if hasattr(proc, 'num_threads') else None,
-                            # НЕ КОРИСТИ proc.connections() - тоа е deprecated!
-                            "connections_count": 0  # Стави 0 или избриши го ова поле
+                            "memory_percent": pinfo.get("memory_percent"),
+                            "create_time": datetime.fromtimestamp(pinfo["create_time"]).strftime("%Y-%m-%d %H:%M:%S")
+                            if pinfo.get("create_time") else None,
+                            "status": pinfo.get("status"),
+                            "exe": proc.exe() if hasattr(proc, "exe") else None,
+                            "cmdline": " ".join(proc.cmdline()) if hasattr(proc, "cmdline") else None,
+                            "num_threads": proc.num_threads() if hasattr(proc, "num_threads") else None,
+                            "connections_count": 0
                         })
                 except (psutil.NoSuchProcess, psutil.AccessDenied):
                     continue
-
-                if len(processes) >= 100:
+                except Exception:
+                    continue
+
+                if len(processes) >= limit:
                     break
 
@@ -340,137 +366,129 @@
         return processes
 
+    def get_detailed_info(self):
+        info = {
+            "computer_name": self.computer_name,
+            "user": self.user,
+            "ip_address": get_local_ip_fallback(),
+            "os": f"{platform.system()} {platform.release()} {platform.version()}",
+            "architecture": platform.architecture()[0],
+            "timestamp": datetime.now().isoformat(),
+            "is_sysmon_available": self._check_sysmon_installed()
+        }
+        info.update(self.get_performance_metrics())
+        info.update(self.get_hardware_info())
+        return info
+
     def collect_and_send(self):
-        """Собери и испрати сите податоци"""
-        print(f"\n[{datetime.now().strftime('%H:%M:%S')}] 🔍 Собирање податоци...")
-
-        # Собери сите податоци
+        print(f"\n[{datetime.now().strftime('%H:%M:%S')}] 🔍 Collecting...")
+
         data = {
             "info": self.get_detailed_info(),
-            "processes": self.get_detailed_processes(),
-            "security_data": self.sysmon_collector.collect_all_security_data(),  # ОВА СЕГА РАБОТИ!
+            "processes": self.get_detailed_processes(limit=100),
+            "security_data": self.sysmon_collector.collect_all_security_data(),
             "collection_time": datetime.now().isoformat(),
-            "client_version": "2.1_fixed"
+            "client_version": "2.2_fixed"
         }
 
-        # Прикажи основни информации
         info = data["info"]
-        sec_data = data["security_data"]
-
-        print(f"   💻 Компјутер: {info['computer_name']}")
-        print(f"   👤 Корисник: {info['user']}")
-        print(
-            f"   📊 CPU: {info.get('cpu_usage', 0)}% | RAM: {info.get('ram_usage', 0)}% | Disk: {info.get('disk_usage', 0)}%")
-        print(f"   🔄 Процеси: {len(data['processes'])}")
-        print(f"   🛡️  Sysmon настани: {len(sec_data.get('sysmon_events', []))}")
-        print(f"   🌐 Мрежни конекции: {len(sec_data.get('network_connections', []))}")
-
-        # Испрати ги податоците
-        try:
-            headers = {"X-Env-Token": self.env_token} if self.env_token else {}
-
-            response = requests.post(
-                f"http://{self.server_ip}:{self.port}/receive",
-                json=data,
-                headers=headers,
-                timeout=30
-            )
-
-            if response.status_code == 200:
-                result = response.json()
-                print(f"   ✅ Податоците се успешно испратени!")
-                if 'event_count' in result:
-                    print(f"   📝 Зачувани {result['event_count']} Sysmon настани")
+        sec = data["security_data"]
+
+        print(f"   💻 {info.get('computer_name')} | 👤 {info.get('user')}")
+        print(f"   📊 CPU {info.get('cpu_usage', 0)}% | RAM {info.get('ram_usage', 0)}% | Disk {info.get('disk_usage', 0)}%")
+        print(f"   🔄 Processes: {len(data['processes'])}")
+        print(f"   🛡️ Sysmon events: {len(sec.get('sysmon_events', []))}")
+        print(f"   🌐 Net conns: {len(sec.get('network_connections', []))}")
+
+        try:
+            headers = {}
+            if self.env_token:
+                headers["X-Env-Token"] = self.env_token
+            headers["X-Client-Id"] = self.computer_name  # optional
+
+            url = f"http://{self.server_ip}:{self.port}/receive"
+            r = requests.post(url, json=data, headers=headers, timeout=30)
+
+            if r.ok:
+                resp = r.json()
+                print("   ✅ Sent OK")
+                if "sysmon_events_saved" in resp:
+                    print(f"   📝 Saved sysmon: {resp['sysmon_events_saved']}")
                 return True
+
+            # errors
+            if r.status_code == 401:
+                try:
+                    msg = r.json()
+                except Exception:
+                    msg = {"error": r.text[:200]}
+                print("   🔒 Token invalid/expired. Generate new token in Admin panel.")
+                print(f"   Server says: {msg}")
             else:
-                if response.status_code == 401:
-                    try:
-                        msg = response.json()
-                    except:
-                        msg = {}
-                    print("   🔒 Token invalid/expired. Побарај нов token од Admin панел.")
-                    print(f"   Server says: {msg}")
-                else:
-                    print(f"   ❌ Грешка: {response.status_code}")
-                    try:
-                        print("   ", response.text[:300])
-                    except:
-                        pass
-                return False
-
-        except Exception as e:
-            print(f"   ❌ Проблем со серверот: {e}")
+                print(f"   ❌ HTTP {r.status_code}: {r.text[:300]}")
             return False
 
+        except Exception as e:
+            print(f"   ❌ Connection problem: {e}")
+            return False
+
 
 def main():
-    """Главна програма"""
     print("=" * 70)
-    print("🖥️  FIXED LAN LOG COLLECTOR v2.1")
+    print("🖥️  netIntel Collector (Fixed)")
     print("=" * 70)
-    print(f"Компјутер: {socket.gethostname()}")
-    print(f"Корисник: {os.getlogin()}")
-    print(f"IP: {socket.gethostbyname(socket.gethostname())}")
+    print(f"Computer: {socket.gethostname()}")
+    print(f"User: {safe_username()}")
+    print(f"Local IP: {get_local_ip_fallback()}")
     print("=" * 70)
-    print("Податоците ќе се собираат и испраќаат на секои 30 секунди.")
-    print("Притисни Ctrl+C за да го прекинеш.")
+    print("Will send every 30 seconds. Ctrl+C to stop.")
     print("=" * 70)
 
-    # Провери дали серверот е достапен
-    server_ip = input("Внеси сервер IP (default 192.168.1.13): ").strip() or "192.168.1.13"
-
-    env_token = input("Внеси ENV TOKEN (од Admin панел): ").strip()
+    server_ip = input("Server IP (default 192.168.1.13): ").strip() or "192.168.1.13"
+    env_token = input("ENV TOKEN (from Admin panel): ").strip()
     if not env_token:
-        print("❌ Мора ENV TOKEN за да се регистрира уредот.")
+        print("❌ ENV TOKEN is required.")
         return
 
     client = EnhancedFixedClient(server_ip, 5555, env_token=env_token)
-    # Тест конекција
-    print(f"\n🔌 Тестирање на врска со серверот {server_ip}...")
+
+    print(f"\n🔌 Testing server {server_ip}...")
     try:
-        response = requests.get(f"http://{server_ip}:5555/ping", timeout=5)
-        if response.status_code == 200:
-            print("   ✅ Серверот е достапен!")
+        r = requests.get(f"http://{server_ip}:5555/ping", timeout=5)
+        if r.ok:
+            print("   ✅ Server reachable")
         else:
-            print(f"   ⚠️  Серверот одговори со: {response.status_code}")
-            confirm = input("   Сакаш ли да продолжиш? (y/n): ").lower()
-            if confirm != 'y':
-                return
+            print(f"   ⚠️ Server responded: {r.status_code}")
     except Exception as e:
-        print(f"   ❌ Не можам да се поврзам со серверот {server_ip}: {e}")
-        confirm = input("   Сакаш ли да продолжиш? (y/n): ").lower()
-        if confirm != 'y':
-            return
+        print(f"   ❌ Can't reach server: {e}")
+        return
 
     try:
         count = 1
         while True:
-            print(f"\n📤 Трансмисија #{count}")
-
-            success = client.collect_and_send()
-
+            print(f"\n📤 Transmission #{count}")
+            client.collect_and_send()
             count += 1
-            print(f"\n⏳ Чекам 30 секунди до следната трансмисија...")
-
-            # Countdown
+
+            print("\n⏳ Waiting 30s...")
             for i in range(30, 0, -1):
                 if i % 10 == 0 or i <= 5:
-                    print(f"\r   {i} секунди остануваат...", end="")
+                    print(f"\r   {i} seconds remaining...", end="")
                 time.sleep(1)
             print("\r" + " " * 40 + "\r", end="")
 
     except KeyboardInterrupt:
-        print("\n\n🛑 Програмата е зајчана.")
-        print(f"📊 Dashboard: http://{server_ip}:5555/")
+        print("\n\n🛑 Stopped.")
+        print(f"📊 Dashboard/API: http://{server_ip}:5555/")
 
 
 if __name__ == "__main__":
     try:
-        import psutil
-        import requests
+        import psutil  # noqa
+        import requests  # noqa
     except ImportError:
-        print("Инсталирај ги модулите:")
+        print("Install modules:")
         print("pip install psutil requests")
-        input("Притисни ENTER за излез...")
-        exit(1)
+        input("Press ENTER to exit...")
+        raise SystemExit(1)
 
     main()
