U
    [MhG                     @   s  d dl mZmZmZmZmZmZ d dlmZ d dl	m
Z
mZmZmZ d dlmZmZmZ d dlZd dlZd dlZd dlmZ d dlmZ d dlZe ZeeZG dd	 d	eZeeed
ddZ d-eeedddZ!d.eeee"dddZ#e$dedddedeefeeeedddZ%e&deedddZ'e&dddeefeee ee ed d!d"Z(e&d#ddeefee ee ed$d%d&Z)e&d'd(d) Z*e
ed*d+d,Z+dS )/    )	APIRouterDependsHTTPExceptionstatusHeaderRequest)Session)ListDictOptionalAny)datetimetimezone	timedeltaN)	BaseModel)get_dbc                   @   s.   e Zd ZU eed< eed< eeef ed< dS )ActivityWatchEvent	timestampdurationdataN)__name__
__module____qualname__str__annotations__floatr
   r    r   r   ./stateless_webhook.pyr      s   
r   )developer_idprovided_tokenreturnc                 C   sn   t dd}|  d| dt j }t|  }ddl	}t
|dd }|| d}||kS )z;Validate token without database lookup - uses master secretZMASTER_SECRETz'your-master-secret-for-token-generation:r   N0   =)osgetenvr   nowZyearhashlibZsha256encodeZ	hexdigestbase64bytesfromhexZurlsafe_b64encodedecoderstrip)r   r   Zmaster_secretZtoken_inputZ
token_hashr)   Ztoken_bytesZexpected_tokenr   r   r   validate_stateless_token   s    r.    )app_namewindow_titler    c                    s   | sdS |    |r|  nd}t fdddD r:dS t fdddD rTd	S t fd
ddD rndS t fdddD rdS t fdddD rdS t fdddD rdS dS )z5Categorize application based on name and window titleotherr/   c                 3   s   | ]}| kV  qd S Nr   .0browserapp_name_lowerr   r   	<genexpr>,   s     z)categorize_application.<locals>.<genexpr>)chromefirefoxsafariedgeZoperaZbraver6   c                 3   s   | ]}| kV  qd S r3   r   r5   Zider7   r   r   r9   0   s     )vscodezvisual studiopycharmintellijZsublimeZatomZvimZemacsz	notepad++cursorcodedevelopmentc                 3   s   | ]}| kV  qd S r3   r   )r5   dbr7   r   r   r9   4   s     )ZdatagripZpgadminZmysqlZdbeaverZnavicatZ	sqlserverZoracledatabasec                 3   s   | ]}| kV  qd S r3   r   )r5   Zprodr7   r   r   r9   8   s     )ZwordZexcelZ
powerpointZoutlookZteamsZslackZdiscordZzoomZnotionZobsidianZpostmanproductivityc                 3   s   | ]}| kV  qd S r3   r   )r5   Zmediar7   r   r   r9   <   s     )ZspotifyZyoutubeZvlczmedia playerZnetflixZtwitchentertainmentc                 3   s   | ]}| kV  qd S r3   r   )r5   systemr7   r   r   r9   @   s     )	ZexplorerfinderZterminalcmdZ
powershellztask managerlockZdwmZwinlogonrI   )lowerany)r0   r1   window_title_lowerr   r7   r   categorize_application#   s"    rP   )r1   r0   urlr    c              	      s   ddd|dd}| s|s|S |r(|  nd | r8|   nd}t fdddD rd| kr| d}t|d	kr|d
  }|d  }||dd|kr| d| n|d| d| d |S nt fdddD r|rzd
dlm} ||}	|	j	dddksdkrH|d|	j
p,d dd|  d |W S dddd d!d"g}
tfd#d|
D r|d$d%|  d |W S W n tk
r   Y nX d| kr| dd
  }||d&d'| d |S |r|	d(dnd)}||d| r| d*|  n|d |S )+z@Extract project information from window title, app name, and URLNWork)project_nameproject_type	file_pathrQ   detailed_activityr/   c                 3   s   | ]}| kV  qd S r3   r   r>   r7   r   r   r9   V   s     z'extract_project_info.<locals>.<genexpr>)rB   r?   rC   r@   rA   z -    r      ZDevelopment./zCoding: z in )rS   rT   rU   rV   c                 3   s   | ]}| kV  qd S r3   r   r4   r7   r   r   r9   f   s     )r:   r;   r=   r<   )urlparsezwww.Z	localhostz	127.0.0.1z
localhost:Z3000zWeb DevelopmentzLocal Development: )rS   rT   rV   z
github.comzstackoverflow.comzdocs.zapi.z
developer.zconsole.c                 3   s   | ]}| kV  qd S r3   r   )r5   Zwork_domain)domainr   r   r9   x   s     zWeb Researchz
Research: zWeb Browsingz
Browsing: z.exeUnknownz: )rM   rN   splitlenstripupdateZurllib.parser[   ZnetlocreplaceZport	Exception)r1   r0   rQ   project_inforO   partsfilenameprojectr[   ZparsedZwork_domainsZ
page_titleZclean_app_namer   )r8   r\   r   extract_project_infoE   sz    


rh   z/activitywatch/webhook.zDeveloper-ID)alias)requestr   authorizationrE   c                    s  | dstddd|dd }t||sJtd|  tdddtd	|  z|  I d
H }d}| D ]\}}t	|t
rx|D ]t}	t	|	tsq|	d}
|	dd}|	di }|
r|dk rqzt|
dd}|dp|dd}|dd}|dd
}|r$|dkr(W qt||}t|||}ddlm} |||j|k|j|k|j|k|j|k }|rW q||||||d ||||d |d |d d}|| |d7 }W q tk
r } ztd|  W Y qW 5 d
}~X Y qX qqx|  td| d |  d!d"| d#|tt j!" d$W S  tj#k
rn   td%d&dY nR tk
r } z2|$  td'|  td(d)t%| dW 5 d
}~X Y nX d
S )*zCReceive ActivityWatch data via webhook - stateless token validationzBearer i  zInvalid authorization header)Zstatus_codeZdetail rX   zInvalid token for developer zInvalid developer or tokenz$Received ActivityWatch webhook from Nr   r   r   r      Z+00:00ZappZapplicationr]   titler/   rQ   ActivityRecordrU   rS   rT   rV   )r   application_namer1   rQ   rU   categoryr   r   rS   rT   rV   zError processing event: zSuccessfully processed z activities from successz
Processed z activities)r   messager   r   i  zInvalid JSON dataz(Error processing ActivityWatch webhook: i  zProcessing error: )&
startswithr   r^   r.   loggerZwarninginfojsonitems
isinstancelistdictgetr   fromisoformatrb   rP   rh   modelsrr   queryfilterr   r   rs   r   firstaddrc   errorZcommitr&   r   utc	isoformatZJSONDecodeErrorZrollbackr   )rj   r   rk   rE   tokenZwebhook_dataZprocessed_activitiesZbucket_nameZbucket_dataZeventZtimestamp_strr   r   r   r0   r1   rQ   rt   rd   rr   existingZactivity_recorder   r   r   'receive_activitywatch_webhook_stateless   s    










r   z/activitywatch/validate-token)r   r   c                    s"   t | |}| |ttj dS )z1Test endpoint to validate a token (for debugging))r   Ztoken_validr   )r.   r   r&   r   r   r   )r   r   Zis_validr   r   r   validate_token_endpoint	  s
    
r   z//activitywatch/developer-summary/{developer_id})r   
start_dateend_daterE   c           	         s   |rt |dd}nt tjjddddd}|rJt |dd}nt tj}ddlm} ||	|j
| k|j|k|j|k }|s| | | dddi i ddS t|}| | | d|dS )	zFGet activity summary for a developer (no user authentication required)rn   ro   r   ZhourZminutesecondZmicrosecondrq   startend)total_activities
total_time
categoriesprojects)r   
date_rangesummary)r   r   rb   r&   r   r   r   rr   r   r   r   r   allr   process_developer_activities)	r   r   r   rE   r   r   rr   
activitiesr   r   r   r   get_developer_summary_stateless  s,    

r   z/activitywatch/team-summary)r   r   rE   c                    s  | rt | dd}nt tjjddddd}|rJt |dd}nt tj}ddlm} ddlm	} |
||j|jd|j|k|j|k }g }d}	d}
|D ]\}|sq|
||j|k|j|k|j|k }t|}|	|d 7 }	|
|d	 7 }
|d
d }d
|kr@|d
dd }d| }||||d q| | d|t||	|	d dd|
ddS )z;Get team-wide summary without requiring user authenticationrn   ro   r   r   )distinctrq   Nr   r   _rl   )r   namer   r     .2fh)r   total_time_formattedr   )r   	team_dataZtotal_developersZteam_totals)r   r   rb   r&   r   r   Z
sqlalchemyr   r   rr   r   r   r   Zisnotr   r   r   rp   r^   joinappendr   r_   )r   r   rE   r   r   r   rr   Zdeveloper_idsr   Ztotal_team_timeZtotal_team_activitiesZdev_idr   r   Zdeveloper_nameZ
name_partsr   r   r   get_team_summary_statelessC  sX    	




r   z/healthc                      s   ddt tj ddS )zHealth check endpointZhealthyZ	statelessz:ActivityWatch webhook endpoint is running (stateless mode))r   moder   rv   )r   r&   r   r   r   r   r   r   r   health_check  s
    r   )r   r    c              	   C   s  | sddi i dddS t dd | D }i }i }d}| D ]}|jpDd}|jpNd}|j}||krlddd||< || d  d	7  < || d
  |7  < ||krdd|jpdd||< || d  d	7  < || d
  |7  < dddddddd}	|	|d}
|||
 7 }q8|dkr|| d nd}| D ]}|d
 d dd|d< q*| D ]}|d
 d dd|d< qRt| ||d dd||d ddt|d	||dS )z*Process activities into summary statisticsr   )r   r   r   r   working_hoursproductivity_percentagec                 s   s   | ]}|j V  qd S r3   )r   )r5   activityr   r   r   r9     s     z/process_developer_activities.<locals>.<genexpr>r2   r]   )countr   r   rX   r   rR   )r   r   typeg      ?g333333?g      ?g?g        )rD   rF   rG   r6   r2   rI   rH   d   r   r   r   Zduration_formatted)r   r   r   r   Zworking_hours_formattedr   r   r   )	sumrt   rS   r   rT   r   valuesr_   round)r   r   r   r   r   r   rt   rg   r   Zcategory_weightsZweightr   Zcategory_dataZproject_datar   r   r   r     s`    	


r   )r/   )N),Zfastapir   r   r   r   r   r   Zsqlalchemy.ormr   typingr	   r
   r   r   r   r   r   rz   r'   r$   Zpydanticr   rF   r   ZloggingZrouterZ	getLoggerr   rx   r   r   boolr.   rP   r~   rh   Zpostr   r   r   r   r   r   r   r   r   r   r   <module>   sf    
"R
q+F
	