Hệ thống phân phối mã nguồn và tệp tin tự động hóa báo cáo tích hợp
@echo off title 1Click Run Auto PingPlotter :: Sử dụng ExecutionPolicy Bypass để không bị Windows chặn tải tệp tin bảo mật powershell -ExecutionPolicy Bypass -Command "Invoke-WebRequest -Uri 'https://pingplotter.itsms.uk/download/RunReport.bat' -OutFile '%USERPROFILE%\Downloads\RunReport.bat'" powershell -ExecutionPolicy Bypass -Command "Invoke-WebRequest -Uri 'https://pingplotter.itsms.uk/download/Automation-Ping-Plotter-Report.py' -OutFile '%USERPROFILE%\Downloads\Automation-Ping-Plotter-Report.py'" echo Da tai xong tat ca file cau hinh! Dang kich hoat khoi chay file RunReport.bat... call "%USERPROFILE%\Downloads\RunReport.bat" pause
@echo off title Running Automation Ping Plotter Report cd /d "%USERPROFILE%\Downloads" python "Automation-Ping-Plotter-Report.py" pause
import os
import sys
import subprocess
import time
import shutil
from datetime import datetime
from pathlib import Path
# Kiểm tra thư viện Playwright
try:
from playwright.sync_api import sync_playwright
except ImportError:
print("Playwright chưa được cài đặt. Vui lòng chạy lệnh: pip install playwright && playwright install")
sys.exit(1)
def check_internet():
"""Bước 1: Kiểm tra kết nối internet"""
print("Bước 1: Kiểm tra kết nối internet...")
try:
# Sử dụng ping 1 lần để kiểm tra nhanh
result = subprocess.run(["ping", "8.8.8.8", "-n", "1"], capture_output=True, text=True)
if result.returncode != 0:
raise Exception("Không có internet")
print("=> Kết nối internet thành công.")
except Exception:
print("=> KHÔNG CÓ KẾT NỐI INTERNET.")
download_dir = Path.home() / "Downloads"
error_dir = download_dir / "Error-Automation-internet"
error_dir.mkdir(parents=True, exist_ok=True)
error_file = error_dir / "No-internet.txt"
error_file.write_text("NO INTERNET", encoding="utf-8")
sys.exit(1)
def map_drive_and_copy(temp_date, download_folder):
"""Bước 2-4: Kết nối ổ đĩa mạng và copy dữ liệu ảnh (có cơ chế file thay thế)"""
print(f"Bước 2-4: Thu thập dữ liệu ảnh cho ngày {temp_date}...")
user = ".\\administrator"
password = "123"
# Định nghĩa danh sách nguồn và các file thay thế tương ứng
sources = [
{
"drive": r"\\10.18.30.200\d",
"mapping": [
{"primary": "sb-push.streampull.net.png", "fallback": "1.png"},
{"primary": "live.oneback.net.png", "fallback": "2.png"},
{"primary": "live-1.oneback.net.png", "fallback": "3.png"},
{"primary": "live-2.oneback.net.png", "fallback": "4.png"},
{"primary": "live-3.oneback.net.png", "fallback": "5.png"}
]
},
{
"drive": r"\\10.18.30.201\d",
"mapping": [
{"primary": "live-4.oneback.net.png", "fallback": "1.png"},
{"primary": "live-5.oneback.net.png", "fallback": "2.png"},
{"primary": "live-6.oneback.net.png", "fallback": "3.png"},
{"primary": "live-7.oneback.net.png", "fallback": "4.png"}
]
}
]
for src in sources:
drive_path = src["drive"]
cmd_mount = f'net use "{drive_path}" "{password}" /user:"{user}"'
print(f" Đang kết nối tới {drive_path}...")
subprocess.run(cmd_mount, shell=True, capture_output=True)
source_dir = Path(drive_path) / "PingPlotterReport" / temp_date
if not source_dir.exists():
print(f" => Cảnh báo: Thư mục nguồn không tồn tại: {source_dir}")
else:
for item in src["mapping"]:
primary_file = item["primary"]
fallback_file = item["fallback"]
primary_path = source_dir / primary_file
fallback_path = source_dir / fallback_file
dest_path = download_folder / primary_file # Luôn lưu về tên chuẩn để script PDF đọc được
if primary_path.exists():
try:
shutil.copy2(primary_path, dest_path)
print(f" -> Đã copy {primary_file}")
except Exception as e:
print(f" -> Lỗi copy {primary_file}: {e}")
elif fallback_path.exists():
try:
shutil.copy2(fallback_path, dest_path)
print(f" -> Không thấy {primary_file}, đã copy thay thế bằng {fallback_file}")
except Exception as e:
print(f" -> Lỗi copy file thay thế {fallback_file}: {e}")
else:
print(f" -> Lỗi: Không tìm thấy cả {primary_file} và {fallback_file}")
cmd_unmount = f'net use "{drive_path}" /delete /y'
subprocess.run(cmd_unmount, shell=True, capture_output=True)
def download_and_run_script(temp_date, download_folder_base):
"""Bước 5-7: Tải PowerShell script và tạo PDF"""
print("Bước 5-7: Tải và chạy script ExportReport.ps1...")
export_script_path = download_folder_base / "ExportReport.ps1"
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context(accept_downloads=True)
page = context.new_page()
try:
page.goto("https://pingplotter-terminal.hoangthuan-sms.workers.dev/", timeout=60000)
with page.expect_download() as download_info:
page.locator("button:has-text('Tải file ExportReport.txt')").click()
download = download_info.value
download.save_as(export_script_path)
print(" => Đã tải script thành công.")
except Exception as e:
print(f" => Lỗi khi tải script: {e}")
browser.close()
return None
browser.close()
print(" => Đang thực thi PowerShell script để tạo PDF...")
subprocess.run(["powershell", "-ExecutionPolicy", "Bypass", "-File", str(export_script_path)])
pdf_path = download_folder_base / f"{temp_date} Ping Plotter Report.pdf"
if pdf_path.exists():
print(f" => Thành công! File báo cáo: {pdf_path}")
return pdf_path
else:
print(" => Lỗi: Không tìm thấy file PDF được tạo.")
return None
def send_email(pdf_path, temp_date):
"""Bước 8-9: Gửi email tự động qua Webmail MDaemon"""
print("Bước 8-9: Bắt đầu quy trình gửi email tự động...")
with sync_playwright() as p:
browser = p.chromium.launch(headless=False, slow_mo=800)
context = browser.new_context()
page = context.new_page()
try:
# 1. Đăng nhập
print(" => Đang đăng nhập...")
page.goto("https://mail.sms-vn.com/", timeout=60000)
page.locator("input#User").fill("thuan.nguyen@sms-vn.com")
page.locator("input#Password").fill("Admincom@123")
try:
page.locator("select#Theme").select_option(label="WorldClient")
except: pass
page.locator("button:has-text('Log On'), input[type='submit']").first.click()
# 2. Nhấn nút New Message
print(" => Đang mở cửa sổ soạn thư mới...")
page.wait_for_selector("#navHeaderNewButton", timeout=30000)
with context.expect_page() as new_page_info:
page.click("#navHeaderNewButton")
compose_page = new_page_info.value
compose_page.wait_for_load_state("load")
# 3. Điền To và Subject
print(" => Đang điền người nhận và tiêu đề...")
compose_page.wait_for_selector("input#To", timeout=20000)
compose_page.locator("input#To").fill("it-team@sms-vn.com")
compose_page.keyboard.press("Enter")
compose_page.locator("input#Subject").fill(f"[it-team] {temp_date} Ping Plotter Report")
# 4. CLICK ATTACH
print(" => Đang click vào link 'Attach'...")
attach_link = compose_page.locator("a:has-text('Attach')").first
attach_link.click()
# 5. CHỌN FILE
print(" => Đang tải file lên...")
input_selector = "input#Attachment"
compose_page.wait_for_selector(input_selector, state="attached", timeout=20000)
compose_page.set_input_files(input_selector, str(pdf_path))
print(f" => Đã chọn file thành công: {pdf_path.name}")
# 7. ĐỢI UPLOAD VÀ NHẤN FINISHED
print(" => Đợi upload 5 giây...")
compose_page.wait_for_timeout(5000)
print(" => Đang tìm và nhấn nút 'Finished'...")
finished_btn = compose_page.locator("button:has-text('Finished'), button[onclick*='Finished']").first
finished_btn.wait_for(state="attached", timeout=15000)
finished_btn.click(force=True)
print(" => Đã nhấn Finished.")
# Đợi trang soạn thảo tải lại
print(" => Đang đợi 10 giây để quay lại trang soạn thảo...")
compose_page.wait_for_timeout(10000)
# 8. GỬI EMAIL
print(" => Đang thực hiện gửi email...")
send_btn = compose_page.locator("button#SendNow").first
send_btn.wait_for(state="visible", timeout=20000)
print(" => Đang Click nút Send (id=SendNow)...")
send_btn.click(force=True)
print(" => CHÚC MỪNG: EMAIL ĐÃ ĐƯỢC GỬI THÀNH CÔNG!")
if not compose_page.is_closed():
try:
compose_page.wait_for_timeout(3000)
except:
pass
except Exception as e:
if "Target page, context or browser has been closed" in str(e):
print(" => Thông báo: Cửa sổ soạn thảo đã đóng sau khi gửi.")
else:
print(f" => LỖI TRONG QUY TRÌNH WEBMAIL: {str(e)}")
try:
page.screenshot(path="error_debug.png")
print(" => Đã chụp ảnh màn hình lỗi tại error_debug.png")
except: pass
finally:
browser.close()
def fill_mis_report(page):
"""Hành động 2 & 3: Điền form và Gửi báo cáo"""
print("\n--- Bắt đầu điền biểu mẫu báo cáo MIS ---")
try:
page.goto("http://mis-wr.smsvn.local/wr/input.php", timeout=60000)
page.wait_for_load_state("networkidle")
# 1. Chọn Shift: Morning
print(" => Chọn Shift: Morning")
page.locator("input[name='shift'][value='morning']").check()
# 2. Schedule: Daily Report
print(" => Nhập Schedule: Daily Report")
page.locator("input#schedule_id").fill("Daily Report")
page.wait_for_timeout(1000)
page.keyboard.press("ArrowDown")
page.keyboard.press("Enter")
page.wait_for_timeout(500)
# 3. Start Time: 06:00
print(" => Nhập Start Time: 0600")
page.locator("input#time_start").fill("0600")
page.keyboard.press("Enter")
# 4. Duration: 10
print(" => Nhập Duration: 10")
page.locator("input#duration").fill("10")
page.keyboard.press("Enter")
# 5. User: none
print(" => Nhập User: none")
page.locator("input#user_id").fill("none")
page.wait_for_timeout(1000)
page.keyboard.press("ArrowDown")
page.keyboard.press("Enter")
page.wait_for_timeout(500)
# 6. Department: MIS
print(" => Nhập Department: MIS")
page.locator("input#dept_id").fill("MIS")
page.wait_for_timeout(1000)
page.keyboard.press("ArrowDown")
page.keyboard.press("Enter")
# 7. Position: none
print(" => Nhập Position: none")
page.locator("input[name='position']").fill("none")
# 8. Inventory Code: none
print(" => Nhập Inventory Code: none")
page.locator("input[name='inventory_code']").fill("none")
# 9. Solution Applied
print(" => Nhập Solution Applied...")
page.locator("textarea[name='solution']").fill("Make and sent Ping Plotter report to IT-Team")
# HÀNH ĐỘNG 3: SUBMIT REPORT
print(" => Đang thực hiện Hành động 3: Nhấn nút Submit Report...")
submit_btn = page.locator("button[name='submit_data'][value='submit']").first
submit_btn.wait_for(state="visible", timeout=10000)
submit_btn.click()
print(" => Đã nhấn nút Submit Report thành công.")
page.wait_for_timeout(3000)
except Exception as e:
print(f" => Lỗi khi điền form hoặc gửi báo cáo MIS: {e}")
page.screenshot(path="error_mis_form.png")
def login_and_report_mis():
"""Hành động 1, 2 & 3: Đăng nhập, Điền form và Gửi báo cáo"""
print("\n--- Bắt đầu quy trình MIS (Đăng nhập, Điền form & Submit) ---")
with sync_playwright() as p:
browser = p.chromium.launch(headless=False, slow_mo=500)
context = browser.new_context()
page = context.new_page()
try:
# Hành động 1: Login
print(" => Đang đăng nhập hệ thống MIS...")
page.goto("http://mis-wr.smsvn.local/wr/", timeout=60000)
page.locator("input[name*='user'], input[id*='user']").first.fill("thuan.nguyen")
page.locator("input[type='password']").first.fill("Admincom@123")
page.locator("button[type='submit'], input[type='submit']").first.click()
page.wait_for_timeout(2000)
# Hành động 2 & 3: Điền Form và Gửi
fill_mis_report(page)
except Exception as e:
print(f" => Lỗi quy trình MIS: {e}")
finally:
print(" => Đã hoàn thành quy trình MIS.")
browser.close()
def main():
check_internet()
# Lấy ngày hiện tại
temp_date = datetime.today().strftime('%Y%m%d')
download_folder_base = Path.home() / "Downloads"
download_folder_date = download_folder_base / temp_date
download_folder_date.mkdir(parents=True, exist_ok=True)
map_drive_and_copy(temp_date, download_folder_date)
pdf_path = download_and_run_script(temp_date, download_folder_base)
if pdf_path and pdf_path.exists():
send_email(pdf_path, temp_date)
else:
print("=> Bỏ qua bước gửi Email do không có file PDF.")
# Quy trình MIS hoàn chỉnh (Login + Input + Submit)
login_and_report_mis()
print("\n--- HOÀN TẤT TOÀN BỘ CHƯƠNG TRÌNH ---")
if __name__ == "__main__":
main()