+16
RUST/.env.example
+16
RUST/.env.example
···
1
+
# AT Protocol Configuration (Required)
2
+
ATP_HANDLE=your-handle.bsky.social
3
+
ATP_PASSWORD=your-app-password
4
+
ATP_PDS_URL=https://bsky.social
5
+
ATP_DID=did:plc:your-did
6
+
7
+
# Google Calendar API (Optional - for Google imports)
8
+
GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com
9
+
GOOGLE_CLIENT_SECRET=your-google-client-secret
10
+
11
+
# Microsoft Outlook API (Optional - for Outlook imports)
12
+
OUTLOOK_CLIENT_ID=your-outlook-client-id
13
+
OUTLOOK_CLIENT_SECRET=your-outlook-client-secret
14
+
15
+
# Logging Configuration (Optional)
16
+
RUST_LOG=info
+101
RUST/.gitignore
+101
RUST/.gitignore
···
1
+
# Rust build artifacts
2
+
/target/
3
+
**/*.rs.bk
4
+
*.pdb
5
+
6
+
# Cargo
7
+
Cargo.lock
8
+
.cargo/
9
+
10
+
# IDE files
11
+
.vscode/
12
+
.idea/
13
+
*.swp
14
+
*.swo
15
+
16
+
# OS files
17
+
.DS_Store
18
+
.DS_Store?
19
+
._*
20
+
.Spotlight-V100
21
+
.Trashes
22
+
ehthumbs.db
23
+
Thumbs.db
24
+
25
+
# Environment and secrets
26
+
.env
27
+
.env.*
28
+
!.env.example
29
+
*.key
30
+
*.pem
31
+
*.p12
32
+
*.pfx
33
+
34
+
# Authentication tokens and credentials
35
+
google_credentials.json
36
+
outlook_credentials.json
37
+
auth_tokens.json
38
+
.credentials/
39
+
40
+
# Database files
41
+
*.db
42
+
*.sqlite
43
+
*.sqlite3
44
+
45
+
# Log files
46
+
*.log
47
+
logs/
48
+
log/
49
+
50
+
# Cache and temporary files
51
+
*.tmp
52
+
*.temp
53
+
cache/
54
+
.cache/
55
+
56
+
# Test artifacts
57
+
test-results/
58
+
coverage/
59
+
*.profraw
60
+
61
+
# Documentation build
62
+
/docs/build/
63
+
/docs/site/
64
+
65
+
# Local configuration
66
+
config.local.*
67
+
local.toml
68
+
69
+
# Backup files
70
+
*.bak
71
+
*.backup
72
+
*~
73
+
74
+
# Runtime data
75
+
pids
76
+
*.pid
77
+
*.seed
78
+
*.pid.lock
79
+
80
+
# Coverage directory used by tools like istanbul
81
+
coverage/
82
+
83
+
# Optional npm cache directory
84
+
.npm
85
+
86
+
# Optional eslint cache
87
+
.eslintcache
88
+
89
+
# Editor directories and files
90
+
.vscode/*
91
+
!.vscode/settings.json
92
+
!.vscode/tasks.json
93
+
!.vscode/launch.json
94
+
!.vscode/extensions.json
95
+
*.code-workspace
96
+
97
+
# Local History for Visual Studio Code
98
+
.history/
99
+
100
+
# Built Visual Studio Code Extensions
101
+
*.vsix
+1
-1
RUST/src/auth.rs
+1
-1
RUST/src/auth.rs
+9
-4
RUST/src/dedup.rs
+9
-4
RUST/src/dedup.rs
···
243
243
#[cfg(test)]
244
244
mod tests {
245
245
use super::*;
246
-
use chrono::Utc;
247
246
248
247
fn create_test_event(name: &str, source: &str) -> ExternalEvent {
248
+
let fixed_time = chrono::DateTime::parse_from_rfc3339("2024-01-01T12:00:00Z")
249
+
.unwrap()
250
+
.with_timezone(&chrono::Utc);
251
+
249
252
ExternalEvent {
250
253
id: "test-id".to_string(),
251
254
name: name.to_string(),
252
255
description: None,
253
-
starts_at: Some(Utc::now()),
256
+
starts_at: Some(fixed_time),
254
257
ends_at: None,
255
258
location: None,
256
259
attendees: vec![],
257
-
created_at: Utc::now(),
258
-
updated_at: Utc::now(),
260
+
created_at: fixed_time,
261
+
updated_at: fixed_time,
259
262
source: source.to_string(),
260
263
source_url: None,
264
+
url: None,
261
265
is_all_day: false,
262
266
status: "confirmed".to_string(),
263
267
visibility: "public".to_string(),
268
+
metadata: serde_json::Value::Null,
264
269
}
265
270
}
266
271
+2
-1
RUST/src/import/outlook.rs
+2
-1
RUST/src/import/outlook.rs
···
435
435
#[test]
436
436
fn test_convert_graph_datetime() {
437
437
let graph_dt = GraphDateTime {
438
-
date_time: "2025-06-01T10:00:00.0000000".to_string(),
438
+
date_time: "2025-06-01T10:00:00Z".to_string(),
439
439
time_zone: "UTC".to_string(),
440
440
};
441
441
···
443
443
// that Microsoft Graph returns
444
444
let result = convert_graph_datetime(&graph_dt);
445
445
assert!(result.is_ok());
446
+
assert_eq!(result.unwrap(), "2025-06-01T10:00:00+00:00");
446
447
}
447
448
448
449
#[test]
+1
-1
RUST/src/lib.rs
+1
-1
RUST/src/lib.rs
···
19
19
//! #[tokio::main]
20
20
//! async fn main() -> anyhow::Result<()> {
21
21
//! let config = Config::from_env()?;
22
-
//! let importer = CalendarImporter::new(config).await?;
22
+
//! let mut importer = CalendarImporter::new(config).await?;
23
23
//!
24
24
//! // Import from Google Calendar
25
25
//! let count = importer.import_google_calendar().await?;
+6
-6
RUST/src/transform/mod.rs
+6
-6
RUST/src/transform/mod.rs
···
301
301
302
302
#[test]
303
303
fn test_to_at_event_basic() {
304
-
let external = ExternalEvent::new("test-id", "Test Event")
305
-
.with_description("Test description");
304
+
let external = ExternalEvent::new("test-id".to_string(), "Test Event".to_string())
305
+
.with_description("Test description".to_string());
306
306
307
307
let result = to_at_event(&external);
308
308
assert!(result.is_ok());
···
321
321
322
322
#[test]
323
323
fn test_determine_event_mode_virtual() {
324
-
let external = ExternalEvent::new("test", "Test")
325
-
.with_location("https://zoom.us/j/123456789");
324
+
let external = ExternalEvent::new("test".to_string(), "Test".to_string())
325
+
.with_location("https://zoom.us/j/123456789".to_string());
326
326
327
327
let mode = determine_event_mode(&external);
328
328
assert_eq!(mode, Some(event_mode::VIRTUAL.to_string()));
···
330
330
331
331
#[test]
332
332
fn test_determine_event_status_cancelled() {
333
-
let external = ExternalEvent::new("test", "Test")
334
-
.with_status("cancelled");
333
+
let external = ExternalEvent::new("test".to_string(), "Test".to_string())
334
+
.with_status("cancelled".to_string());
335
335
336
336
let status = determine_event_status(&external);
337
337
assert_eq!(status, Some(event_status::CANCELLED.to_string()));