Aditya DN
Upload 6 files
5372a29 verified
import { defaultData, type GitHubData } from '../types';
const GITHUB_TOKEN = process.env.GITHUB_API_KEY;
const REPO_OWNER = 'Adityadn64';
const REPO_NAME = 'Tampilan-MP42PPT';
const FILE_PATH = 'data.json';
const API_URL = `https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/contents/${FILE_PATH}`;
// Fungsi untuk decode Base64 yang aman untuk Unicode
function b64DecodeUnicode(str: string) {
try {
return decodeURIComponent(atob(str).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
} catch (e) {
console.error("Gagal mendekode Base64:", e);
// Kembalikan struktur data default jika gagal
return JSON.stringify({ questions: [], message: null });
}
}
// Fungsi untuk encode ke Base64 yang aman untuk Unicode
function b64EncodeUnicode(str: string) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
function toSolidBytes(match, p1) {
return String.fromCharCode(parseInt(p1, 16));
}));
}
export const getData = async (): Promise<{ data: GitHubData, sha: string | null }> => {
if (!GITHUB_TOKEN) {
throw new Error("GITHUB_API_KEY tidak diatur.");
}
const response = await fetch(API_URL, {
headers: {
'Authorization': `token ${GITHUB_TOKEN}`,
'Accept': 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
},
cache: 'no-cache', // Selalu ambil data terbaru
});
if (response.status === 404) {
// File tidak ada, ini adalah kondisi yang valid untuk repositori baru.
return { data: defaultData, sha: null };
}
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`Gagal mengambil data dari GitHub: ${errorData.message}`);
}
const responseData = await response.json();
const decodedContent = b64DecodeUnicode(responseData.content);
try {
const data = JSON.parse(decodedContent);
// Pastikan data memiliki struktur yang diharapkan
const validatedData: GitHubData = {
idx: data.idx,
direction: data.direction
};
console.log({data}, {validatedData})
return { data: validatedData, sha: responseData.sha };
} catch(e) {
console.error("Gagal mem-parsing JSON dari GitHub:", e);
throw new Error("Format data dari GitHub tidak valid.");
}
};
export const saveData = async (
data: GitHubData,
commitMessage: string,
sha: string | null
): Promise<{ sha: string }> => {
if (!GITHUB_TOKEN) {
throw new Error("GITHUB_API_KEY tidak diatur.");
}
const content = JSON.stringify(data, null, 2);
const encodedContent = b64EncodeUnicode(content);
console.log(content);
const body: { message: string; content: string; sha?: string } = {
message: commitMessage,
content: encodedContent,
};
if (sha) {
body.sha = sha;
}
let isSuccess = false;
let responseData;
while (!isSuccess) {
try {
const response = await fetch(API_URL, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${GITHUB_TOKEN}`,
'Accept': 'application/vnd.github+json',
'X-GitHub-Api-Version': '2022-11-28',
},
body: JSON.stringify(body),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`Gagal menyimpan data ke GitHub: ${errorData.message}`);
}
responseData = await response.json();
isSuccess = true;
} catch (e) {
if (e.message.includes("does not match")) {
const newData = await getData();
body.sha = newData.sha;
} else {
isSuccess = true;
}
}
}
return { sha: responseData.content.sha };
};