-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfolder.py
More file actions
155 lines (133 loc) · 5.78 KB
/
Copy pathfolder.py
File metadata and controls
155 lines (133 loc) · 5.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import os
from datetime import datetime
import time
from typing import Dict, Any
from settings import logger
from cloud_folder import CloudFolder
class Folder:
"""
Описывает папку операционной системы.
"""
def __init__(self, path: str) -> None:
self.is_connect: bool = False
if os.path.isdir(path):
self.path: str = path
else:
raise Exception('Переданный путь из .env приводит не к папке!')
def create_local_path(self, filename: str) -> str:
"""
Создает полный путь для файла в локальной папке.
:param filename: Имя файла
:return: Полный путь к файлу
"""
return os.path.join(self.path, filename)
def do_connection(self, cloud_folder: CloudFolder) -> None:
"""
Устанавливает соединение с облачной папкой.
:param cloud_folder: Объект класса CloudFolder
"""
if isinstance(cloud_folder, CloudFolder):
self.is_connect = True
self.remote = cloud_folder
cloud_folder.local = self
def is_connected(self) -> None:
"""
Проверяет, подключена ли облачная папка.
"""
if not self.is_connect:
raise Exception('Не подключена облачная папка!')
def get_files_list(self) -> Dict[str, Dict[str, Any]]:
"""
Получает список файлов в локальной папке.
:return: Словарь с информацией о файлах
"""
files = {}
for filename in os.listdir(self.path):
path = self.create_local_path(filename)
files[filename] = {
'name': filename,
'path': path,
'modified': datetime.utcfromtimestamp(os.path.getmtime(path)).isoformat()
}
return files
def download_file(self, filename: str) -> None:
"""
Загружает файл из облачной папки.
:param filename: Имя файла
"""
url = self.remote.main_url + 'resources/download/'
params = {
'path': self.remote.create_remote_path(filename),
}
download_url = self.remote.connect(url, headers=self.remote.headers, params=params)
if download_url:
url = download_url.json()["href"]
with open(self.create_local_path(filename), 'wb') as file:
download_response = self.remote.connect(url)
file.write(download_response.content)
logger.success(f'Файл {filename} успешно скачан с облака!')
def first_sync_modifications(self) -> None:
"""
Синхронизирует файлы по времени последнего изменения.
"""
local_files = self.get_files_list()
cloud_files = self.remote.get_files_list()
intersection = set(local_files) & set(cloud_files)
for filename in intersection:
if cloud_files[filename]['modified'] > local_files[filename]['modified']:
self.download_file(filename)
elif cloud_files[filename]['modified'] < local_files[filename]['modified']:
self.remote.upload_file(filename)
def first_sync_by_name(self) -> None:
"""
Синхронизирует файлы по наличию имени файла.
"""
file_set = set(self.get_files_list())
cloud_set = set(self.remote.get_files_list())
add_to_local = cloud_set - file_set
add_to_cloud = file_set - cloud_set
for filename in add_to_local:
self.download_file(filename)
for filename in add_to_cloud:
self.remote.upload_file(filename)
def first_sync(self) -> None:
"""
Выполняет первую синхронизацию файлов.
"""
self.first_sync_modifications()
self.first_sync_by_name()
logger.success('Первичная синхронизация прошла успешно!')
def start_logging(self, period: int = 5) -> None:
"""
Начинает логирование изменений в файлах.
:param period: Период логирования в секундах
"""
self.is_connected()
self.first_sync()
while True:
files_before = self.get_files_list()
time.sleep(period)
self.logging_files(files_before)
def logging_files_by_names(self, files_before: set) -> None:
"""
Логирует изменения в файлах по именам.
:param files_before: Список файлов до изменений
"""
files_now = set(self.get_files_list())
add_set = files_now - files_before
remove_set = files_before - files_now
for filename in add_set:
self.remote.upload_file(filename)
for filename in remove_set:
self.remote.delete_file(filename)
def logging_files(self, files_before: Dict[str, Dict[str, Any]]) -> None:
"""
Логирует изменения в файлах.
:param files_before: Список файлов до изменений
"""
files_now = self.get_files_list()
intersection = set(files_before) & set(files_now)
for filename in intersection:
if files_now[filename]['modified'] > files_before[filename]['modified']:
self.remote.upload_file(filename)
self.logging_files_by_names(set(files_before))