
    Jiy-                         d dl Z d dlZd dlZd dlmZmZ d dlmZmZmZ d dl	Z	d dl
Z
d dlmZmZ d dlZ e
j                  e      Z G d d      Zy)    N)datetime	timedelta)ListDictOptional)ThreadPoolExecutoras_completedc            
           e Zd ZdZddZdee   fdZdedede	e
   fdZd	e
de	e   fd
Zddedee   dee
   fdZdee
   fdZdee
   fdZ	 	 ddedededee
   fdZdee
   dee
   fdZy)DeveloperDiscoveryzKAutomatically discover ActivityWatch instances on network and local machineNc                 @    || _         g | _        g d| _        d| _        y )N)  i  i  i  iD     )
db_sessiondiscovered_developersdefault_portstimeout)selfr   s     9E:\timesheet\timesheet_new\backend\developer_discovery.py__init__zDeveloperDiscovery.__init__   s     $%'";    returnc                    g }	 t        j                         }t        j                  |      }|rE|j                  d      s4dj	                  |j                  d      dd       }|j                  |       g d}|D ]  }||vs|j                  |        	 |dd S # t        $ r&}t        j                  d|        g d}Y d}~/d}~ww xY w)z5Get local network ranges to scan (simplified version)z127..N)z	192.168.1z	192.168.0z10.0.0z172.16.0z$Could not determine local networks: r   )
socketgethostnamegethostbyname
startswithjoinsplitappend	Exceptionloggerwarning)r   networkshostnamelocal_ipbase_ipcommon_networksnetworkes           r   get_local_networksz%DeveloperDiscovery.get_local_networks   s    	H))+H++H5H  3 3F ;((8>>##6s#;<( OO*(*OOG, + |  	HNNA!EFGH	Hs   A=B B 	C
$CC
hostportc                    	 d| d| d}t        j                  || j                        }|j                  dk(  r|j	                         }t        j                  d| d| d| j                        }|j                  dk(  r|j	                         ni }| j                  |      xs |j                  d|      }| d| ||||j                  d	d
      ||j                  d| d|       t        |j                               t        |      d| t        j                         j                         ddS y# t        $ r(}	t        j                  d| d| d|	        Y d}	~	yd}	~	ww xY w)z7Check if ActivityWatch is running on specific host:portzhttp://:z/api/0/info)r      z/api/0/bucketsr&   _versionunknown	device_idzActivityWatch on online)idnamer-   r.   r3   r&   r5   bucketsbucket_countdescriptiondiscovered_atstatuszNo ActivityWatch at z: N)requestsgetr   status_codejsonextract_hostname_from_bucketslistkeyslenr   now	isoformatr"   r#   debug)
r   r-   r.   urlresponseinfobuckets_responser9   r&   r+   s
             r   check_activitywatch_instancez/DeveloperDiscovery.check_activitywatch_instance2   sp   	D64&4C||C>H##s*}} $,<<'$qn0U_c_k_k#l 5E5Q5QUX5X*//1^`  ==gFd$((S]_cJd &Jav.$  #xx	9= (!%+(1TF7K!L#GLLN3$'L%6xj#A%-\\^%=%=%?&  +0  	LL/vQtfBqcBC	s   D2D6 6	E'?E""E'r9   c                     |j                         D ]-  }d|v s|j                  d      }t        |      dkD  s(|d   c S  y)z"Extract hostname from bucket namesr2      r   N)rD   r    rE   )r   r9   bucket_namepartss       r   rB   z0DeveloperDiscovery.extract_hostname_from_bucketsT   sD    "<<>Kk!#))#.u:> 9$ * r   network_baseportsc                     | j                   }g } fd}g }t        dd      D ]#  }| d| }|D ]  }|j                  ||f        % t        d      5 }	|D 
ci c]  }
|	j	                  ||
      |
 }}
t        |      D ]M  }|j                         }|s|j                  |       t        j                  d|d	    d
|d    d|d           O 	 ddd       |S c c}
w # 1 sw Y   |S xY w)z0Scan a network range for ActivityWatch instancesNc                 <    | \  }}j                  ||      }|r|S y N)rM   )	host_portr-   r.   resultr   s       r   check_host_portz>DeveloperDiscovery.scan_network_range.<locals>.check_host_porte   s)    "JD$66tTBFr   rO   2   r      max_workerszDiscovered ActivityWatch: r8   z at r-   r0   r.   )	r   ranger!   r   submitr	   rX   r#   rK   )r   rR   rS   
discoveredrY   host_port_combinationsir-   r.   executorhpfuture_to_host_portfuturerX   s   `             r   scan_network_rangez%DeveloperDiscovery.scan_network_range^   s#   =&&E
	 "$q"A"^1QC(D&--tTl;    B/8 1#0B 4b80   #
 '':;%%f-KK"<VF^<LDQWX^Q_P``abhiobpaq rs	 < 0 # 0 s$   C#C6"C#:C#C##C-c                 V   g }ddg}|D ]  }| j                   D ]{  }| j                  ||      }|s|d   dv rK	 t        j                         |d<   t        j                         |d<   t        j                          d| |d<   |j	                  |          |S #  d|d<   d|d<   Y &xY w)	z-Discover ActivityWatch instances on localhost	127.0.0.1	localhostr8   )ri   rj   r&   r2   r7   zLocal Machine)r   rM   r   r   r!   )r   r`   localhost_addressesr-   r.   rX   s         r   discover_local_instancesz+DeveloperDiscovery.discover_local_instances   s    
  +K8'D**::4Ff~)CC=-3-?-?-AF6N171C1C1EF:..4.@.@.B-C1TF+KF4L %%f- + (  =-<F6N1<F:.s   A
BB(c                 6   | j                   sg S 	 ddlm}  |d      }t        j                         t        d      z
  }| j                   j                  |d|i      }g }|D ]  }|j                  |j                  |j                  dd|j                  |j                  d	|j                   d
|j                  r|j                  j                         nd|j                  ddd        |S # t        $ r$}t        j                  d|        g cY d}~S d}~ww xY w)z2Discover developers from database activity recordsr   )texta  
                SELECT DISTINCT 
                    developer_id,
                    MAX(created_at) as last_seen,
                    COUNT(*) as activity_count
                FROM activity_records 
                WHERE developer_id IS NOT NULL 
                    AND created_at > :last_month
                GROUP BY developer_id
                ORDER BY last_seen DESC
            r[   )days
last_monthr4   r   zFrom database records (z activities)Ndatabase)r7   r8   r-   r.   r&   r5   r;   	last_seenactivity_countsourcer=   z!Error discovering from database: )r   
sqlalchemyrn   r   rF   r   executer!   developer_idrs   rr   rG   r"   r#   error)r   rn   queryrp   rX   db_developersrowr+   s           r   discover_from_databasez)DeveloperDiscovery.discover_from_database   s   I(	'  
 
E ")*<<J__,,U\:4NOFM$$**,,%  # 0 0!$!1!1%<S=O=O<PP\#]>Amm!8!8!:QU&)&8&8('&   !  	LL<QC@AI	s   CC+ +	D4DDDscan_network
scan_localscan_databasec                 J   g }|rXt         j                  d       | j                         }|j                  |       t         j                  dt	        |       d       |rXt         j                  d       | j                         }|j                  |       t         j                  dt	        |       d       |rt         j                  d       | j                         }|dd D ]b  }t         j                  d	| d
       | j                  |      }	|j                  |	       t         j                  dt	        |	       d| d       d i }
|D ]  }|j                  d      xs |d    d|d    }||
vr||
|<   -|
|   }|j                  d      dk(  sG|j                  d      rY|j                  dd      |d<   |j                  d      |d<    t        |
j                               | _        t         j                  dt	        | j                                | j                  S )z2Discover all available developers from all sourcesz,Discovering local ActivityWatch instances...zFound z local instancesz'Discovering developers from database...z developers in databasez/Scanning network for ActivityWatch instances...N   zScanning network z.x...z instances on z.xr5   r-   r0   r.   rt   rq   rs   r   rr   z$Total unique developers discovered: )r#   rK   rl   extendrE   r|   r,   rg   r?   rC   valuesr   )r   r}   r~   r   all_developers
local_devsdb_devsr%   r*   network_devsunique_developersdevkeyexistings                 r   discover_all_developersz*DeveloperDiscovery.discover_all_developers   s     KKFG668J!!*-KK&Z 11ABC KKAB113G!!'*KK&W.EFG KKIJ..0H#BQ</y>?#66w?%%l3fS%6$7~gYbQR	 ( !C''+&HS[M3v;-*HC++),!#& -S1778$
28<<HX;Y149I11MH-.,/GGK,@H[) " &**;*B*B*D%E":3t?Y?Y;Z:[\])))r   
developersc                       fd}t        d      5 }t        |j                  ||            }ddd       |S # 1 sw Y   S xY w)z(Refresh online status for all developersc                     | j                  d      dk(  r| j                  d      dk(  rd| d<   | S j                  | d   | d         }|rdnd	| d<   t        j                         j	                         | d
<   | S )Nrt   rq   r-   r4   database_onlyr=   r.   r6   offlinelast_checked)r?   rM   r   rF   rG   )r   rX   r   s     r   check_statuszADeveloperDiscovery.refresh_developer_status.<locals>.check_status   sv    wwx J.3776?i3O /H
66s6{CKPF(.HICM"*,,.":":"<CJr   
   r\   N)r   rC   map)r   r   r   rc   updated_developerss   `    r   refresh_developer_statusz+DeveloperDiscovery.refresh_developer_status   sE    	  B/8!%hll<&L!M 0 "! 0 "!s	   9ArV   )FTT)__name__
__module____qualname____doc__r   r   strr,   intr   r   rM   rB   rg   rl   r|   boolr   r    r   r   r   r      s    UDI 4   C  HTN  DT hsm "s "49 "PTUYPZ "H$t* 2-T
 -^ VZ48/*D /*d /*-1/*=A$Z/*b"4: "$t* "r   r   )r>   r   	threadingr   r   typingr   r   r   rA   loggingconcurrent.futuresr   r	   psutil	getLoggerr   r#   r   r   r   r   <module>r      sC       ( ' '   ? 			8	${" {"r   