update-case-drive 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,155 @@
1
+ import ctypes
2
+ import os
3
+
4
+ import psutil
5
+ import requests
6
+ import typer
7
+
8
+ app = typer.Typer()
9
+
10
+
11
+ def get_windows_volume_name(drive_letter):
12
+ """ฟังก์ชันสำหรับดึง Volume Name (ชื่อไดรฟ์) จาก Windows อัตโนมัติ"""
13
+ volume_name_buffer = ctypes.create_unicode_buffer(261)
14
+ file_system_buffer = ctypes.create_unicode_buffer(261)
15
+ serial_number = ctypes.c_ulong(0)
16
+ max_component_len = ctypes.c_ulong(0)
17
+ file_system_flags = ctypes.c_ulong(0)
18
+
19
+ try:
20
+ rc = ctypes.windll.kernel32.GetVolumeInformationW(
21
+ ctypes.c_wchar_p(drive_letter),
22
+ volume_name_buffer,
23
+ ctypes.sizeof(volume_name_buffer),
24
+ ctypes.byref(serial_number),
25
+ ctypes.byref(max_component_len),
26
+ ctypes.byref(file_system_flags),
27
+ file_system_buffer,
28
+ ctypes.sizeof(file_system_buffer),
29
+ )
30
+ if rc:
31
+ return volume_name_buffer.value
32
+ except (OSError, ctypes.ArgumentError) as e:
33
+ print(f"Error occurred while fetching volume name for {drive_letter}: {e}")
34
+ return ""
35
+
36
+
37
+ @app.command()
38
+ def browse(
39
+ mode: str = typer.Option(
40
+ "online",
41
+ help="โหมดการเชื่อมต่อ: 'local' สำหรับ localhost หรือ 'online' สำหรับ server จริง",
42
+ ),
43
+ ):
44
+ """แสดงรายการไดรฟ์เฉพาะที่มีการตั้งชื่อ Volume Name (ยกเว้น Drive C)
45
+
46
+ ให้ผู้ใช้เลือก แล้วส่งข้อมูลไป Django API ทันที
47
+ """
48
+ # กำหนด URL ตามโหมดที่เลือก
49
+ if mode.lower() == "local":
50
+ api_url = "http://127.0.0.1:9747/drives/api/receive/"
51
+ typer.echo("🛠️ โหมด: Local (http://127.0.0.1:9747/)")
52
+ else:
53
+ api_url = "https://www.policeadmin.com/storage/drives/api/receive/"
54
+ typer.echo("🌐 โหมด: Online (https://www.policeadmin.com/)")
55
+
56
+ # 1. ดึงรายชื่อพาร์ทิชัน/ไดรฟ์ทั้งหมดในเครื่อง
57
+ partitions = psutil.disk_partitions(all=True)
58
+ drive_list = []
59
+
60
+ typer.echo("🖥️ รายชื่อไดรฟ์ที่มีการตั้งชื่อในระบบ (ไม่รวม Drive C):")
61
+ for partition in partitions:
62
+ mountpoint = partition.mountpoint
63
+
64
+ # ข้าม Drive C (รองรับทั้ง C:\ และรูปแบบอื่นๆ ที่ขึ้นต้นด้วย C)
65
+ if mountpoint.lower().startswith("c:") or "c:\\" in mountpoint.lower():
66
+ continue
67
+
68
+ # ดึงชื่อ Volume Name
69
+ vol_name = get_windows_volume_name(mountpoint)
70
+
71
+ # กรองเฉพาะไดรฟ์ที่มีการตั้งชื่อ (Volume Name) เท่านั้น ถ้าไม่มีให้ข้ามไป
72
+ if not vol_name:
73
+ continue
74
+
75
+ drive_list.append(mountpoint)
76
+ label_display = f" [ชื่อ: {vol_name}]"
77
+
78
+ # เช็คขนาดความจุ
79
+ size_info = ""
80
+ try:
81
+ usage = psutil.disk_usage(mountpoint)
82
+ total_gb = usage.total / (1024**3)
83
+ free_gb = usage.free / (1024**3)
84
+ size_info = f" (ความจุ: {total_gb:.2f} GB, ว่าง: {free_gb:.2f} GB)"
85
+ except OSError:
86
+ size_info = " (ไม่สามารถอ่านข้อมูลความจุได้)"
87
+
88
+ current_idx = len(drive_list) - 1
89
+ typer.echo(f" [{current_idx}] {mountpoint}{label_display}{size_info}")
90
+
91
+ if not drive_list:
92
+ typer.echo("❌ ไม่พบไดรฟ์ที่มีการตั้งชื่อ Volume Name ในระบบ (นอกจาก Drive C)")
93
+ raise typer.Exit()
94
+
95
+ # 2. ให้ผู้ใช้เลือกหมายเลขไดรฟ์
96
+ selected_idx = typer.prompt("\nกรุณากรอกหมายเลขไดรฟ์ที่ต้องการเปิดดู", type=int)
97
+
98
+ if selected_idx < 0 or selected_idx >= len(drive_list):
99
+ typer.echo("❌ หมายเลขไดรฟ์ไม่ถูกต้อง")
100
+ raise typer.Exit()
101
+
102
+ selected_drive = drive_list[selected_idx]
103
+
104
+ # 3. ดึงชื่ออัตโนมัติจากไดรฟ์ที่เลือก
105
+ storage_name = get_windows_volume_name(selected_drive)
106
+
107
+ typer.echo(f"\n📂 กำลังเปิดดูและรวบรวมข้อมูลโฟลเดอร์ในไดรฟ์: {selected_drive} (ชื่อที่ใช้: {storage_name})\n")
108
+
109
+ # 4. อ่านขนาดความจุ และรายชื่อโฟลเดอร์ในไดรฟ์ที่เลือก
110
+ total_gb = 0.0
111
+ try:
112
+ usage = psutil.disk_usage(selected_drive)
113
+ total_gb = round(usage.total / (1024**3), 2)
114
+ except OSError:
115
+ typer.echo("⚠️ ไม่สามารถอ่านขนาดความจุของไดรฟ์ได้ (จะส่งขนาดเป็น 0.0)")
116
+
117
+ folders = []
118
+ try:
119
+ items = os.listdir(selected_drive)
120
+ folders = [os.path.join(selected_drive, item) for item in items if os.path.isdir(os.path.join(selected_drive, item))]
121
+
122
+ if not folders:
123
+ typer.echo("📁 ไม่พบโฟลเดอร์ย่อยในไดรฟ์นี้")
124
+ else:
125
+ typer.echo(f"พบโฟลเดอร์ทั้งหมด {len(folders)} โฟลเดอร์:")
126
+ for folder in folders:
127
+ typer.echo(f" - 📁 {folder}")
128
+
129
+ except PermissionError:
130
+ typer.echo(f"❌ ไม่มีสิทธิ์เข้าถึงไดรฟ์ {selected_drive} (Permission Denied)")
131
+ except OSError as e:
132
+ typer.echo(f"❌ เกิดข้อผิดพลาดในการอ่านโฟลเดอร์: {e}")
133
+
134
+ # 5. เตรียม Payload ส่งข้อมูลไปยัง Django API
135
+ payload = {
136
+ "name": storage_name, # ชื่อไดรฟ์ที่ดึงจาก Windows อัตโนมัติ (เช่น SC01)
137
+ "drive_path": selected_drive, # เก็บ path จริงไว้ด้วย (เช่น D:\)
138
+ "size_gb": total_gb,
139
+ "folders": folders,
140
+ }
141
+
142
+ typer.echo(f"\n🚀 กำลังส่งข้อมูลไปยัง Django API ({api_url})...")
143
+ try:
144
+ response = requests.post(api_url, json=payload, timeout=10)
145
+ if response.status_code == 201:
146
+ typer.echo("✅ ส่งข้อมูลเข้า Django Database สำเร็จ!")
147
+ typer.echo(f" Response: {response.json()}")
148
+ else:
149
+ typer.echo(f"⚠️ เกิดข้อผิดพลาดจาก Server (Status {response.status_code}): {response.text}")
150
+ except requests.exceptions.RequestException as e:
151
+ typer.echo(f"❌ ไม่สามารถเชื่อมต่อ API ได้: {e}")
152
+
153
+
154
+ if __name__ == "__main__":
155
+ app()
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.3
2
+ Name: update-case-drive
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ Author: 6vi7ms
6
+ Author-email: 6vi7ms <6vi7ms@gmail.com>
7
+ Requires-Dist: psutil>=7.2.2
8
+ Requires-Dist: requests>=2.34.2
9
+ Requires-Dist: typer>=0.27.3
10
+ Requires-Python: >=3.13
11
+ Description-Content-Type: text/markdown
12
+
@@ -0,0 +1,6 @@
1
+ update_case_drive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ update_case_drive/main.py,sha256=Hq5NA_CpbQHfwvv7CNdmmQfKdHDFWfd8Bmf3lSz-35A,7555
3
+ update_case_drive-0.1.0.dist-info/WHEEL,sha256=7hzKWg-J8I3Buqyw5tBii5z_MmAVsDYXXijd_QAtNZ8,81
4
+ update_case_drive-0.1.0.dist-info/entry_points.txt,sha256=CuZJjb6LSoffsvj2zoD2vmoLxh6TIJaYNjiyk433ZdE,66
5
+ update_case_drive-0.1.0.dist-info/METADATA,sha256=GlO3X4n_wSQbxndJk6bP3Lw9-MT-qWEzy_HIXKchuLc,306
6
+ update_case_drive-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.12.18
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ update-case-drive = update_case_drive.main:app
3
+