U
    %hy                     @   st   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	m
Z
 d dlZd dlmZ e
  G dd dZdS )    N)datetime	timedelta)ListDictOptional)load_dotenv)urlparsec                   @   s  e Zd Zdd Zee dddZeeeee dddZ	d'eeed
ddZ
eeedddZeee dddZeee dddZeee dddZeee dddZeeee dddZd(eeeee dddZeeedd d!Zeeedd"d#Zedd$d%Zd&S ))ActivityWatchClientc                 C   s    t dd| _| j d| _d S )NZACTIVITYWATCH_HOSTzhttp://localhost:5600z/api/0)osgetenvbase_urlapi_url)self r   :/var/www/html/timesheet/backend/my_activitywatch_client.py__init__   s    zActivityWatchClient.__init__)returnc                 C   s   z(t j| j ddd}|  | W S  t jk
r } ztd|  z0t j| j ddd}|  | W  W Y HS  t jk
r } z"td|  i  W Y 
 W Y S d}~X Y nX W 5 d}~X Y nX dS )z,Get all available buckets from ActivityWatch	/buckets/T)allow_redirectszError fetching buckets: /bucketsz!Error with alternative endpoint: N)requestsgetr   raise_for_statusjsonRequestExceptionprint)r   responseee2r   r   r   get_buckets   s    
zActivityWatchClient.get_buckets)	bucket_idstartendr   c           
      C   s  zP| d}| d}||dd}tj| j d| d|dd}|  | W S  tjk
r } ztd| d	|  z8tj| j d| d
|dd}|  | W  W Y JS  tjk
 r }	 z"td|	  g  W Y 
 W Y S d}	~	X Y nX W 5 d}~X Y nX dS )z!Get events from a specific bucketz%Y-%m-%dT%H:%M:%Si  )r!   r"   limitr   z/eventsT)paramsr   z"Error fetching events from bucket : z/events/z(Error with alternative events endpoint: N)strftimer   r   r   r   r   r   r   )
r   r    r!   r"   Z	start_strZend_strr$   r   r   r   r   r   r   
get_events#   s&    


zActivityWatchClient.get_events )app_namewindow_titler   c                    s   |   |  }t fdddD r*dS t fdddD rDdS t fddd	D r^d
S t fdddD rxdS t fdddD rdS t fdddD sȈ drt fdddD rdS t fdddD rdS dS )z5Categorize application based on name and window titlec                 3   s   | ]}| kV  qd S Nr   .0browserapp_name_lowerr   r   	<genexpr>E   s     z=ActivityWatchClient.categorize_application.<locals>.<genexpr>chromefirefoxsafariedgeoperabraver.   c                 3   s   | ]}| kV  qd S r+   r   r-   ider/   r   r   r1   I   s     )vscodevisual studiopycharmintellijsublimeatomvimemacs	notepad++cursorcodedevelopmentc                 3   s   | ]}| kV  qd S r+   r   r-   dbr/   r   r   r1   M   s     datagrippgadminmysqldbeavernavicat	sqlserveroracledatabasec                 3   s   | ]}| kV  qd S r+   r   )r-   prodr/   r   r   r1   Q   s     )wordexcel
powerpointoutlookteamsslackdiscordzoomnotionobsidianpostmanproductivityc                 3   s   | ]}| kV  qd S r+   r   r-   mediar/   r   r   r1   U   s     )spotifyyoutubevlcmedia playernetflixtwitchentertainmentc                 3   s   | ]}| kV  qd S r+   r   )r-   systemr/   r   r   r1   Y   s     )explorerfinderterminalcmd
powershellztask managerlockdwmwinlogonZcsrssZlsassZservicesZsvchost
searchhostnotepad.exec                 3   s   | ]}| kV  qd S r+   r   )r-   Zsys_exer/   r   r   r1   Z   s     )rn   ri   ro   rp   rq   rr   rh   c                 3   s   | ]}| kV  qd S r+   r   )r-   devr/   r   r   r1   ^   s     )gitnpmnodepythonjavaZdotnetother)loweranyendswith)r   r)   r*   window_title_lowerr   r/   r   categorize_application?   s*    z*ActivityWatchClient.categorize_application)r*   r)   r   c           	         s  dddddd}|   |  }t fdddD r| ||d< d|kr|dd  }d	| |d
< |d r|d
  d|d  d7  < nd	| |d
< n*t fdddD r2| ||d< |d r d|d kr|d dd\}}d| d| |d
< nd|d  |d
< nd| |d
< nt fdddD r| ||d< |d rvd|d  |d
< n(|dddd}d| d| |d
< n,| 	||dks 
dr,||d< |
dr|ddn|}|r||krt| dkrd| d| |d
< nd| |d
< nt fddd D r| ||d< |d rpd!|d  |d
< nd!| |d
< nNt fd"dd#D rd$| |d
< n&t fd%dd&D rd'| |d
< |d
 s| d(| |d
< |S ))z;Extract detailed information from window title and app nameN)url	file_pathdatabase_connectionspecific_processdetailed_activityc                 3   s   | ]}| kV  qd S r+   r   r,   r/   r   r   r1   q   s     z<ActivityWatchClient.extract_detailed_info.<locals>.<genexpr>r2   r    - r   z
Browsing: r   z ()c                 3   s   | ]}| kV  qd S r+   r   r9   r/   r   r   r1   }   s     )
r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   r   /   zCoding: z in c                 3   s   | ]}| kV  qd S r+   r   )r-   Zdb_toolr/   r   r   r1      s     rI   r   zDatabase: Connected to rs   r(   Z64z
Database: rh   r   zSystem: c                 3   s   | ]}| kV  qd S r+   r   )r-   Zofficer/   r   r   r1      s     )rS   rT   rU   rV   zOffice: c                 3   s   | ]}| kV  qd S r+   r   )r-   Zcommr/   r   r   r1      s     )rW   rX   rY   rZ   ZskypezCommunication: c                 3   s   | ]}| kV  qd S r+   r   r_   r/   r   r   r1      s     )ra   rb   rc   rd   re   zMedia: r%   )r{   r|   extract_url_from_browser_titlesplitstripextract_file_pathrsplitextract_database_inforeplacer   r}   lenextract_office_document)	r   r*   r)   infor~   
page_titleprojectfilenameclean_app_namer   r/   r   extract_detailed_infoc   sd    

"

z)ActivityWatchClient.extract_detailed_info)r*   r   c                    s  dddg}|D ]}t ||t j}|rd| ks@d| kr| }|dsZd| }z&t|}|j d|j |j W   S    | Y   S X q|d	 d	d
ddddddddd
}
 }| D ]\}	}|	|kr|    S qtdk rtfdddD sd
 dd d  S qdg}
|
D ]d}t ||}|D ]L}t|trhd| n| t fdddD sLd      S qLq8dS ) z1Enhanced URL extraction from browser window titlezN^(.+?)\s*-\s*(Google Chrome|Mozilla Firefox|Microsoft Edge|Safari|Opera|Brave)zhttps?://[^\s\)]+zwww\.[^\s\)]+httpwwwzhttps://z://r   zhttps://claude.aizhttps://chat.openai.comzhttps://github.comzhttps://stackoverflow.comzhttps://google.comzhttps://youtube.comzhttps://gmail.comzhttps://linkedin.comzhttps://twitter.comzhttps://facebook.com)
claudechatgptgithubstackoverflowgooglerb   ZgmailZlinkedintwitterfacebook2   c                 3   s   | ]}| kV  qd S r+   r   )r-   char)r   r   r   r1      s     zEActivityWatchClient.extract_url_from_browser_title.<locals>.<genexpr>)	r   \:*?"<>|zhttps://www. r(   z.comz([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}c                 3   s   | ]}|   kV  qd S r+   r{   )r-   rS   )domainr   r   r1      s     )Zdocumentuntitlednewfiler   r3   r4   N)research
IGNORECASEgroup
startswithr   schemenetlocpathr   r{   itemsr   r|   r   findall
isinstancetuplejoin)r   r*   Zbrowser_patternspatternmatchr   parsedZtitle_to_urlZ
page_lowerkeyZdomain_patternsmatchesr   )r   r   r   r      sZ    

"z2ActivityWatchClient.extract_url_from_browser_titlec                 C   s   ddddddg}|D ]}t ||t j}|rt| dkr|d }t| dkrh|d nd	}| d
kr|  S d|krt|ddkr| d|   S |  S q|d   S qdS )z'Extract file path from IDE window titlez&([A-Za-z]:\\[^|<>:*?"]+\.[a-zA-Z0-9]+)z(/[^|<>:*?"]+\.[a-zA-Z0-9]+)zF^([^-]+\.[a-zA-Z0-9]+)\s*-\s*([^-]+)\s*-\s*(Cursor|Code|Visual Studio)zI^([^-]+\.[a-zA-Z0-9]+)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)z<^([^-]+)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)$z^([^\\/:*?"<>|]+\.[a-zA-Z0-9]+)   r   r(   )rD   rE   r<   r=   r>   .r   N)	r   r   r   r   groupsr   r   r{   r   )r   r*   patternsr   r   Z
first_partZsecond_partr   r   r   r      s(    "
z%ActivityWatchClient.extract_file_pathc                 C   s4   dddg}|D ] }t ||}|r|   S qdS )z@Extract database connection info from database tool window titlez
@([^@\s]+)z([a-zA-Z0-9_]+@[a-zA-Z0-9.-]+)z&([a-zA-Z0-9_]+)\s*-\s*([a-zA-Z0-9.-]+)N)r   r   r   )r   r*   Zdb_patternsr   r   r   r   r   r   "  s    z)ActivityWatchClient.extract_database_infoc                 C   sJ   |}ddddddg}|D ]}||kr| |d} q6q| rF| S dS )	z3Extract document name from Office application titlez - Wordz - Excelz - PowerPointz - Microsoft Wordz - Microsoft Excelz - Microsoft PowerPointr(   N)r   r   )r   r*   titleZoffice_suffixessuffixr   r   r   r   2  s    z+ActivityWatchClient.extract_office_document)r!   r"   r   c                 C   s   |   }g }| D ]\}}d| kr*q| |||}|D ]}|di }	|dd}
t|dddd}|	d	|	d
d}|	dd}|
dk rq<| ||}| 	||}|
|||d |d |d |d |d ||
|d
 q<q|S )z.Get processed activity data from ActivityWatchafkdatadurationr   	timestampr(   Z+00:00appapplicationUnknownr      r   r   r   r   r   )
application_namer*   r   r   r   r   r   categoryr   r   )r   r   r{   r'   r   r   fromisoformatr   r   r   append)r   r!   r"   bucketsactivity_databucket_namebucket_infoeventseventr   r   r   r)   r*   r   Zdetailed_infor   r   r   get_activity_data?  s:    z%ActivityWatchClient.get_activity_data   )r!   r"   r#   r   c              
   C   s@  zt d| d|  |  }g }| D ]\}}d| krBq,t d|  | |||}|D ]}	|	di }
|	dd}t|	dd	d
d}|
d|
dd}|
dd	}|dk rqb| 	||rqb|
|||||d qbq,t dt| d i }|D ]}	|	d }|	d }|	d }|	d }| d| }||krj||| ||dd| |||d||< || d  |7  < || d  d7  < ||| d kr||| d< qt| dd dd}t d t|t| d! |d"| W S  tk
r: } z*t d#|  dd"l}|  g  W Y S d"}~X Y nX d"S )$zVGet top window titles by duration from ActivityWatch - Direct API call for better datau!   🔍 Fetching window titles from z to r   u!   📊 Getting events from bucket: r   r   r   r   r(   r   r   r   r   r   r   r   )r*   r   r   r   Zbucketu   📈 Found z total eventsr*   r   r   )r*   r   r   total_durationactivity_countproject_info	last_seenr   r   r   r   c                 S   s   | d S )Nr   r   )xr   r   r   <lambda>      z;ActivityWatchClient.get_top_window_titles.<locals>.<lambda>T)r   reverseu   🏆 Returning top z window titlesNu%   ❌ Error getting top window titles: )r   r   r   r{   r'   r   r   r   r   _is_non_work_activityr   r   r   extract_project_from_titlesortedvaluesmin	Exception	traceback	print_exc)r   r!   r"   r#   r   Z
all_eventsr   r   r   r   r   r   r   r)   r*   Ztitle_statsr   r   Zsorted_titlesr   r   r   r   r   get_top_window_titlesk  sv    




z)ActivityWatchClient.get_top_window_titlesc                    s*  |   t fdddD rd}t|tj}|rV|d |d ddS d	}t|tj}|r|d d
ddS npt fdddD r&dkrdd  }dkrtd}|r|dnd}d| |ddS td}	|	r|	d|ddS |dddS nd ks:d krftd}
|
rd|
d dddS ntfdddD rtd}|rd|d dddS nNt fddd D rtd!}|rd"|d d#|d d$d$dS |d%d&t	d'kr d(d' d) nd*dS )+z:Extract project information from window title and app namec                 3   s   | ]}| kV  qd S r+   r   r9   r/   r   r   r1     s     zAActivityWatchClient.extract_project_from_title.<locals>.<genexpr>)rD   r;   rE   r=   r>   zE^(.+?)\s*-\s*(.+?)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)r   r   Development)project_name	file_nameproject_typez:^(.+?)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)$zProject Rootc                 3   s   | ]}| kV  qd S r+   r   r,   r/   r   r   r1     s     r3   r4   r6   r5   r   r   z
localhost:zlocalhost:(\d+)unknownzWeb Developmentz([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})zWeb Page	filezillaftpz1([a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|\d+\.\d+\.\d+\.\d+)zFTP: zServer ConnectionzServer Managementc                 3   s   | ]}|   kV  qd S r+   r   )r-   panel)r*   r   r   r1     s     )cpanelpleskhostingz	Hosting: zControl Panelc                 3   s   | ]}| kV  qd S r+   r   rG   r/   r   r   r1     s     )rJ   rK   rL   rM   z!([a-zA-Z0-9_-]+)@([a-zA-Z0-9.-]+)zDB: @ZDatabasers   r(   r   Nz...Work)
r{   r|   r   r   r   r   r   r   r   r   )r   r*   r)   Zide_patternr   Zsimple_patternr   Z
port_matchportZ	url_matchZserver_matchZdomain_matchZdb_matchr   )r0   r*   r   r     sz    


 z.ActivityWatchClient.extract_project_from_titlec              |      s"  |s|sdS |r@|  dks@|dks@|  dks@t|  dk rDdS |rP| nd|r`| nd ddddd	d
ddddddddddg}dddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5d6d7g#}d8d9d:d;d<d=d>d?d@dAdBdCg}|D ]}|ks| kr dS q|D ] }|ks,| kr dS q|D ] }|ksR| kr: dS q:dDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrdsddtduddddddvdwdxdydzd{d|d}d~dddddddddddddddddddddd
dddddddddddddddddddddddddddddddddddddg|}|D ] }|kst| kr\ dS q\t fdddD rdksdksdksdksdksdksd`ksdakstfdddD rdS tfdddD sdS dS )z@Check if activity is non-work related and should be filtered outTr(   )r   r   r(      znew tabz
blank pager   loadingzplease waiterrorZ404z	not foundzaccess deniedZ	forbiddenZreactrw   rv   ZyarnZwebpackZbabelrb   re   ra   ZmusicZvideoZmovieZsongrg   ZgameZgamingrf   streamZ	instagramr   r   ZtiktokZsnapchatZwhatsappZtelegramZredditZ	pinterestzlinkedin personalZdatingZshoppingzamazon personalZflipkartZmyntranewsZcricketZsportsZ	bollywoodZhindizdubbed moviezlatest movieZtrailerzlock screenlockedZlockappZscreensaveridlezwindows default lockZlogonzlogin screenshutdownrestartz
sleep modeZ	hibernaterF   rE   ZprogrammingrD   r;   r<   r=   r>   r?   r@   rA   rB   rC   ru   r   ZgitlabZ	bitbucketr   documentationapirQ   sqlrL   
postgresqlmongodbredisserverr   r   r   r   sshrk   rl   rm   ZbashZubuntulinuxZawsazuregcpZdockerZ
kubernetesZnginxZapacheZphprx   Z
javascriptZvueZangularZ
typescripthtmlcssZsassZscssZ	bootstrapZtailwindZfigmaZ	photoshopZillustratorZcanvaZdesignZuiZuxr   clientworkbusinessadmin	dashboardr   r   r   ZaiZ
automationscriptZtoolZutilityZtestingdebugZbugZfixZdeploybuildcompile	localhostz	127.0.0.1rt   Zstaging
productionZliveZwaareeZfirsteconomyZgeraZistanaZkikiZleadsZcrmZ
salesforceintegrationZajaxform
validationemailmailZinboxcontactZinquiryZwebsiter   ZdnssslcertificateZbackupZ	migrationupdateupgradeFc                 3   s   | ]}| kV  qd S r+   r   r,   )	app_lowerr   r   r1   q  s     z<ActivityWatchClient._is_non_work_activity.<locals>.<genexpr>r   c                 3   s   | ]}| kV  qd S r+   r   )r-   r   title_lowerr   r   r1   w  s     )z
github.comzstackoverflow.comzdocs.zapi.z
developer.zconsole.zaws.zazure.zcloud.zfirsteconomy.comz
waaree.comz	claude.aiz
openai.comc                 3   s   | ]}| kV  qd S r+   r   )r-   Z	work_wordr+  r   r   r1     s     )r   r  r  r  rF   rE   r	  rQ   r  r  r  r   )r   r   r{   r|   )r   r*   r)   Zgeneric_keywordsZentertainment_keywordsZsystem_keywordskeywordZwork_keywordsr   )r*  r,  r   r     s   
                                                   

                                                                                                          
	z)ActivityWatchClient._is_non_work_activityc                 C   s6   z"t j| j ddd}|jdkW S    Y dS X dS )z'Test connection to ActivityWatch serverr   r   )timeout   FN)r   r   r   status_code)r   r   r   r   r   test_connection  s
    z#ActivityWatchClient.test_connectionN)r(   )r   )__name__
__module____qualname__r   r   r   r   strr   r'   r   dictr   r   r   r   r   r   r   intr   r   boolr   r1  r   r   r   r   r	      s   $RF',V^ir	   )r   r   r   r   typingr   r   r   r
   dotenvr   r   urllib.parser   r	   r   r   r   r   <module>   s   