-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
228 lines (204 loc) · 8.72 KB
/
script.js
File metadata and controls
228 lines (204 loc) · 8.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
// 言語データ
const translations = {
ja: {
homeTitle: "EDBP プラグイン・ネクサス",
whatIsEdbp: "🚀 EDBPとは?",
desc1: "EDBP (Easy Discord Bot Plugin) は、コーディング不要でDiscordボットを強化するモジュール式拡張システムです。",
desc2: "EDBB (Easy Discord Bot Builder) に組み込まれており、初心者からプロまで誰でも簡単に高機能ボットを構築できます。",
installMethod: "🤖 導入方法",
installList: [
"1. 公式ショップ(推奨) — ネクサスから即時インストール。ファイル操作不要。",
"2. 手動インポート — カスタムプラグインをファイルから読み込み。"
],
fetchedData: "📥 取得データ(GitHub経由)",
field: "項目",
desc: "説明",
nameDesc: "プラグイン名",
authorDesc: "開発者名",
starsDesc: "人気度(スター数)",
versionDesc: "最新バージョン",
descDesc: "機能概要",
shopTitle: "プラグイン・ネクサス",
backToHome: "← Homeに戻る",
backToNexus: "← ネクサスに戻る",
changelog: "📜 更新履歴",
footer: "© 2025 EDBP | すべてのクリエイターへ、すべてのクリエイターによって。"
},
en: {
homeTitle: "EDBP PLUGIN NEXUS",
whatIsEdbp: "🚀 What is EDBP?",
desc1: "EDBP (Easy Discord Bot Plugin) is a modular extension system that supercharges your Discord bot—no coding required.",
desc2: "Built into EDBB (Easy Discord Bot Builder), it empowers creators of all skill levels to customize bots with powerful, plug-and-play features.",
installMethod: "🤖 How to Install",
installList: [
"1. Official Shop (Recommended) — Install plugins instantly from the Nexus. No file management.",
"2. Manual Import — Load custom or community plugins via file import."
],
fetchedData: "📥 Fetched Data (via GitHub)",
field: "Field",
desc: "Description",
nameDesc: "Plugin title",
authorDesc: "Developer handle",
starsDesc: "Community popularity",
versionDesc: "Latest release tag",
descDesc: "Plugin functionality",
shopTitle: "Plugin Nexus",
backToHome: "← Back to Home",
backToNexus: "← Back to Nexus",
changelog: "📜 Changelog",
footer: "© 2025 EDBP | Built for creators, by creators."
}
};
// 言語管理
let currentLang = 'ja';
const detectLanguage = () => {
const urlLang = new URLSearchParams(window.location.search).get('lang');
if (urlLang === 'en' || urlLang === 'ja') return urlLang;
return navigator.language.startsWith('ja') ? 'ja' : 'en';
};
const setLanguage = (lang) => {
currentLang = lang;
const t = translations[lang];
// ホーム
document.getElementById('home-title').textContent = t.homeTitle;
document.getElementById('what-is-edbp').textContent = t.whatIsEdbp;
document.getElementById('desc1').textContent = t.desc1;
document.getElementById('desc2').textContent = t.desc2;
document.getElementById('install-method').textContent = t.installMethod;
const installList = document.getElementById('install-list');
installList.innerHTML = t.installList.map(item => `<li>${item}</li>`).join('');
document.getElementById('fetched-data').textContent = t.fetchedData;
document.getElementById('field').textContent = t.field;
document.getElementById('desc').textContent = t.desc;
document.getElementById('name-desc').textContent = t.nameDesc;
document.getElementById('author-desc').textContent = t.authorDesc;
document.getElementById('stars-desc').textContent = t.starsDesc;
document.getElementById('version-desc').textContent = t.versionDesc;
document.getElementById('desc-desc').textContent = t.descDesc;
// ショップ
document.getElementById('shop-title').textContent = t.shopTitle;
document.getElementById('homeFromShopBtn').textContent = t.backToHome;
document.getElementById('backToShopBtn').textContent = t.backToNexus;
// フッター
document.getElementById('footer-text').textContent = t.footer;
// 言語ボタン
document.getElementById('langToggle').textContent = lang === 'ja' ? 'EN' : 'JP';
// URLにlangを追加
const url = new URL(window.location);
url.searchParams.set('lang', lang);
history.replaceState(null, '', url);
};
// 切り替え
document.getElementById('langToggle').addEventListener('click', () => {
setLanguage(currentLang === 'ja' ? 'en' : 'ja');
});
// セクション制御
const showSection = id => {
document.querySelectorAll('.section').forEach(s => s.classList.remove('active'));
document.getElementById(id).classList.add('active');
};
document.getElementById('shopBtn').addEventListener('click', e => {
e.preventDefault();
showSection('shop');
if (!window.shopLoaded) loadShopData();
});
document.getElementById('homeFromShopBtn').addEventListener('click', e => {
e.preventDefault();
showSection('home');
});
document.getElementById('backToShopBtn').addEventListener('click', e => {
e.preventDefault();
showSection('shop');
});
// GitHub
const fetchPlugins = async () => {
try {
const res = await fetch('https://api.github.com/search/repositories?q=topic:edbp-plugin&sort=stars&order=desc&per_page=30');
const data = await res.json();
return data.items || [];
} catch {
return [];
}
};
const getReleases = async (owner, repo) => {
try {
const res = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases?per_page=10`);
if (res.ok) {
const releases = await res.json();
return releases.map(r => ({
name: r.name || r.tag_name,
published_at: r.published_at,
body: r.body || 'No description.'
}));
}
} catch {}
return [];
};
const formatDate = (d, lang) => {
if (!d) return lang === 'ja' ? '不明' : 'Unknown';
return new Date(d).toLocaleDateString(lang === 'ja' ? 'ja-JP' : 'en-US');
};
const loadShopData = async () => {
const plugins = await fetchPlugins();
const el = document.getElementById('shopContainer');
if (plugins.length === 0) {
el.innerHTML = `<div class="error">${currentLang === 'ja' ? 'プラグインが見つかりません' : 'No plugins found'}</div>`;
return;
}
el.innerHTML = plugins.slice(0, 12).map(p => `
<div class="shop-card" onclick="window.open('${p.html_url}', '_blank')">
<h3>${p.name}</h3>
<div class="plugin-meta">
<span class="author">@${p.owner.login}</span>
<span class="stars">★ ${p.stargazers_count}</span>
</div>
<p class="description">${p.description || (currentLang === 'ja' ? '説明なし' : 'No description.')}</p>
<div style="display:flex; gap:0.6rem; margin-top:1rem;">
<div class="view-releases" onclick="event.stopPropagation(); showPluginDetail('${p.owner.login}', '${p.name}')">
${translations[currentLang].changelog}
</div>
</div>
</div>
`).join('');
window.shopLoaded = true;
};
window.showPluginDetail = async (owner, repo) => {
const el = document.getElementById('detailContent');
el.innerHTML = `<div class="loading">${currentLang === 'ja' ? '更新履歴を読み込み中...' : 'Loading changelog...'}</div>`;
showSection('detail');
try {
const [repoData, releases] = await Promise.all([
fetch(`https://api.github.com/repos/${owner}/${repo}`).then(r => r.json()),
getReleases(owner, repo)
]);
const desc = repoData.description || (currentLang === 'ja' ? '説明なし' : 'No description.');
const releaseHtml = releases.length ? releases.map(r => `
<div class="release-item">
<div class="release-header">${r.name}</div>
<div class="release-date">${formatDate(r.published_at, currentLang)}</div>
<div class="release-body">${r.body.replace(/\n/g, '<br>')}</div>
</div>
`).join('') : `<p>${currentLang === 'ja' ? 'リリース履歴がありません' : 'No releases found.'}</p>`;
el.innerHTML = `
<h1>${repoData.name}</h1>
<p class="description">${desc}</p>
<div style="margin:1rem 0; color:var(--text-muted);">
by <span class="author">@${owner}</span> • <span class="stars">★ ${repoData.stargazers_count}</span>
</div>
<h2>${currentLang === 'ja' ? `更新履歴 (${releases.length} 件)` : `Changelog (${releases.length} releases)`}</h2>
${releaseHtml}
`;
} catch {
el.innerHTML = `<div class="error">${currentLang === 'ja' ? 'プラグイン情報の取得に失敗しました' : 'Failed to load plugin details.'}</div>`;
}
};
// 初期化
window.addEventListener('load', () => {
currentLang = detectLanguage();
setLanguage(currentLang);
const plugin = new URLSearchParams(window.location.search).get('plugin');
if (plugin && plugin.includes('/')) {
const [o, r] = plugin.split('/');
showPluginDetail(o, r);
}
});