o
    Vj                     @   s   d Z ddlZddlZddlZddlZddlZddlZddlZdZ	dZ
dZdZdZdZd	d
 ZG dd dZdd Zdd Zdd ZedkrJe  dS dS )uC  Otto OneDrive-Sync — spiegelt einen lokalen Antrags-Workspace in den
OneDrive-Ordner Plappi/. Laeuft als User 'nk' (liest /home/nk Workspace),
holt den Graph-Token per `sudo -u agent _od_token.py`.

Nur echte Doku wird gesynct (.md/.docx/.xlsx/.pdf); Scratch (_*, *.png, *.py,
Dotfiles, __pycache__) wird uebersprungen. Aenderungs-Erkennung via sha256-
Manifest → nur geaenderte/neue Dateien werden hochgeladen (idempotent).

Usage:
  onedrive-sync.py                 # default: plappi-Workspace
  onedrive-sync.py <local_dir>     # anderer Workspace (in Plappi/ gespiegelt)
    NzBb!XAhltkZhfUCTfxe1WwksbeUH1YxptIVGoT43oPMC_ECbiaw4ncFDTrhiHvflGezt"01LU3Y225F6DGKDHF2EVA2462D2QZLCRUTz*/home/nk/hobo-godmode/otto/projekte/plappiz.onedrive-sync-manifest.json)z.mdz.docxz.xlsxz.pdfz.pptxz.csva  
import json,time,urllib.request,urllib.parse
c=json.load(open("/home/agent/etc/msal-token-cache.json"))
for v in c.get("AccessToken",{}).values():
    if int(v.get("expires_on",0))>time.time()+120:
        print(v["secret"]);raise SystemExit
rt=next(iter(c["RefreshToken"].values()))
t=rt["home_account_id"].split(".")[1]
s=next(iter(c["AccessToken"].values()))["target"]
d=urllib.parse.urlencode({"client_id":rt["client_id"],"grant_type":"refresh_token","refresh_token":rt["secret"],"scope":s}).encode()
r=urllib.request.Request(f"https://login.microsoftonline.com/{t}/oauth2/v2.0/token",data=d,method="POST",headers={"Content-Type":"application/x-www-form-urlencoded"})
print(json.loads(urllib.request.urlopen(r).read())["access_token"])
c                  C   sH   t jdddddtgddd} | j }|s"td| j pd	  |S )
Nsudoz-uagentz/home/agent/venv/bin/python3z-cT)capture_outputtextzToken-Fehler: leer)
subprocessrun_TOKEN_CODEstdoutstripsysexitstderr)outtok r   //home/nk/hobo-godmode/otto/bin/onedrive-sync.py	get_token&   s   
r   c                   @   s6   e Zd Zdd ZdddZdd Zdd	 Zd
d ZdS )Graphc                 C   s
   || _ d S N)r   )selfr   r   r   r   __init__0      
 zGraph.__init__Nc                 C   sF   dd| j  i}|r||d< tjj||||d}ttj| S )NAuthorizationzBearer zContent-Type)datamethodheaders)r   urllibrequestRequestjsonloadsurlopenread)r   r   urlr   ctypehreqr   r   r   _req1   s   z
Graph._reqc                 C   sD   dt  d| d}| d|dg D ]}|d |kr|  S qd S )N(https://graph.microsoft.com/v1.0/drives//items/z)/children?$select=id,name,folder&$top=400GETvaluename)DRIVEr)   get)r   	parent_idr.   r%   itr   r   r   child_by_name6   s   zGraph.child_by_namec                 C   s^   |  ||}|r|dr|d S dt d| d}t|i dd }| d||d	d S )
Nfolderidr*   r+   z	/childrenfail)r.   r4   z!@microsoft.graph.conflictBehaviorPOSTzapplication/json)r3   r0   r/   r!   dumpsencoder)   )r   r1   r.   exr%   bodyr   r   r   ensure_folder=   s   zGraph.ensure_folderc                 C   sh   t |d}| }W d    n1 sw   Y  dt d| dtj| d}| d||ddS )	Nrbr*   r+   z:/z	:/contentPUTzapplication/octet-streamsize)openr$   r/   r   parsequoter)   r0   )r   r1   localr.   fcontentr%   r   r   r   put_fileE   s   

zGraph.put_file)NN)__name__
__module____qualname__r   r)   r3   r<   rF   r   r   r   r   r   /   s    
r   c                 C   s&   |  ds
|  drdS |  tS )N_.F)
startswithlowerendswithKEEP_EXT)fnr   r   r   wantL   s   rQ   c                    sb   t  }t| d t fdddD ]}|| qW d    | S 1 s(w   Y  | S )Nr=   c                      s
     dS )Ni   )r$   r   rD   r   r   <lambda>T   r   zsha.<locals>.<lambda>    )hashlibsha256r@   iterupdate	hexdigest)pathr'   br   rR   r   shaQ   s   
r\   c                     s  t tjdkrtjtjd nt} tj| s td|   t	t
 tj| t}i }tj|rIz	tt|}W n tyH   i }Y nw dti  fdddd l}g dg }}}t| D ]\}}}	dd |D |d d < tj|| }
|
d	krdn|
}
t|	D ]}t|sqtj||}|
s|n|
 d
| }t|}|||kr|d7 }qd }tdD ]f}z|
||}W  nX tjjy } z*|jdv r|dk r| d|d   W Y d }~q|!|d|j f W Y d }~ n%d }~w ty } z|!|t"|d d f W Y d }~ nd }~ww |d ur/|||< |!||f qqftj#|t|ddd |D ]\}}t$d| d| d q>|D ]\}}t$d| d| d qQt$dt | d| dt | d t|r~d d S d d S )N   zkein Verzeichnis:  c                    s@   |  v r |  S t j| }|t j| }| | < |S r   )osrZ   dirnamer<   basename)reldirparentfidfolder_cache	folder_idgr   r   rg   d   s   zmain.<locals>.folder_idr   c                 S   s"   g | ]}| d s|dkr|qS ))rJ   rK   __pycache__)rL   ).0dr   r   r   
<listcomp>o   s   " zmain.<locals>.<listcomp>rK   /   )i  i  i  i  i  i     zHTTP <   w)indentzOK    Plappi/z  (zb)zSKIP  Plappi/u!    — evtl. gerade offen/gesperrt)z
=== Sync fertig: z hochgeladen, z unveraendert, z uebersprungen ===)%lenr   argvr_   rZ   abspathDEFAULT_LOCALisdirr   r   r   joinMANIFEST_NAMEexistsr!   loadr@   	ExceptionPLAPPI_ROOT_IDtimewalkrelpathsortedrQ   r\   r0   rangerF   r   error	HTTPErrorcodesleepappendstrdumpprint)rC   mpathmanifest_tuploadedskippedfailedrootdirsfilesrb   rP   lpr   digestszattempterpwhyr   re   r   mainX   sj   $
(
$r   __main__)__doc__r_   r   r!   rU   r   urllib.requestr   urllib.parser/   r}   rv   ry   rO   r
   r   r   rQ   r\   r   rG   r   r   r   r   <module>   s    8	;
