U
    [Mhy                     @   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getenvZbase_urlapi_url)self r   ./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edgeZoperaZbraver-   c                 3   s   | ]}| kV  qd S r*   r   r,   Zider.   r   r   r0   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,   Zdbr.   r   r   r0   M   s     datagrippgadminmysqldbeaverZnavicatZ	sqlserverZoracledatabasec                 3   s   | ]}| kV  qd S r*   r   )r,   Zprodr.   r   r   r0   Q   s     )wordexcel
powerpointoutlookteamsslackdiscordzoomZnotionZobsidianZpostmanZproductivityc                 3   s   | ]}| kV  qd S r*   r   r,   Zmediar.   r   r   r0   U   s     )spotifyyoutubevlcmedia playernetflixtwitchentertainmentc                 3   s   | ]}| kV  qd S r*   r   )r,   systemr.   r   r   r0   Y   s     )explorerfinderterminalcmd
powershellztask managerlockdwmwinlogonZcsrssZlsassservicesZsvchost
searchhostnotepad.exec                 3   s   | ]}| kV  qd S r*   r   )r,   Zsys_exer.   r   r   r0   Z   s     )r`   r[   ra   rb   rd   re   rZ   c                 3   s   | ]}| kV  qd S r*   r   )r,   devr.   r   r   r0   ^   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   r0   q   s     z<ActivityWatchClient.extract_detailed_info.<locals>.<genexpr>r1   rs    - r   z
Browsing: rw   z ()c                 3   s   | ]}| kV  qd S r*   r   r6   r.   r   r   r0   }   s     )
r7   r8   r9   r:   r;   r<   r=   r>   r?   r@   rt   /   zCoding: z in c                 3   s   | ]}| kV  qd S r*   r   )r,   Zdb_toolr.   r   r   r0      s     rD   ru   zDatabase: Connected to rf   r'   Z64z
Database: rZ   rv   zSystem: c                 3   s   | ]}| kV  qd S r*   r   )r,   Zofficer.   r   r   r0      s     )rJ   rK   rL   rM   zOffice: c                 3   s   | ]}| kV  qd S r*   r   )r,   Zcommr.   r   r   r0      s     )rN   rO   rP   rQ   ZskypezCommunication: c                 3   s   | ]}| kV  qd S r*   r   rR   r.   r   r   r0      s     )rS   rT   rU   rV   rW   zMedia: r$   )rn   ro   extract_url_from_browser_titlesplitstripextract_file_pathrsplitextract_database_inforeplacerr   rp   lenextract_office_document)	r   r)   r(   inforq   
page_titleprojectfilenameZ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\)]+ZhttpZ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googlerT   ZgmailZlinkedintwitterfacebook2   c                 3   s   | ]}| kV  qd S r*   r   )r,   char)r   r   r   r0      s     zEActivityWatchClient.extract_url_from_browser_title.<locals>.<genexpr>)	rz   \:*?"<>|zhttps://www. r'   z.comz([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}c                 3   s   | ]}|   kV  qd S r*   rn   )r,   rJ   )domainr   r   r0      s     )Zdocumentuntitlednewfiler   r2   r3   N)research
IGNORECASEgroup
startswithr   ZschemeZnetlocpathr~   rn   itemsr   ro   r   findall
isinstancetuplejoin)r   r)   Zbrowser_patternspatternmatchrs   Z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'   )r@   rA   r8   r9   r:   .rz   N)	r   r   r   r   groupsr   r~   rn   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      rs   rt   ru   rv   rw   )
application_namer)   rs   rt   ru   rv   rw   categoryr   r   )r   r   rn   r&   r   r   fromisoformatr   rr   r   append)r   r    r!   bucketsZ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_countZ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   rn   r&   r   r   r   r   _is_non_work_activityr   r   rr   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   r6   r.   r   r   r0     s     zAActivityWatchClient.extract_project_from_title.<locals>.<genexpr>)r@   r7   rA   r9   r:   zE^(.+?)\s*-\s*(.+?)\s*-\s*(Cursor|Code|Visual Studio|PyCharm|IntelliJ)r   r{   ZDevelopment)Zproject_name	file_nameZ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   r0     s     r2   r3   r5   r4   rx   r   z
localhost:zlocalhost:(\d+)unknownzWeb Developmentz([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})zWeb Page	filezillaZ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   r0     s     )cpanelpleskhostingz	Hosting: zControl Panelc                 3   s   | ]}| kV  qd S r*   r   rC   r.   r   r   r0     s     )rE   rF   rG   rH   z!([a-zA-Z0-9_-]+)@([a-zA-Z0-9.-]+)zDB: @ZDatabaserf   r'   r   Nz...ZWork)
rn   ro   r   r   r   r   r~   r}   r   r   )r   r)   r(   Zide_patternr   Zsimple_patternr   Z
port_matchZportZ	url_matchZserver_matchZdomain_matchZdb_matchr   )r/   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   Zloadingzplease waiterrorZ404z	not foundzaccess deniedZ	forbiddenZreactrj   ri   ZyarnZwebpackZbabelrT   rW   rS   ZmusicZvideoZmovieZsongrY   ZgameZgamingrX   streamZ	instagramr   r   ZtiktokZsnapchatZwhatsappZtelegramZredditZ	pinterestzlinkedin personalZdatingZshoppingzamazon personalZflipkartZmyntraZnewsZcricketZsportsZ	bollywoodZhindizdubbed moviezlatest movieZtrailerzlock screenlockedZlockappZscreensaverZidlezwindows default lockZlogonzlogin screenZshutdownZrestartz
sleep modeZ	hibernaterB   rA   Zprogrammingr@   r7   r8   r9   r:   r;   r<   r=   r>   r?   rh   r   ZgitlabZ	bitbucketr   ZdocumentationapirI   ZsqlrG   Z
postgresqlZmongodbZredisserverr   r   r   r   Zsshr]   r^   r_   ZbashZubuntuZlinuxZawsZazureZgcpZdockerZ
kubernetesZnginxZapacheZphprk   Z
javascriptZvueZangularZ
typescriptZhtmlZcssZsassZscssZ	bootstrapZtailwindZfigmaZ	photoshopZillustratorZcanvaZdesignZuiZuxr   clientworkbusinessadmin	dashboardr   r   r   ZaiZ
automationZscriptZtoolZutilityZtestingdebugZbugZfixZdeployZbuildcompileZ	localhostz	127.0.0.1rg   ZstagingZ
productionZliveZwaareeZfirsteconomyZgeraZistanaZkikiZleadsZcrmZ
salesforceintegrationZajaxZformZ
validationZemailZmailZinboxZcontactZinquiryZwebsiter   ZdnsZsslZcertificateZbackupZ	migrationupdateZupgradeFc                 3   s   | ]}| kV  qd S r*   r   r+   )	app_lowerr   r   r0   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   r0   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   r0     s     )r   r   r   r   rB   rA   r   rI   r   r   r   r   )r~   r   rn   ro   )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   Z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&   rr   dictr   r   r|   r   r   r   r   intr   r   boolr   r   r   r   r   r   r	      s   $RF',V^ir	   )r   r   r   r   typingr   r   r   r
   Zdotenvr   r   Zurllib.parser   r	   r   r   r   r   <module>   s   