|
|
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}`;
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
return JSON.stringify({ questions: [], message: null });
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
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',
|
|
|
});
|
|
|
|
|
|
if (response.status === 404) {
|
|
|
|
|
|
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);
|
|
|
|
|
|
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 };
|
|
|
};
|
|
|
|