successfully intercept the mp4 request (but 401 response get, as cookie not sent)

This commit is contained in:
Tiger Ren 2025-01-07 14:27:40 +08:00
parent b9248eecb9
commit 28e4e07b83
3 changed files with 174 additions and 13 deletions

89
main.js
View File

@ -1,5 +1,7 @@
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const { app, BrowserWindow, ipcMain, dialog, session } = require('electron');
const path = require('path');
const fs = require('fs');
const https = require('https');
let store;
let mainWindow;
@ -8,9 +10,11 @@ let mainWindow;
(async () => {
const Store = await import('electron-store');
store = new Store.default();
console.log('Store initialized');
})();
function createWindow() {
console.log('Creating main window...');
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
@ -21,8 +25,79 @@ function createWindow() {
}
});
// Set up network request monitoring
console.log('Setting up network request monitoring...');
session.defaultSession.webRequest.onBeforeRequest(
{ urls: ['*://*.onedrive.com/*', '*://*.1drv.com/*', '*://*.microsoftpersonalcontent.com/*'] },
(details, callback) => {
console.log('Intercepted request:', details.url);
// Check if this is a video request (typically .mov for Live Photos)
if (details.url.toLowerCase().includes('.mov') || details.url.toLowerCase().includes('mp4')) {
console.log('✓ Detected video URL:', details.url);
if (store) {
const destFolder = store.get('destFolder', '');
if (destFolder) {
// Extract item ID from URL
const urlObj = new URL(details.url);
const pathParts = urlObj.pathname.split('/');
const itemIndex = pathParts.findIndex(part => part === 'items');
const itemId = itemIndex !== -1 ? pathParts[itemIndex + 1] : null;
// Create filename with item ID and extension
const extension = details.url.toLowerCase().includes('.mov') ? '.mov' : '.mp4';
const filename = itemId ? `${itemId}${extension}` : `video_${Date.now()}${extension}`;
console.log('Downloading video as:', filename);
console.log('To folder:', destFolder);
downloadVideo(details.url, path.join(destFolder, filename));
} else {
console.warn('⚠ No destination folder configured');
}
} else {
console.error('⚠ Store not initialized');
}
}
callback({ cancel: false });
}
);
mainWindow.loadFile(path.join(__dirname, 'renderer/index.html'));
mainWindow.setTitle('OneDrive Photos');
console.log('Main window created and loaded');
}
function downloadVideo(url, filepath) {
console.log('Starting video download:', url);
console.log('Save path:', filepath);
const dir = path.dirname(filepath);
if (!fs.existsSync(dir)) {
console.log('Creating directory:', dir);
fs.mkdirSync(dir, { recursive: true });
}
const file = fs.createWriteStream(filepath);
https.get(url, (response) => {
console.log('Download started, status:', response.statusCode);
console.log('Content type:', response.headers['content-type']);
console.log('Content length:', response.headers['content-length']);
response.pipe(file);
file.on('finish', () => {
file.close();
console.log('✓ Video saved successfully:', filepath);
mainWindow.webContents.send('video-saved', {
filename: path.basename(filepath),
path: filepath
});
});
}).on('error', (err) => {
console.error('⚠ Download error:', err);
fs.unlink(filepath, () => {
console.log('Cleaned up failed download file');
});
mainWindow.webContents.send('video-save-error', err.message);
});
}
app.whenReady().then(createWindow);
@ -39,26 +114,34 @@ app.on('activate', () => {
}
});
// Modified IPC handlers
// IPC Handlers with debug logs
ipcMain.on('toggle-config', () => {
console.log('Toggle config panel requested');
mainWindow.webContents.send('toggle-config');
});
ipcMain.on('set-config', (event, config) => {
console.log('Saving configuration:', config);
if (store) {
store.set('destFolder', config.destFolder);
store.set('onedriveSource', config.onedriveSource);
console.log('Configuration saved:', config);
console.log('✓ Configuration saved successfully');
} else {
console.error('⚠ Store not initialized, cannot save config');
}
});
ipcMain.on('load-config', (event) => {
console.log('Loading configuration...');
if (store) {
const config = {
destFolder: store.get('destFolder', ''),
onedriveSource: store.get('onedriveSource', '')
};
console.log('Configuration loaded:', config);
event.reply('config-loaded', config);
} else {
console.error('⚠ Store not initialized, cannot load config');
}
});

View File

@ -2,36 +2,54 @@ const { ipcRenderer } = require('electron');
// Wait for webview to load
const webview = document.getElementById('main-content');
console.log('Setting up webview event listeners...');
webview.addEventListener('did-start-loading', () => {
console.log('Webview started loading');
});
webview.addEventListener('did-finish-load', () => {
console.log('Webview finished loading');
// Create and add the configuration button
console.log('Creating configuration button');
const button = document.createElement('button');
button.id = 'config-button';
button.innerHTML = '<i class="fas fa-cog"></i> Configuration';
document.body.appendChild(button);
console.log('Configuration button added to DOM');
// Add click handler to the dynamically created button
button.addEventListener('click', () => {
console.log('Configuration button clicked');
ipcRenderer.send('toggle-config');
});
});
webview.addEventListener('did-fail-load', (event) => {
console.error('Webview failed to load:', event);
});
// Configuration panel toggle
ipcRenderer.on('toggle-config', () => {
console.log('Toggling configuration panel');
const panel = document.getElementById('config-panel');
const isOpening = !panel.classList.contains('open');
panel.classList.toggle('open');
console.log(isOpening ? 'Panel opened' : 'Panel closed');
// Load saved config when panel opens
if (panel.classList.contains('open')) {
if (isOpening) {
console.log('Loading saved configuration...');
ipcRenderer.send('load-config');
}
});
// Folder selection
document.getElementById('select-folder').addEventListener('click', () => {
console.log('Folder selection requested');
ipcRenderer.send('select-folder');
});
ipcRenderer.on('folder-selected', (event, path) => {
console.log('Folder selected:', path);
document.getElementById('dest-folder').value = path;
});
@ -40,18 +58,46 @@ document.getElementById('config-form').addEventListener('submit', (event) => {
event.preventDefault();
const destFolder = document.getElementById('dest-folder').value;
const onedriveSource = document.getElementById('onedrive-source').value;
console.log('Saving configuration:', { destFolder, onedriveSource });
ipcRenderer.send('set-config', { destFolder, onedriveSource });
// Close the panel after saving
document.getElementById('config-panel').classList.remove('open');
});
// Close button handler
document.getElementById('close-config').addEventListener('click', () => {
document.getElementById('config-panel').classList.remove('open');
console.log('Configuration panel closed');
});
// Config loaded handler
ipcRenderer.on('config-loaded', (event, config) => {
console.log('Received saved configuration:', config);
document.getElementById('dest-folder').value = config.destFolder;
document.getElementById('onedrive-source').value = config.onedriveSource;
});
});
// Video handling
ipcRenderer.on('video-saved', (event, { filename, path }) => {
console.log('✓ Video saved successfully:', { filename, path });
showStatus(`Saved: ${filename}`);
});
ipcRenderer.on('video-save-error', (event, error) => {
console.error('⚠ Video save error:', error);
showStatus(`Error: ${error}`, true);
});
function showStatus(message, isError = false) {
console.log(`Showing status: ${message} (${isError ? 'error' : 'success'})`);
const statusDiv = document.getElementById('status-display') || createStatusDisplay();
statusDiv.textContent = message;
statusDiv.className = `show ${isError ? 'error' : 'success'}`;
// Reset animation
statusDiv.style.animation = 'none';
statusDiv.offsetHeight;
statusDiv.style.animation = null;
}
function createStatusDisplay() {
console.log('Creating status display element');
const div = document.createElement('div');
div.id = 'status-display';
document.body.appendChild(div);
return div;
}

View File

@ -186,3 +186,35 @@ body {
.submit-button:active {
background: #005a9e;
}
#status-display {
position: fixed;
bottom: 20px;
right: 20px;
padding: 10px 20px;
border-radius: 4px;
font-size: 14px;
z-index: 1002;
display: none;
}
#status-display.show {
display: block;
animation: fadeOut 3s forwards;
}
#status-display.success {
background: rgba(0, 120, 212, 0.9);
color: white;
}
#status-display.error {
background: rgba(232, 17, 35, 0.9);
color: white;
}
@keyframes fadeOut {
0% { opacity: 1; }
70% { opacity: 1; }
100% { opacity: 0; }
}