Premier commit
This commit is contained in:
commit
3062472c97
5 changed files with 816 additions and 0 deletions
290
main.py
Normal file
290
main.py
Normal file
|
@ -0,0 +1,290 @@
|
|||
'''
|
||||
|
||||
|
||||
|
||||
Pierre Cadart
|
||||
Script pour NAS sous Linux
|
||||
|
||||
Utilise un accès en FTP
|
||||
|
||||
|
||||
Organisation du programme (modules) finale:
|
||||
|
||||
|
||||
|----------| |-------------|
|
||||
| | | [piexel.py] |
|
||||
| | | |
|
||||
| accès | | accès |
|
||||
| FTP | | API |
|
||||
| | | |
|
||||
|----------| |-------------|
|
||||
\ /
|
||||
|--------------|
|
||||
| |
|
||||
| arborescence |
|
||||
| |
|
||||
|--------------|
|
||||
|
|
||||
| <-- échange par liste d'actions ([actions.py]) sur des files ([file.py])
|
||||
|
|
||||
|------------| |------------| |------------|
|
||||
| | | | | |
|
||||
| sauvegarde |----| code |-->| logs |
|
||||
| | | de màj | | |
|
||||
|------------| | | | |
|
||||
|------------| |------------|
|
||||
^ /
|
||||
| /
|
||||
|------------|L |------------|
|
||||
| [main.py] | | |
|
||||
| main |<--| config |
|
||||
| | | |
|
||||
|------------| |------------|
|
||||
|
|
||||
|
|
||||
|------------|
|
||||
| |
|
||||
| accès |
|
||||
| manuel |
|
||||
| |
|
||||
|------------|
|
||||
|
||||
|
||||
|
||||
|
||||
après avoir listé les fichiers avec les bonnes extensions localement, et les fichiers de la BDD, on effectue:
|
||||
(1) transformation des dossiers en fichier + sous-titres
|
||||
* parcours des 'file' de l'api qui sont des dossiers
|
||||
- dans le cas d'un seul fichier video, on effectue automatiquement l'opération
|
||||
- dans le cas de 0 fichiers videos, c'est soit:
|
||||
- le dossier à changé de nom:
|
||||
- on essaye de trouver son nouveau nom, en comparant les noms filtrés pour ne contenir que des lettres et l'année entre crochet
|
||||
- le dossier a été déplacé:
|
||||
- on peut chercher dans l'arborescence complète si le dossier existe
|
||||
- dans le cas de plusieurs fichiers, on ne fait rien, mais on le met dans les logs, pour que cela soit fait manuellement
|
||||
- lorsque l'on a un dossier local associé:
|
||||
- on ajoute le fichier vidéo
|
||||
- on ajoute les sous-titres à côté si la langue est disponible dans le nom
|
||||
2) fichiers déplacés et/ou renommés
|
||||
* parcours des fichiers dans l'API mais non dans le FTP
|
||||
- cherche un renommage simple, par réduction des noms aux lettres seules et année
|
||||
- sinon, recherche parmis tous les fichiers locaux non référencés les noms proches (même méthode)
|
||||
- les fichiers restants (côté api) sont maintenant 'broken_link'
|
||||
3) fichiers restants localement
|
||||
* parcours des fichiers locaux restant (non dans un sous-dossier),
|
||||
- pour chaque fichier, essaye de trouver le film/la série associé
|
||||
- si déjà disponible, et broken_link, on complète simplement
|
||||
- si non disponible, on ajoute le fichier
|
||||
|
||||
à supprimer:
|
||||
|
||||
exclure: reportages/documentaires
|
||||
|
||||
'''
|
||||
|
||||
import posixpath
|
||||
import re
|
||||
import config
|
||||
import piexel
|
||||
from ftplib import FTP
|
||||
import time
|
||||
import file
|
||||
|
||||
|
||||
def ftpwalk(directory, ftp):
|
||||
"""
|
||||
Parcours en profondeur un dossier du serveur FTP
|
||||
Effectue un parcours préfixe
|
||||
"""
|
||||
to_visit = [directory]
|
||||
while len(to_visit) > 0:
|
||||
current = to_visit.pop(0)
|
||||
ftp.cwd(current)
|
||||
Lfiles = []
|
||||
Ldirs = []
|
||||
for name, prop in ftp.mlsd():
|
||||
if name.startswith('.'):
|
||||
continue
|
||||
if prop['type'] == 'dir':
|
||||
Ldirs.append(name)
|
||||
to_visit.append(current+'/'+name)
|
||||
elif prop['type'] == 'file':
|
||||
Lfiles.append(name)
|
||||
# ne construit pas la liste complète,
|
||||
# mais retourne les résultats intermédiaires
|
||||
yield (current, Ldirs, Lfiles)
|
||||
|
||||
def visit_server(domain, conf, api):
|
||||
# Connection au serveur
|
||||
print('connect to:', conf.get_domain(domain))
|
||||
ftp = FTP(conf.get_domain(domain), user='rez', passwd='rez')
|
||||
ftp.encoding = 'UTF-8'
|
||||
# Initialisation des listes de mises à jour
|
||||
L_missing = [] # fichiers non trouvés sur le serveur FTP
|
||||
L_unreferenced = [] # fichiers non référencés dans l'API
|
||||
L_moved = [] # fichiers déplacés sur le serveur FTP
|
||||
# Lecture à distance des deux BDD
|
||||
for directory in conf.get_movie_dir(domain):
|
||||
# Visite l'arborescence de chaque dossier
|
||||
Lloc = []
|
||||
for path, _, files in ftpwalk(directory, ftp):
|
||||
# Vérifie si le parcours du dossier est autorisé
|
||||
if not any(path.startswith(p) for p in conf.get_excluded_movie_dir(domain)):
|
||||
# Ajoute les fichiers correspondants aux extensions
|
||||
for f in files:
|
||||
if conf.is_valid_file(f):
|
||||
F = file.File(path, f)
|
||||
Lloc.append(F)
|
||||
# Récupère les fichiers de l'api
|
||||
Lapi = []
|
||||
for info in api.get_files(path='ftp://'+conf.get_domain(domain)+directory, like=1):
|
||||
Lapi.append(file.File(info['path'][len('ftp://'+conf.get_domain(domain)):], info['name'], api_id=info['filable_id']))
|
||||
ftp.close()
|
||||
|
||||
# supprime les dossiers de l'api
|
||||
Lapi = [f for f in Lapi if conf.is_valid_file(f.name)]
|
||||
|
||||
# supprime les noms avec un '+'
|
||||
Lloc = [f for f in Lloc if '+' not in f.name]
|
||||
|
||||
# Compare avec la liste de l'api
|
||||
Lmissing = [f for f in Lapi if f not in Lloc] # fichiers non présents localement
|
||||
Lunref = [f for f in Lloc if f not in Lapi] # fichiers non référencés
|
||||
|
||||
# Fichiers déplacés localement
|
||||
Lrelink = [] # liste des références à changer
|
||||
for file1 in Lmissing:
|
||||
for file2 in Lunref:
|
||||
if file1.filename_same(file2):
|
||||
Lrelink.append((file1, file2))
|
||||
for fApi, fLoc in Lrelink:
|
||||
Lmissing.remove(fApi)
|
||||
Lunref.remove(fLoc)
|
||||
print('moved:', Lrelink)
|
||||
|
||||
# Linke les fichiers identiques au même film
|
||||
Llink = []
|
||||
for file1 in Lunref:
|
||||
for file2 in Lapi:
|
||||
if file1.title == file2.title:
|
||||
Llink.append((file1, file2.api_id))
|
||||
print('D add:', file1, file2, file2.api_id)
|
||||
break
|
||||
print('doubles:', sorted(Llink, key=lambda f:str(f)))
|
||||
for f, _ in Llink:
|
||||
Lunref.remove(f)
|
||||
|
||||
# Linke les films par nom si possible
|
||||
APIfilms = api.get_films()
|
||||
API_alltitles = []
|
||||
for f in APIfilms:
|
||||
if f['title']:
|
||||
t = f['title'].replace(' ','').lower()
|
||||
if t not in [e[0] for e in API_alltitles]:
|
||||
API_alltitles.append((t, f['id']))
|
||||
if f['title_vo']:
|
||||
t = f['title_vo'].replace(' ','').lower()
|
||||
if t not in [e[0] for e in API_alltitles]:
|
||||
API_alltitles.append((t, f['id']))
|
||||
API_alltitles = [f for f in API_alltitles if len(f[0])>10]
|
||||
Llink2 = []
|
||||
for film in Lunref:
|
||||
for title, fid in API_alltitles:
|
||||
if title==film.simple_name:
|
||||
Llink2.append((film, fid))
|
||||
break
|
||||
#print(film, ' <-> ', [f for f in APIfilms if f['id']==fid][0]['title'])
|
||||
print('easy ref:', sorted(Llink2, key=lambda f:str(f)))
|
||||
for f, _ in Llink2:
|
||||
Lunref.remove(f)
|
||||
|
||||
print('missing:',Lmissing)
|
||||
print('\n'*3)
|
||||
print('unreferenced:','\n'.join(str(f) for f in Lunref))
|
||||
print('\n'*3)
|
||||
print('unreferenced titles:', '\n'.join([f.title for f in Lunref]))
|
||||
"""
|
||||
# Put les renommages / déplacements
|
||||
i = 0
|
||||
for filmApi, filmLoc in Lrelink:
|
||||
i += 1
|
||||
print('['+str(i)+'/'+str(len(Lrelink))+']'+'relink:', filmApi.title)
|
||||
try:
|
||||
api.debug_print = True
|
||||
api.put_file(id=filmApi.api_id, path='ftp://'+conf.get_domain(domain)+filmLoc.path, name=filmLoc.name)
|
||||
api.debug_print = False
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print('film '+filmApi.title+' not edited')
|
||||
raise Exception('end')
|
||||
|
||||
# Poste les ajouts de doubles
|
||||
i = 0
|
||||
for film, filmID in Llink:
|
||||
i += 1
|
||||
print('['+str(i)+'/'+str(len(Llink))+']'+'link:', film.title)
|
||||
try:
|
||||
api.debug_print = True
|
||||
api.post_file(path='ftp://'+conf.get_domain(domain)+film.path, name=film.name, type='Film', type_id=filmID, **film.additional_info())
|
||||
api.debug_print = False
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print('film '+film.title+' not added')
|
||||
raise Exception('end')
|
||||
|
||||
# Poste les ajouts de doubles plus complexes
|
||||
i = 0
|
||||
for film, filmID in Llink2:
|
||||
i += 1
|
||||
print('['+str(i)+'/'+str(len(Llink2))+']'+'link2:', film.title)
|
||||
try:
|
||||
api.debug_print = True
|
||||
api.post_file(path='ftp://'+conf.get_domain(domain)+film.path, name=film.name, type='Film', type_id=filmID, **film.additional_info())
|
||||
api.debug_print = False
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print('film '+film.title+' not added')
|
||||
raise Exception('end')
|
||||
|
||||
# Poste tout les films locaux
|
||||
i = 0
|
||||
for film in Lunref:
|
||||
i += 1
|
||||
print('['+str(i)+'/'+str(len(Lunref))+']'+'post:', film.title)
|
||||
try:
|
||||
api.debug_print = True
|
||||
if film.year is not None:
|
||||
resp = api.post_film(title=film.title, year=film.year)
|
||||
else:
|
||||
resp = api.post_film(title=film.title)
|
||||
if "id" in resp:
|
||||
api.post_file(path='ftp://'+conf.get_domain(domain)+film.path, name=film.name, type='Film', type_id=resp["id"], **film.additional_info())
|
||||
api.debug_print = False
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print('film '+film.title+' not posted')
|
||||
raise Exception('end')
|
||||
"""
|
||||
# Marque comme broken les films référencés non présents
|
||||
'''
|
||||
i = 0
|
||||
for film in Lmissing:
|
||||
i += 1
|
||||
print('['+str(i)+'/'+len(Lmissing)+']'+'broken:', film)
|
||||
time.sleep(1)
|
||||
'''
|
||||
print('visit finished')
|
||||
|
||||
def main():
|
||||
conf = config.Config()
|
||||
api = piexel.Piexel(conf.server, conf.app, conf.token)
|
||||
for dom in conf.domains:
|
||||
visit_server(dom, conf, api)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue