Make project Windows-only compatible
- Remove xcap dependency (Linux-focused) - Add Windows crate with Win32 APIs support - Implement native Windows window capture using GetForegroundWindow - Implement process name retrieval using GetModuleBaseNameW - Update all paths to use Windows backslash separators - Update README to specify Windows-only platform - Add Windows badge and requirements - Update installation instructions for PowerShell - Add error handling for non-Windows platforms 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9c46beb11c
commit
9eea0199bb
12
Cargo.toml
12
Cargo.toml
@ -3,7 +3,7 @@ name = "activity-tracker"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["Activity Tracker Team"]
|
||||
description = "Backend de suivi d'activité pour reconstruire l'historique de travail"
|
||||
description = "Backend de suivi d'activité pour reconstruire l'historique de travail (Windows uniquement)"
|
||||
|
||||
[dependencies]
|
||||
# Core dependencies
|
||||
@ -17,7 +17,15 @@ env_logger = "0.11"
|
||||
screenshots = "0.6"
|
||||
image = "0.24"
|
||||
webp = "0.2"
|
||||
xcap = "0.0.10"
|
||||
|
||||
# Windows APIs
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.52", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_UI_WindowsAndMessaging",
|
||||
"Win32_System_Threading",
|
||||
"Win32_System_ProcessStatus",
|
||||
] }
|
||||
|
||||
# Storage (SQLite + Encryption)
|
||||
rusqlite = { version = "0.31", features = ["bundled"] }
|
||||
|
||||
36
README.md
36
README.md
@ -3,12 +3,14 @@
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
**Activity Tracker** est un système de suivi d'activité conçu pour aider les utilisateurs à reconstruire leur historique de travail via une analyse automatisée des actions numériques.
|
||||
**Activity Tracker** est un système de suivi d'activité **Windows uniquement** conçu pour aider les utilisateurs à reconstruire leur historique de travail via une analyse automatisée des actions numériques.
|
||||
|
||||
## Caractéristiques (MVP)
|
||||
|
||||
- **Capture passive** : Screenshots toutes les 5 minutes + métadonnées fenêtres
|
||||
- **Capture passive** : Screenshots toutes les 5 minutes + métadonnées fenêtres Windows
|
||||
- **API Windows native** : Utilise GetForegroundWindow et les APIs Win32
|
||||
- **Stockage sécurisé** : Base SQLite avec chiffrement AES-256-GCM
|
||||
- **Analyse intelligente** : Classification automatique en 5 catégories
|
||||
- **Rapports journaliers** : Export JSON avec statistiques détaillées
|
||||
@ -18,28 +20,27 @@
|
||||
|
||||
### Prérequis
|
||||
|
||||
- Rust 1.70+
|
||||
- Cargo
|
||||
- SQLite3
|
||||
- **Windows 10 ou supérieur** (requis)
|
||||
- Rust 1.70+ et Cargo (installer via [rustup](https://rustup.rs/))
|
||||
- SQLite3 (inclus automatiquement via Cargo)
|
||||
|
||||
### Compilation
|
||||
|
||||
```bash
|
||||
```powershell
|
||||
git clone https://gitea.legion-muyue.fr/Muyue/activity-tracker.git
|
||||
cd activity-tracker
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
Le binaire compilé sera disponible dans `target/release/activity-tracker`.
|
||||
Le binaire compilé sera disponible dans `target\release\activity-tracker.exe`.
|
||||
|
||||
### Installation système
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
sudo cp target/release/activity-tracker /usr/local/bin/
|
||||
```powershell
|
||||
# Ajoutez le répertoire à votre PATH ou copiez le binaire
|
||||
copy target\release\activity-tracker.exe C:\Program Files\ActivityTracker\
|
||||
|
||||
# Ou ajoutez le chemin à votre PATH
|
||||
export PATH=$PATH:$(pwd)/target/release
|
||||
# Ou utilisez directement depuis le dossier target\release
|
||||
```
|
||||
|
||||
## Utilisation
|
||||
@ -173,7 +174,7 @@ inactivity_threshold = 600 # 10 minutes
|
||||
[storage]
|
||||
max_storage_mb = 500
|
||||
retention_days = 30
|
||||
db_path = "data/activity_tracker.db"
|
||||
db_path = "data\\activity_tracker.db"
|
||||
|
||||
[ai]
|
||||
categories = ["Development", "Meeting", "Research", "Design", "Other"]
|
||||
@ -277,11 +278,12 @@ Pattern::new(vec!["slack", "discord", "telegram"], 0.9),
|
||||
- [ ] **Détection audio** de réunions
|
||||
- [ ] **Intégrations** (Trello, Jira, calendriers)
|
||||
|
||||
## Problèmes connus
|
||||
## Plateforme supportée
|
||||
|
||||
- **Linux** : L'accès aux métadonnées de fenêtres nécessite X11 (Wayland non supporté)
|
||||
- **macOS** : Nécessite autorisations Accessibilité (voir documentation officielle)
|
||||
- **Windows** : Fonctionne avec les privilèges standards
|
||||
- **Windows uniquement** : Fonctionne avec Windows 10 et supérieur
|
||||
- Utilise les APIs Windows natives pour la capture de fenêtres
|
||||
- Aucune autorisation spéciale requise (privilèges standards suffisants)
|
||||
- Les plateformes Linux et macOS ne sont **pas supportées**
|
||||
|
||||
## Contribution
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Activity Tracker MVP Configuration
|
||||
# Activity Tracker MVP Configuration (Windows uniquement)
|
||||
|
||||
[capture]
|
||||
interval_seconds = 300 # 5 minutes (as per MVP spec)
|
||||
@ -8,7 +8,7 @@ inactivity_threshold = 600 # 10 minutes
|
||||
[storage]
|
||||
max_storage_mb = 500
|
||||
retention_days = 30
|
||||
db_path = "data/activity_tracker.db"
|
||||
db_path = "data\\activity_tracker.db" # Chemin Windows
|
||||
|
||||
[ai]
|
||||
categories = ["Development", "Meeting", "Research", "Design", "Other"]
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
/// Window metadata extraction
|
||||
/// Window metadata extraction (Windows uniquement)
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::error::{AppError, Result};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use xcap::Window;
|
||||
#[cfg(windows)]
|
||||
use windows::{
|
||||
core::PWSTR,
|
||||
Win32::Foundation::{HWND, MAX_PATH},
|
||||
Win32::System::ProcessStatus::GetModuleBaseNameW,
|
||||
Win32::System::Threading::{OpenProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_READ},
|
||||
Win32::UI::WindowsAndMessaging::{GetForegroundWindow, GetWindowTextW, GetWindowThreadProcessId},
|
||||
};
|
||||
|
||||
/// Window metadata structure
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -81,39 +87,72 @@ impl WindowMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get metadata for the currently active window
|
||||
#[cfg(target_os = "linux")]
|
||||
/// Get metadata for the currently active window (Windows implementation)
|
||||
#[cfg(windows)]
|
||||
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
||||
let windows = Window::all()
|
||||
.map_err(|e| AppError::Capture(format!("Failed to get windows: {}", e)))?;
|
||||
unsafe {
|
||||
// Get the foreground window handle
|
||||
let hwnd = GetForegroundWindow();
|
||||
if hwnd.0 == 0 {
|
||||
return Ok(WindowMetadata::inactive());
|
||||
}
|
||||
|
||||
// Find the active/focused window
|
||||
// For MVP, we'll use the first window as a fallback
|
||||
let active_window = windows.first()
|
||||
.ok_or_else(|| AppError::Capture("No windows found".to_string()))?;
|
||||
// Get window title
|
||||
let mut title_buffer = [0u16; 512];
|
||||
let title_len = GetWindowTextW(hwnd, &mut title_buffer);
|
||||
let title = if title_len > 0 {
|
||||
String::from_utf16_lossy(&title_buffer[..title_len as usize])
|
||||
} else {
|
||||
"Unknown".to_string()
|
||||
};
|
||||
|
||||
// Get process ID
|
||||
let mut process_id: u32 = 0;
|
||||
GetWindowThreadProcessId(hwnd, Some(&mut process_id));
|
||||
|
||||
// Get process name
|
||||
let process_name = get_process_name(process_id).unwrap_or_else(|| "unknown".to_string());
|
||||
|
||||
Ok(WindowMetadata {
|
||||
title: active_window.title().to_string(),
|
||||
process_name: active_window.app_name().to_string(),
|
||||
process_id: active_window.id() as u32,
|
||||
title,
|
||||
process_name,
|
||||
process_id,
|
||||
is_active: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Get metadata for the currently active window (Windows implementation)
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
||||
// Simplified implementation for MVP
|
||||
// In production, would use Windows API to get active window
|
||||
Ok(WindowMetadata::unknown())
|
||||
/// Get process name from process ID (Windows)
|
||||
#[cfg(windows)]
|
||||
fn get_process_name(process_id: u32) -> Option<String> {
|
||||
unsafe {
|
||||
let process_handle = OpenProcess(
|
||||
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
||||
false,
|
||||
process_id,
|
||||
).ok()?;
|
||||
|
||||
let mut name_buffer = [0u16; MAX_PATH as usize];
|
||||
let name_len = GetModuleBaseNameW(
|
||||
process_handle,
|
||||
None,
|
||||
&mut name_buffer,
|
||||
);
|
||||
|
||||
if name_len > 0 {
|
||||
Some(String::from_utf16_lossy(&name_buffer[..name_len as usize]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get metadata for the currently active window (macOS implementation)
|
||||
#[cfg(target_os = "macos")]
|
||||
/// Fallback for non-Windows platforms (not supported)
|
||||
#[cfg(not(windows))]
|
||||
pub fn get_active_window_metadata() -> Result<WindowMetadata> {
|
||||
// Simplified implementation for MVP
|
||||
// In production, would use macOS APIs to get active window
|
||||
Ok(WindowMetadata::unknown())
|
||||
Err(AppError::Capture(
|
||||
"This application only supports Windows".to_string()
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -77,7 +77,7 @@ impl Config {
|
||||
storage: StorageConfig {
|
||||
max_storage_mb: 500,
|
||||
retention_days: 30,
|
||||
db_path: "data/activity_tracker.db".to_string(),
|
||||
db_path: "data\\activity_tracker.db".to_string(),
|
||||
},
|
||||
ai: AiConfig {
|
||||
categories: vec![
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user