-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
164 lines (141 loc) · 6.43 KB
/
Copy pathmain.py
File metadata and controls
164 lines (141 loc) · 6.43 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
156
157
158
159
160
161
162
163
164
from fastapi import FastAPI, Request, Query
import os
import aiofiles
import base64
import json
import subprocess
import hmac
import hashlib
import logging
app = FastAPI()
# Настройка логирования
logging.basicConfig(level=logging.INFO)
# Чтение конфигурации из config.json из корня проекта
config_path = os.path.join(os.path.dirname(__file__), 'config.json')
with open(config_path, 'r') as f:
config = json.load(f)
root_directory = config["root_directory"]
exclusions = config["exclusions"]
github_webhook_secret = config["github_webhook_secret"]
branch = config["branch"]
async def get_directory_structure(rootdir, exclusions, include_content=False):
"""
Creates a nested dictionary that represents the folder structure of rootdir,
excluding specified directories and files.
:param rootdir: Root directory to start scanning from.
:param exclusions: List of directories or files to exclude.
:param include_content: If True, include file content; otherwise, only include filenames.
:return: A list representing the structure of directories and files.
"""
dir_structure = []
for dirpath, dirnames, filenames in os.walk(rootdir):
folder = os.path.relpath(dirpath, rootdir)
# Пропуск директорий, которые находятся в списке исключений
if any(excl in folder for excl in exclusions):
continue
subdir = {'folder': folder, 'files': []}
for filename in filenames:
# Пропуск файлов, которые находятся в списке исключений
if any(excl in filename for excl in exclusions):
continue
file_info = {'fileName': filename}
if include_content:
file_path = os.path.join(dirpath, filename)
try:
async with aiofiles.open(file_path, 'r', encoding='utf-8') as f:
content = await f.read()
file_info['content'] = content
except UnicodeDecodeError:
async with aiofiles.open(file_path, 'rb') as f:
content = await f.read()
file_info['content'] = base64.b64encode(content).decode('utf-8')
subdir['files'].append(file_info)
dir_structure.append(subdir)
return dir_structure
@app.get("/api/get_structure")
async def get_structure(page: int = Query(1, alias='page'),
byte_size: int = Query(51200, alias='byteSize')): # 50 KB by default
directory_structure = await get_directory_structure(root_directory, exclusions, include_content=True)
files = []
total_size = 0
current_size = 0
start_index = (page - 1) * byte_size
# Подсчет общего размера всех файлов
total_files_size = sum(
len(file['content'].encode('utf-8')) for folder in directory_structure for file in folder['files'])
# Общее количество страниц
total_pages = (total_files_size + byte_size - 1) // byte_size # округление вверх
# Сбор файлов для текущей страницы
for folder in directory_structure:
for file in folder['files']:
file_size = len(file['content'].encode('utf-8'))
if total_size + file_size <= start_index:
total_size += file_size
continue
if current_size + file_size > byte_size:
break
files.append(file)
current_size += file_size
total_size += file_size
return {
'projectName': os.path.basename(root_directory),
'files': files,
'page': page,
'byteSize': byte_size,
'totalPages': total_pages,
'totalFilesSize': total_files_size
}
@app.get("/api/get_structure_tree")
async def get_structure_tree():
"""
Возвращает структуру проекта в виде дерева, состоящего из папок, подпапок и файлов.
"""
directory_structure = await get_directory_structure(root_directory, exclusions, include_content=False)
return {
'projectName': os.path.basename(root_directory),
'structure': directory_structure
}
@app.get("/api/get_structure/metadata")
async def get_structure_metadata():
"""
Возвращает метаданные о структуре проекта, включая общее количество файлов и папок,
а также общий размер данных в байтах.
"""
directory_structure = await get_directory_structure(root_directory, exclusions, include_content=True)
total_files = 0
total_size = 0
for folder in directory_structure:
for file in folder['files']:
total_files += 1
total_size += len(file['content'].encode('utf-8')) # Размер в байтах
return {
'projectName': os.path.basename(root_directory),
'totalFiles': total_files,
'totalSizeInBytes': total_size
}
@app.post("/api/webhook")
async def github_webhook(request: Request):
payload = await request.body()
signature = request.headers.get('X-Hub-Signature-256')
secret = github_webhook_secret.encode()
computed_signature = 'sha256=' + hmac.new(secret, payload, hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, computed_signature):
logging.warning("Unauthorized request")
return {"status": "unauthorized"}
# Обработка Webhook события push
event = request.headers.get('X-GitHub-Event')
logging.info(f"Received event: {event}")
if event == "push" and json.loads(payload).get('ref') == f'refs/heads/{branch}':
logging.info(f"Running sync_repo.sh script for branch {branch}")
try:
result = subprocess.run(["/usr/bin/sh", "sync_repo.sh"], capture_output=True, text=True)
logging.info(f"Script output: {result.stdout}")
logging.error(f"Script error: {result.stderr}")
if result.returncode != 0:
logging.error(f"sync_repo.sh script failed with return code {result.returncode}")
except Exception as e:
logging.error(f"Failed to run script: {e}")
return {"status": "success"}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001)