feat:修改了软件下载源

This commit is contained in:
sqj
2025-09-06 18:56:35 +08:00
parent d03d62c8d4
commit 394bdd573c
7 changed files with 844 additions and 29 deletions

View File

@@ -11,15 +11,163 @@ function scrollToFeatures() {
});
}
// GitHub repository configuration
// Alist API configuration
const ALIST_BASE_URL = 'http://47.96.72.224:5244';
const ALIST_USERNAME = 'ceruupdate';
const ALIST_PASSWORD = '123456';
// GitHub repository configuration (for fallback)
const GITHUB_REPO = 'timeshiftsauce/CeruMusic';
const GITHUB_API_URL = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`;
// Cache for release data
let releaseData = null;
let releaseDataTimestamp = null;
let alistToken = null;
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
// Alist authentication
async function getAlistToken() {
if (alistToken) {
return alistToken;
}
try {
const response = await fetch(`${ALIST_BASE_URL}/api/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: ALIST_USERNAME,
password: ALIST_PASSWORD
})
});
const data = await response.json();
if (data.code === 200) {
alistToken = data.data.token;
return alistToken;
} else {
throw new Error(`Alist authentication failed: ${data.message}`);
}
} catch (error) {
console.error('Alist authentication error:', error);
throw error;
}
}
// Get available versions from Alist
async function getAlistVersions() {
try {
const token = await getAlistToken();
const response = await fetch(`${ALIST_BASE_URL}/api/fs/list`, {
method: 'POST',
headers: {
'Authorization': token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
path: '/',
password: '',
page: 1,
per_page: 100,
refresh: false
})
});
const data = await response.json();
if (data.code === 200) {
// Filter directories that look like version numbers
const versions = data.data.content
.filter(item => item.is_dir && /^v?\d+\.\d+\.\d+/.test(item.name))
.sort((a, b) => b.name.localeCompare(a.name)); // Sort by version desc
return versions;
} else {
throw new Error(`Failed to get versions: ${data.message}`);
}
} catch (error) {
console.error('Failed to get Alist versions:', error);
return [];
}
}
// Get files in a specific version directory
async function getAlistVersionFiles(version) {
try {
const token = await getAlistToken();
const response = await fetch(`${ALIST_BASE_URL}/api/fs/list`, {
method: 'POST',
headers: {
'Authorization': token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
path: `/${version}`,
password: '',
page: 1,
per_page: 100,
refresh: false
})
});
const data = await response.json();
if (data.code === 200) {
return data.data.content.filter(item => !item.is_dir);
} else {
throw new Error(`Failed to get version files: ${data.message}`);
}
} catch (error) {
console.error('Failed to get version files:', error);
return [];
}
}
// Get direct download URL from Alist
async function getAlistDownloadUrl(version, fileName) {
try {
const token = await getAlistToken();
const filePath = `/${version}/${fileName}`;
const response = await fetch(`${ALIST_BASE_URL}/api/fs/get`, {
method: 'POST',
headers: {
'Authorization': token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
path: filePath
})
});
const data = await response.json();
if (data.code === 200) {
const fileInfo = data.data;
// Try different URL formats
if (fileInfo.raw_url) {
return fileInfo.raw_url;
} else if (fileInfo.sign) {
return `${ALIST_BASE_URL}/d${filePath}?sign=${fileInfo.sign}`;
} else {
return `${ALIST_BASE_URL}/d${filePath}`;
}
} else {
throw new Error(`Failed to get download URL: ${data.message}`);
}
} catch (error) {
console.error('Failed to get Alist download URL:', error);
throw error;
}
}
// Download functionality
async function downloadApp(platform) {
const button = event.target;
@@ -35,38 +183,53 @@ async function downloadApp(platform) {
button.disabled = true;
try {
// Get latest release data
const release = await getLatestRelease();
// Try Alist first
const versions = await getAlistVersions();
if (!release) {
throw new Error('无法获取最新版本信息');
if (versions.length > 0) {
const latestVersion = versions[0];
const files = await getAlistVersionFiles(latestVersion.name);
// Find the appropriate file for the platform
const fileName = findFileForPlatform(files, platform);
if (fileName) {
const downloadUrl = await getAlistDownloadUrl(latestVersion.name, fileName);
// Show success notification
showNotification(`正在下载 ${getPlatformName(platform)} 版本 ${latestVersion.name}...`, 'success');
// Start download
window.open(downloadUrl, '_blank');
// Track download
trackDownload(platform, latestVersion.name);
return; // Success, exit function
}
}
// Find the appropriate download asset
const downloadUrl = findDownloadAsset(release.assets, platform);
if (!downloadUrl) {
throw new Error(`暂无 ${getPlatformName(platform)} 版本下载`);
}
// Show success notification
showNotification(`正在下载 ${getPlatformName(platform)} 版本 v${release.tag_name}...`, 'success');
// Start download
window.open('https://gh.bugdey.us.kg/'+downloadUrl, '_blank');
// Track download
trackDownload(platform, release.tag_name);
// Fallback to GitHub if Alist fails
console.log('Alist download failed, trying GitHub fallback...');
await downloadFromGitHub(platform);
} catch (error) {
console.error('Download error:', error);
showNotification(`下载失败: ${error.message}`, 'error');
// Fallback to GitHub releases page
setTimeout(() => {
showNotification('正在跳转到GitHub下载页面...', 'info');
window.open(`https://gh.bugdey.us.kg/https://github.com/${GITHUB_REPO}/releases/latest`, '_blank');
}, 2000);
// Try GitHub fallback
try {
console.log('Trying GitHub fallback...');
await downloadFromGitHub(platform);
} catch (fallbackError) {
console.error('GitHub fallback also failed:', fallbackError);
showNotification(`下载失败: ${error.message}`, 'error');
// Final fallback to GitHub releases page
setTimeout(() => {
showNotification('正在跳转到GitHub下载页面...', 'info');
window.open(`https://github.com/${GITHUB_REPO}/releases/latest`, '_blank');
}, 2000);
}
} finally {
// Restore button state
setTimeout(() => {
@@ -76,6 +239,30 @@ async function downloadApp(platform) {
}
}
// GitHub fallback function
async function downloadFromGitHub(platform) {
const release = await getLatestRelease();
if (!release) {
throw new Error('无法获取最新版本信息');
}
const downloadUrl = findDownloadAsset(release.assets, platform);
if (!downloadUrl) {
throw new Error(`暂无 ${getPlatformName(platform)} 版本下载`);
}
// Show success notification
showNotification(`正在下载 ${getPlatformName(platform)} 版本 v${release.tag_name}...`, 'success');
// Start download
window.open(downloadUrl, '_blank');
// Track download
trackDownload(platform, release.tag_name);
}
// Get latest release from GitHub API
async function getLatestRelease() {
// Check cache first
@@ -104,6 +291,64 @@ async function getLatestRelease() {
}
}
// Find appropriate file for platform from Alist files
function findFileForPlatform(files, platform) {
if (!files || !Array.isArray(files)) {
return null;
}
// Define file patterns for each platform
const patterns = {
windows: [
/\\.exe$/i,
/windows.*\\.zip$/i,
/win32.*\\.zip$/i,
/win.*x64.*\\.zip$/i
],
macos: [
/\\.dmg$/i,
/darwin.*\\.zip$/i,
/macos.*\\.zip$/i,
/mac.*\\.zip$/i,
/osx.*\\.zip$/i
],
linux: [
/\\.AppImage$/i,
/linux.*\\.zip$/i,
/linux.*\\.tar\\.gz$/i,
/\\.deb$/i,
/\\.rpm$/i
]
};
const platformPatterns = patterns[platform] || [];
// Try to find exact match
for (const pattern of platformPatterns) {
const file = files.find(file => pattern.test(file.name));
if (file) {
return file.name;
}
}
// Fallback: look for any file that might match the platform
const fallbackPatterns = {
windows: /win|exe/i,
macos: /mac|darwin|dmg/i,
linux: /linux|appimage|deb|rpm/i
};
const fallbackPattern = fallbackPatterns[platform];
if (fallbackPattern) {
const file = files.find(file => fallbackPattern.test(file.name));
if (file) {
return file.name;
}
}
return null;
}
// Find appropriate download asset based on platform
function findDownloadAsset(assets, platform) {
if (!assets || !Array.isArray(assets)) {
@@ -460,6 +705,36 @@ window.addEventListener('error', (e) => {
// Update version information on page
async function updateVersionInfo() {
try {
// Try to get version info from Alist first
const versions = await getAlistVersions();
if (versions.length > 0) {
const latestVersion = versions[0];
const versionElement = document.querySelector('.version');
const versionInfoElement = document.querySelector('.version-info p');
if (versionElement) {
versionElement.textContent = latestVersion.name;
}
if (versionInfoElement) {
const modifyDate = new Date(latestVersion.modified);
const formattedDate = modifyDate.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long'
});
versionInfoElement.innerHTML = `当前版本: <span class="version">${latestVersion.name}</span> | 更新时间: ${formattedDate}`;
}
// Update download button text with file info from Alist
const files = await getAlistVersionFiles(latestVersion.name);
updateDownloadButtonsWithAlistFiles(files);
return; // Success, exit function
}
// Fallback to GitHub if Alist fails
console.log('Alist version info failed, trying GitHub fallback...');
const release = await getLatestRelease();
if (release) {
const versionElement = document.querySelector('.version');
@@ -486,6 +761,29 @@ async function updateVersionInfo() {
}
}
// Update download buttons with Alist file information
function updateDownloadButtonsWithAlistFiles(files) {
if (!files || !Array.isArray(files)) return;
const downloadCards = document.querySelectorAll('.download-card');
const platforms = ['windows', 'macos', 'linux'];
downloadCards.forEach((card, index) => {
const platform = platforms[index];
const fileName = findFileForPlatform(files, platform);
if (fileName) {
const file = files.find(f => f.name === fileName);
const button = card.querySelector('.btn-download');
const sizeText = formatFileSize(file.size);
const originalText = button.innerHTML;
// Add file size info
button.innerHTML = originalText.replace(/下载 \..*?$/, `下载 .${getFileExtension(fileName)} (${sizeText})`);
}
});
}
// Update download buttons with asset information
function updateDownloadButtonsWithAssets(assets) {
if (!assets || !Array.isArray(assets)) return;