megalib

A Rust client library for the MEGA cloud storage service.
This library provides a clean, asynchronous Rust interface for interacting with MEGA, supporting authentication, filesystem access, and file management.
Features
-
Authentication:
- Full registration flow (account creation + email verification)
- Login (supports both v1 and v2/PBKDF2 authentication)
- Session management and caching
- Password Change (
change_password)
-
Filesystem:
- Fetch filesystem tree
- List files and directories
- Get node information (
stat)
- Create directories (
mkdir)
- Remove files/folders (
rm)
- Rename files/folders (
rename)
- Move files/folders (
mv)
- Access Public Folders (
open_folder)
-
File Transfer:
- File upload with optional resume support
- File download with resume support
- Parallel transfer workers support
- Progress callbacks for monitoring transfers
- Text/Video/Image streaming support
- Automatic thumbnail generation on upload
- Public link generation (
export, export_many)
- Proxy support (HTTP/HTTPS/SOCKS5)
-
Node Operations:
- Get node by handle
- Check ancestor relationships
- Check write permissions
-
Sharing & Contacts:
- Share folders with other users (
share_folder)
- List contacts (
list_contacts)
- Access incoming shared folders
Installation
Add this to your Cargo.toml:
[dependencies]
megalib = "0.1.0"
tokio = { version = "1", features = ["full"] }
Usage Examples
1. Authentication
Registration
use megalib::session::registration::{register, verify_registration};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let state = register("newuser@example.com", "MySecretPassword", "New User").await?;
println!("Registration initiated! Check your email for the confirmation link.");
let state_str = state.serialize();
let link = "https://mega.nz/#confirm..."; let restored_state = megalib::session::registration::RegistrationState::deserialize(&state_str)?;
verify_registration(&restored_state, link).await?;
println!("Account verified successfully!");
Ok(())
}
Login (Standard)
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let session = Session::login("user@example.com", "password").await?;
println!("Logged in as: {}", session.email);
Ok(())
}
Login (With Proxy)
The library supports HTTP, HTTPS, and SOCKS5 proxies.
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let session = Session::login_with_proxy(
"user@example.com",
"password",
"socks5://127.0.0.1:9050"
).await?;
println!("Logged in via proxy as: {}", session.email);
Ok(())
}
Change Password
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "old_password").await?;
session.change_password("new_secure_password").await?;
println!("Password changed successfully!");
Ok(())
}
2. Session Management
Session Caching
Save your session to avoid logging in every time.
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = match Session::load("session.json").await? {
Some(s) => s,
None => {
let s = Session::login("user@example.com", "password").await?;
s.save("session.json")?;
s
}
};
session.refresh().await?;
Ok(())
}
Loading Session with Proxy
When loading a cached session, you can optionally specify a proxy to use for the restored session.
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = match Session::load_with_proxy("session.json", "http://proxy:8080").await? {
Some(s) => s,
None => {
let s = Session::login_with_proxy("user@example.com", "password", "http://proxy:8080").await?;
s.save("session.json")?;
s
}
};
session.refresh().await?;
Ok(())
}
3. Filesystem Operations
List Files and Get Info
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
let nodes = session.list("/", false)?;
for node in nodes {
println!("- {} ({} bytes)", node.name, node.size);
}
if let Some(node) = session.stat("/Root/Documents/Report.pdf") {
println!("Found file: {}", node.name);
}
Ok(())
}
File Management (mkdir, mv, rename, rm)
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
session.mkdir("/Root/Project").await?;
session.mv("/Root/draft.txt", "/Root/Project").await?;
session.rename("/Root/Project/draft.txt", "final.txt").await?;
session.rm("/Root/Project/old_notes.txt").await?;
Ok(())
}
Storage Quota
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
let quota = session.quota().await?;
println!("Used: {} / {} bytes ({:.1}%)",
quota.used, quota.total, quota.usage_percent());
println!("Free: {} bytes", quota.free());
Ok(())
}
Node Type Checks
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
for node in session.list("/Root", true)? {
if node.is_file() {
println!("File: {} ({} bytes)", node.name, node.size);
} else if node.is_folder() {
println!("Folder: {}/", node.name);
}
if node.is_exported() {
if let Some(url) = node.get_link(true) {
println!(" Public link: {}", url);
}
}
}
Ok(())
}
Node Operations
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
if let Some(node) = session.get_node_by_handle("ABC123xyz") {
println!("Found: {}", node.name);
}
let file = session.stat("/Root/Documents/report.pdf").unwrap();
let folder = session.stat("/Root/Documents").unwrap();
if session.node_has_ancestor(file, folder) {
println!("File is inside Documents folder");
}
if file.is_writable() {
println!("Can modify this file");
}
Ok(())
}
List Contacts
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
for contact in session.list_contacts() {
println!("Contact: {} ({})", contact.name, contact.handle);
}
Ok(())
}
4. File Transfer
Upload
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
let node = session.upload("local_file.txt", "/Root/Project").await?;
println!("Uploaded: {}", node.name);
Ok(())
}
Upload with Thumbnail Generation
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
session.enable_previews(true);
let node = session.upload("photo.jpg", "/Root/Photos").await?;
println!("Uploaded with thumbnail: {}", node.name);
Ok(())
}
Download
use megalib::Session;
use std::fs::File;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
if let Some(node) = session.stat("/Root/Project/final.txt") {
let mut file = File::create("downloaded_final.txt")?;
session.download(node, &mut file).await?;
}
Ok(())
}
Download Resume Support
Enable resumption of interrupted downloads.
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
session.set_resume(true);
session.set_workers(4);
if let Some(node) = session.stat("/Root/LargeVideo.mp4") {
session.download_to_file(&node, "video.mp4").await?;
}
Ok(())
}
Upload with Resume Support
For large uploads that may be interrupted:
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
session.set_workers(4);
let node = session.upload_resumable("large_file.zip", "/Root").await?;
println!("Uploaded: {}", node.name);
Ok(())
}
Progress Callbacks
Monitor transfer progress:
use megalib::{Session, progress::TransferProgress};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
session.watch_status(Box::new(|progress: &TransferProgress| {
println!("{:.1}% - {}", progress.percent(), progress.filename);
true }));
session.upload("file.txt", "/Root").await?;
Ok(())
}
5. Sharing
Export Public Link
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
let url = session.export("/Root/Project/final.txt").await?;
println!("Public Download Link: {}", url);
Ok(())
}
Export Multiple Files
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
let paths = &["/Root/doc1.pdf", "/Root/doc2.pdf", "/Root/image.png"];
let results = session.export_many(paths).await?;
for (path, url) in results {
println!("{} -> {}", path, url);
}
Ok(())
}
Get Existing Export Link
use megalib::Session;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut session = Session::login("user@example.com", "password").await?;
session.refresh().await?;
if let Some(node) = session.stat("/Root/shared_file.txt") {
if let Some(url) = node.get_link(true) {
println!("Existing link: {}", url);
}
if let Some(key) = node.get_key() {
println!("Node key: {}", key);
}
}
Ok(())
}
Share a folder
Share a folder with another MEGA user.
session.share_folder("FOLDER_HANDLE", "friend@example.com", 0).await?;
Access levels:
0: Read-only
1: Read/Write
2: Full Access
6. Public Links & Folders (No Login Required)
You can interact with public MEGA links without logging in.
Download a Public File
use megalib::public::download_public_file;
use std::fs::File;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut file = File::create("shared_file.zip")?;
download_public_file("https://mega.nz/file/ABC123#key...", &mut file).await?;
println!("Download complete!");
Ok(())
}
Browse and Download from Public Folder
use megalib::public::open_folder;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let folder = open_folder("https://mega.nz/folder/XYZ789#key...").await?;
for node in folder.list("/", true) {
println!("Found: {} ({} bytes)", node.name, node.size);
if node.name == "image.jpg" {
let mut file = std::fs::File::create("image.jpg")?;
folder.download(node, &mut file).await?;
}
}
Ok(())
}
Running Examples
Clone the repository and run the included examples:
cargo run --example register -- --email test@example.com --password TestPass123 --name "Test User"
cargo run --example verify -- "https://mega.nz/#confirm..."
cargo run --example passwd -- --email test@example.com --old OldPass --new NewPass
cargo run --example ls -- --email test@example.com --password TestPass123 --path /Root/
cargo run --example cached_session -- --email test@example.com --password TestPass123
cargo run --example mkdir -- --email test@example.com --password TestPass123 /Root/NewFolder
cargo run --example mv -- --email test@example.com --password TestPass123 /Root/file.txt /Root/NewFolder/
cargo run --example rename -- --email test@example.com --password TestPass123 /Root/file.txt "new_name.txt"
cargo run --example rm -- --email test@example.com --password TestPass123 /Root/delete_me.txt
cargo run --example stat -- --email test@example.com --password TestPass123 /Root/file.txt
cargo run --example upload -- --email test@example.com --password TestPass123 local_file.txt /Root/
cargo run --example upload_resume -- --email test@example.com --password TestPass123 large_file.zip /Root/
cargo run --example download -- --email test@example.com --password TestPass123 /Root/file.zip ./file.zip
cargo run --example download_resume -- --email test@example.com --password TestPass123 /Root/file.zip ./file.zip
cargo run --example export -- --email test@example.com --password TestPass123 /Root/file.txt
cargo run --example share -- --email test@example.com --password TestPass123 --folder /Root/Documents --recipient friend@example.com --level 0
cargo run --example download_public -- "https://mega.nz/file/..."
cargo run --example folder -- "https://mega.nz/folder/..."
Acknowledgements
This project is based on the work of megatools by Ondřej Jirman, which provided the foundational understanding of the MEGA API protocol and served as a reference implementation.
License
This project is licensed under the GNU General Public License v2.0 (GPLv2) - see the license file for details.
Disclaimer
This is an unofficial client library and is not affiliated with, associated with, authorized by, endorsed by, or in any way officially connected with Mega Limited.