Skip to content

Instantly share code, notes, and snippets.

@flashvnn
Created June 9, 2025 03:36
Show Gist options
  • Save flashvnn/b290cac981d7af06980f382f158bd0a1 to your computer and use it in GitHub Desktop.
Save flashvnn/b290cac981d7af06980f382f158bd0a1 to your computer and use it in GitHub Desktop.
Mihong SJC price
// Tên script: Widget Giá Vàng Mi Hồng
// Tác giả: Gemini
// Mô tả: Widget này hiển thị giá vàng SJC mới nhất từ API của mihong.vn.
// Phiên bản này bao gồm đầy đủ headers và cookies để giả lập yêu cầu từ trình duyệt.
// Hướng dẫn: Đặt widget ở cỡ vừa (Medium) để hiển thị đẹp nhất.
// --- CÀI ĐẶT ---
const GOLD_CODE = "SJC"; // Có thể đổi thành mã khác nếu API hỗ trợ
// URL API để lấy dữ liệu giá vàng từ Mi Hồng
const API_URL = `https://mihong.vn/api/v1/gold/prices?gold_code=${GOLD_CODE}&date_type=6`;
async function createWidget() {
const widget = new ListWidget();
const gradient = new LinearGradient();
gradient.locations = [0, 1];
gradient.colors = [
new Color("#2c3e50"),
new Color("#466368")
];
widget.backgroundGradient = gradient;
widget.setPadding(15, 15, 15, 15);
try {
// --- TẢI DỮ LIỆU TỪ API ---
const request = new Request(API_URL);
// --- HEADERS & COOKIES ---
// Thêm headers và cookies để giả lập yêu cầu từ trình duyệt, giống với lệnh curl.
// LƯU Ý: Các giá trị token này có thể hết hạn sau một thời gian. Nếu widget báo lỗi,
// bạn cần lấy giá trị XSRF-TOKEN và laravel_session mới từ trình duyệt và cập nhật lại vào đây.
const xsrfToken = "eyJpdiI6Ik5Pb2J2SkJxXC9nTlJmVzhcL0g3MTVxZz09IiwidmFsdWUiOiI2SEs0NXhLY2R1d0NsbmZ2cEozN0FkQ25HZlNGY3JSb0p4TWlmRHBcL0dPc2s3MExoWGdCWFJiMUg4cml5ZGVUVSIsIm1hYyI6IjFiM2U1ZjNmMzdiN2I1MjY1NGZiOTI0OTBiMDVmMGQxMzA1YmY2OTM2ODJiYzU4NzQ1NDA5ZTRlZTJiZWQxYTEifQ%3D%3D";
const laravelSession = "eyJpdiI6IlwvNjNCUlwvZ1VsNUE0TFM3d0xscVkrdz09IiwidmFsdWUiOiJ4dVFVQjhWU0orVE5PemdKbWluVGlLV2srMnhYekFnS1FPSUhCQk1YZHNIakpJYUlmcVRmNzV5MVZnVmNZQ2c4IiwibWFjIjoiZjhmZTVmZjE4NDRiMWFiYTJhY2Y5NzBkODhlNzdhODI2ZjhjOWIyNDJjZTY3NTkxODAzMTA1NWU3ZjM2YWU3OCJ9";
request.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
"Referer": "https://mihong.vn/vi/gia-vang-trong-nuoc",
"Cookie": `XSRF-TOKEN=${xsrfToken}; laravel_session=${laravelSession}`,
"X-Requested-With": "XMLHttpRequest",
"accept": "*/*"
};
const response = await request.loadJSON();
// Kiểm tra dữ liệu trả về có hợp lệ không
if (!response || !response.success || !Array.isArray(response.data) || response.data.length === 0) {
return createErrorWidget("Không thể tải dữ liệu. API có thể đã thay đổi hoặc cần xác thực (token hết hạn).");
}
// Lấy dữ liệu mới nhất (là phần tử cuối cùng trong mảng)
const latestData = response.data[response.data.length - 1];
// --- TIÊU ĐỀ WIDGET ---
const titleStack = widget.addStack();
titleStack.layoutHorizontally();
const titleText = titleStack.addText(`Giá Vàng ${GOLD_CODE}`);
titleText.font = Font.boldSystemFont(18);
titleText.textColor = new Color("#f1c40f"); // Màu vàng
titleStack.addSpacer();
const logoImg = titleStack.addImage(SFSymbol.named("dollarsign.circle.fill").image);
logoImg.imageSize = new Size(24, 24);
logoImg.tintColor = new Color("#f1c40f");
widget.addSpacer(); // Thêm khoảng trống
// --- HIỂN THỊ GIÁ MUA VÀ BÁN ---
const priceStack = widget.addStack();
priceStack.layoutHorizontally();
// Cột giá mua
const buyStack = priceStack.addStack();
buyStack.layoutVertically();
const buyLabel = buyStack.addText("Mua vào");
buyLabel.font = Font.mediumSystemFont(14);
buyLabel.textColor = Color.white();
buyStack.addSpacer(4);
const buyPriceText = buyStack.addText(formatPrice(latestData.buy));
buyPriceText.font = Font.boldSystemFont(22);
buyPriceText.textColor = new Color("#2ecc71"); // Màu xanh lá
priceStack.addSpacer(); // Căn giữa 2 cột
// Cột giá bán
const sellStack = priceStack.addStack();
sellStack.layoutVertically();
sellStack.centerAlignContent();
const sellLabel = sellStack.addText("Bán ra");
sellLabel.font = Font.mediumSystemFont(14);
sellLabel.textColor = Color.white();
sellStack.addSpacer(4);
const sellPriceText = sellStack.addText(formatPrice(latestData.sell));
sellPriceText.font = Font.boldSystemFont(22);
sellPriceText.textColor = new Color("#e74c3c"); // Màu đỏ
widget.addSpacer(); // Thêm khoảng trống ở dưới
// --- THỜI GIAN CẬP NHẬT TỪ API ---
const updateDate = new Date(latestData.date);
const dateText = widget.addText(`Cập nhật: ${formatDate(updateDate)}`);
dateText.font = Font.regularSystemFont(10);
dateText.textColor = new Color("#bdc3c7");
dateText.rightAlignText();
} catch (error) {
console.error(error);
return createErrorWidget("Có lỗi khi chạy script. Hãy kiểm tra lại kết nối mạng hoặc API.");
}
return widget;
}
// Hàm tạo widget hiển thị lỗi
function createErrorWidget(errorMessage) {
const widget = new ListWidget();
widget.addText("Lỗi Widget Giá Vàng");
widget.addSpacer(5);
const errorText = widget.addText(errorMessage);
errorText.font = Font.systemFont(12);
errorText.textColor = Color.red();
return widget;
}
// Hàm định dạng giá cho dễ đọc (đơn vị: triệu/lượng)
function formatPrice(priceString) {
const price = parseFloat(priceString);
if (isNaN(price) || price === 0) {
return "-";
}
return (price / 1000000).toFixed(2);
}
// Hàm định dạng lại ngày tháng cho dễ nhìn
function formatDate(date) {
const options = { hour: '2-digit', minute: '2-digit', day: '2-digit', month: '2-digit' };
return date.toLocaleString('vi-VN', options);
}
// --- CHẠY SCRIPT ---
const widget = await createWidget();
if (config.runsInWidget) {
Script.setWidget(widget);
} else {
widget.presentMedium();
}
Script.complete();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment