Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
2080642
dev: wrapped libc::getuid into a function
Sreehari425 Oct 10, 2025
fdaf55d
dev: refactored discover pipes
Sreehari425 Oct 10, 2025
c3ac3aa
dev: refactored unix auto connect
Sreehari425 Oct 10, 2025
be8432f
dev: merged retry tests to a single file
Sreehari425 Oct 10, 2025
3f70a02
dev: unfied async retry api
Sreehari425 Oct 10, 2025
98b0bea
docs: fixed mutliple named refrences
Sreehari425 Oct 11, 2025
0073910
changelogs: added unrealsed changelogs
Sreehari425 Oct 12, 2025
df8402e
examples: added example for tokio
Sreehari425 Oct 13, 2025
a68fa0f
dev: fixed tokio examples
Sreehari425 Oct 14, 2025
5103a60
chore: fixed typo in the update tokio example
Sreehari425 Oct 14, 2025
dfab29c
dev: remnaed utils to nonce
Sreehari425 Oct 15, 2025
25567c8
dev: fixed cargo docs
Sreehari425 Oct 15, 2025
07b23fc
dev: removed redadunt implentation of client.rs
Sreehari425 Oct 15, 2025
c28d256
Update import path for DiscordIpcClient in API reference
Sreehari425 Oct 15, 2025
b96d17b
dev: fixed api changes and updated the code base to use the new expli…
Sreehari425 Oct 15, 2025
78bfe61
dev: applied clippy suggetion
Sreehari425 Oct 16, 2025
b55be4e
dev: improved macros debug_println
Sreehari425 Oct 16, 2025
049fcbc
doc: updated genrate_nonce description
Sreehari425 Oct 16, 2025
38378f3
scripts: added clippy pedantic
Sreehari425 Oct 16, 2025
dc55605
ci : removed ci to run on every pr
Sreehari425 Oct 17, 2025
3eaa128
docs: updated docs (mostly fixed api which changed )
Sreehari425 Oct 17, 2025
0fe2fab
dev: added 'tmp' to env keys
Sreehari425 Oct 18, 2025
0a1cda4
chore: bump to v0.1.0-dev and update docs notes
Sreehari425 Oct 18, 2025
cc3a293
chore: bump the edition to 2024
Sreehari425 Oct 18, 2025
5b1e023
chore: updated the changelogs
Sreehari425 Oct 18, 2025
ad3db2d
chroe: applied suggetion from clippy and fmt
Sreehari425 Oct 18, 2025
14b02b7
Apply suggestion from @Copilot
Sreehari425 Oct 18, 2025
6068536
Apply suggestion from @Copilot
Sreehari425 Oct 18, 2025
ed2e0ab
Apply suggestion from @Copilot
Sreehari425 Oct 18, 2025
2838635
Apply suggestion from @Copilot
Sreehari425 Oct 18, 2025
6057a7f
Update src/macros.rs
Sreehari425 Oct 18, 2025
ec50ddb
Update scripts/clippy_god_mode.sh
Sreehari425 Oct 18, 2025
9648e1f
chore: fix docs and improve spacing
Sreehari425 Oct 18, 2025
d03e243
Update src/ipc/connection.rs
Sreehari425 Oct 18, 2025
3328e5a
Update README.md
Sreehari425 Oct 18, 2025
52e8ee8
Update src/nonce.rs
Sreehari425 Oct 18, 2025
58bb88a
chore : removed a extra whitespace
Sreehari425 Oct 18, 2025
28e06cd
Update src/ipc/connection.rs
Sreehari425 Oct 18, 2025
5865426
Update src/sync/client.rs
Sreehari425 Oct 18, 2025
0244691
Update src/sync/client.rs
Sreehari425 Oct 18, 2025
3ce87b3
Update src/ipc/connection.rs
Sreehari425 Oct 18, 2025
996049c
Update src/retry.rs
Sreehari425 Oct 18, 2025
9391ee9
Update src/sync/client.rs
Sreehari425 Oct 18, 2025
8967549
chore: cargo fmt
Sreehari425 Oct 18, 2025
e9dd98d
dev: added explicity type to closure return and formated the code
Sreehari425 Oct 18, 2025
918e51d
chore: enabled party feature for builder_all.rs
Sreehari425 Oct 18, 2025
400fb25
chore: bump the release of changelogs to 0.1.0-dev
Sreehari425 Oct 18, 2025
9e38d4c
Update README for presenceforge dependency version
Sreehari425 Oct 18, 2025
b007233
docs: bumped all the example version to 0.1.0-dev
Sreehari425 Oct 18, 2025
eb756b1
Update src/nonce.rs
Sreehari425 Oct 18, 2025
7cc6f3a
added docs to current_uuid function
Sreehari425 Oct 18, 2025
f285dd5
dev: used if-let syntax for consisteny
Sreehari425 Oct 18, 2025
c9a1fac
Update src/sync/client.rs
Sreehari425 Oct 18, 2025
fd81f49
Update src/ipc/connection.rs
Sreehari425 Oct 18, 2025
5275757
chore: cargo fmt
Sreehari425 Oct 18, 2025
e395524
Update src/ipc/connection.rs
Sreehari425 Oct 18, 2025
1b150b7
chore : minor typo fix
Sreehari425 Oct 18, 2025
83597f6
Trigger CI for PR
Sreehari425 Oct 18, 2025
611dbf2
chore: copied the ci from main
Sreehari425 Oct 18, 2025
ca90ba9
scripts: added tree script
Sreehari425 Oct 19, 2025
fabb33f
Lowered MSRV
Sreehari425 Oct 19, 2025
18efbca
dev: added allow collapasible if to conserve MSRV
Sreehari425 Oct 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/workflows/basic-ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name: CI


on:
push:
branches:
Expand All @@ -8,10 +9,6 @@ on:
branches:
- main
workflow_dispatch:

permissions:
contents: read

env:
CARGO_TERM_COLOR: always

Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "presenceforge"
version = "0.0.0"
edition = "2021"
version = "0.1.0-dev"
edition = "2024"
authors = ["Sreehari Anil <sreehari7102008@gmail.com>"]
description = "A library for Discord Rich Presence (IPC) integration"
readme = "README.md"
Expand Down
36 changes: 17 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ A Rust library for Discord Rich Presence that actually works without the headach

[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](https://github.com/Sreehari425/presenceforge#license)
[![Rust](https://img.shields.io/badge/rust-1.70+-blue.svg)](https://www.rust-lang.org)
![Crates.io Version](https://img.shields.io/crates/v/presenceforge)

> **Note**: This is currently in early development (v0.0.0). Things might break
> **Note**: This is currently in development (v0.1.0-dev). Things might break
> This is a learning/hobby project.
>
> ⚠️ FINAL WARNING: PresenceForge is a learning/hobby project. If you need production-ready Discord Rich Presence, use a mature library like pypresence, discord-rpc, or CraftPresence.
> Features and APIs may change in future versions.


## Documentation

Expand All @@ -26,44 +27,41 @@ A Rust library for Discord Rich Presence that actually works without the headach
## What Works

- [x] Linux and macOS (Unix domain sockets)
- [x] Windows support (named pipes) - needs testing
- [x] Windows support (named pipes)
- [x] Flatpak Discord support (automatic detection)
- [x] Basic Rich Presence activities
- [x] Activity builder pattern
- [x] Images, buttons, and timestamps
- [x] Async support with runtime-agnostic design
- [x] Support for tokio, async-std, and smol
- [x] Flexible pipe/socket selection
- [ ] Error handling could be better
- [ ] Party/lobby features (partial implementation only)

## Quick Start

Add PresenceForge to your `Cargo.toml`:

```toml
[dependencies]
presenceforge = { git = "https://github.com/Sreehari425/presenceforge" }
presenceforge = "0.1.0-dev"
```

For async support, add one of the runtime features:

```toml
[dependencies]
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["tokio-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["tokio-runtime"] }
# OR
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["async-std-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["async-std-runtime"] }
# OR
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["smol-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["smol-runtime"] }
```

> **Note**: Not published to crates.io yet. Use the git dependency for now.

### Basic Usage (Synchronous)

```rust
use presenceforge::{DiscordIpcClient, ActivityBuilder};

use presenceforge::ActivityBuilder;
use presenceforge::sync::DiscordIpcClient;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = DiscordIpcClient::new("your_client_id")?;
client.connect()?;
Expand Down Expand Up @@ -173,8 +171,8 @@ fn main() -> Result {
### Game Integration

```rust
use presenceforge::{ActivityBuilder, DiscordIpcClient};

use presenceforge::ActivityBuilder;
use presenceforge::sync::DiscordIpcClient;
let activity = ActivityBuilder::new()
.state("Forest Level")
.details("Fighting goblins")
Expand Down Expand Up @@ -276,7 +274,7 @@ ActivityBuilder::new()
.small_image("image_key") // Small image asset
.small_text("Hover text") // Small image hover text
.button("Label", "https://url") // Clickable button (max 2)
.party_size(1, 4) // Party size (current, max)
.party("id",1, 4) // Party size (current, max)
.build()
```

Expand Down Expand Up @@ -341,8 +339,8 @@ cargo run --example async_tokio --features tokio-runtime
PresenceForge uses the `Result` type for error handling:

```rust
use presenceforge::{DiscordIpcClient, DiscordIpcError};

use presenceforge::DiscordIpcError;
use presenceforge::sync::DiscordIpcClient;
match client.connect() {
Ok(_) => println!("Connected successfully!"),
Err(DiscordIpcError::ConnectionFailed) => {
Expand All @@ -358,7 +356,7 @@ match client.connect() {
- [ ] Party/lobby functionality (partial implementation)
- [x] Async support (tokio, async-std, and smol)
- [x] More comprehensive examples
- [ ] Publish to crates.io
- [x] Publish to crates.io
- [ ] CI/CD pipeline
- [x] Proper documentation
- [x] Connection retry logic with exponential backoff
Expand Down
34 changes: 34 additions & 0 deletions changelogs/0.1.0-dev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Unreleased

## [0.1.0-dev] - dev-release


### Added

#### Core Features

- Cross-platform Discord IPC support (Unix sockets for Linux/macOS, named pipes for Windows)
- Automatic discovery of Discord IPC pipes/sockets
- Flatpak Discord support with automatic detection
- Synchronous client API (`DiscordIpcClient`)
- Unified async API (`AsyncDiscordIpcClient`) with runtime-agnostic design
- Support for Tokio, async-std, and smol runtimes via feature flags
- Activity builder pattern for creating Rich Presence activities
- Full Discord Rich Presence field support (state, details, timestamps, assets, buttons, party)
- Basic input validation for all Discord field length limits
- Pipe discovery and custom path selection
- Connection timeout configuration
- Retry logic with exponential backoff (sync and async)
- Comprehensive error handling with categorization
- UUID v4-based cryptographic nonces for request tracking

#### Testing

- Unit tests for core functionality
- Integration tests for activity builder, serialization, error handling, IPC protocol, and retry logic

### Feature Flags

- `tokio-runtime` - Tokio async runtime support
- `async-std-runtime` - async-std runtime support
- `smol-runtime` - smol runtime support
15 changes: 8 additions & 7 deletions docs/ACTIVITY_BUILDER_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ S = Small Image (overlays large image in bottom-right corner)
#### Start Timestamp (Elapsed Time)

```rust
.start_timestamp_now().expect("timestamp") // Start counting from now
.start_timestamp_now()? // Start counting from now (returns Result)
// or
.start_timestamp(1234567890) // Unix timestamp (u64)
```
Expand Down Expand Up @@ -134,15 +134,15 @@ let end_time = now + 300;

### 6. **Party** (`party()`)

#### Note: Partialy tested feature
#### Note: Partially tested feature

```rust
.party("unique-party-id", 2, 4) // party_id, current_size, max_size
.party("unique-party-id", 2, 4) // id, current_size, max_size
```

- **Appears as:** "2 of 4" below the state text
- **Parameters:**
- `party_id`: Unique identifier for the party (string)
- `id`: Unique identifier for the party (string)
- `current_size`: Current number of players (u32)
- `max_size`: Maximum number of players (u32)
- **Use for:** Multiplayer games, voice channels, collaborative work
Expand Down Expand Up @@ -174,7 +174,7 @@ let end_time = now + 300;
### 8. **Secrets** (For "Ask to Join" and Spectate features)

> **⚠️ Feature Flag Required:** These methods require the `secrets` feature flag to be enabled.
> Add to your `Cargo.toml`: `presenceforge = { git = "...", features = ["secrets"] }`
> Add to your `Cargo.toml`: `presenceforge = { version = "0.1.0-dev", features = ["secrets"] }`

#### Note: untested feature

Expand Down Expand Up @@ -238,7 +238,8 @@ let end_time = now + 300;
Here's an activity using all fields:

```rust
use presenceforge::{ActivityBuilder, DiscordIpcClient};
use presenceforge::sync::DiscordIpcClient;
use presenceforge::ActivityBuilder;

let activity = ActivityBuilder::new()
// Text
Expand All @@ -252,7 +253,7 @@ let activity = ActivityBuilder::new()
.small_text("Level 42 Warrior")

// Time
.start_timestamp_now().expect("timestamp")
.start_timestamp_now()?

// Party
.party("party-12345", 3, 4)
Expand Down
29 changes: 11 additions & 18 deletions docs/API_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

API reference for PresenceForge (work-in-progress; APIs may change).

> ⚠️ **NOTE:** This feature is experimental/untested. Use at your own risk.
> **Note:** PresenceForge v0.1.0-dev is an early development release.
> It’s functional, but features may change or be incomplete.

## Table of Contents

Expand All @@ -27,7 +28,7 @@ The synchronous Discord IPC client for managing Rich Presence.
Creates a new Discord IPC client with automatic pipe discovery.

```rust
use presenceforge::DiscordIpcClient;
use presenceforge::sync::DiscordIpcClient;

let client = DiscordIpcClient::new("your_client_id")?;
```
Expand All @@ -49,7 +50,8 @@ let client = DiscordIpcClient::new("your_client_id")?;
Creates a new Discord IPC client with custom pipe configuration.

```rust
use presenceforge::{DiscordIpcClient, PipeConfig};
use presenceforge::PipeConfig;
use presenceforge::sync::DiscordIpcClient;

// Auto-discovery (equivalent to ::new())
let client = DiscordIpcClient::new_with_config("client_id", None)?;
Expand Down Expand Up @@ -310,28 +312,19 @@ Adds a button to the Rich Presence (max 2 buttons).

### Party Methods

#### `party_id(self, id: impl Into<String>) -> Self`

Sets the party ID (for grouping players).

```rust
.party_id("party_12345")
```

---

#### `party_size(self, current: i32, max: i32) -> Self`
#### `party(self, id: impl Into<String>, current_size: u32, max_size: u32) -> Self`

Sets the party size display.
Sets the party information (ID and size) in a single method.

```rust
.party_size(2, 4) // Shows "2 of 4"
.party("party_12345", 2, 4) // Shows "2 of 4"
```

**Parameters:**

- `current` - Current number of players
- `max` - Maximum number of players
- `id` - Unique party identifier for grouping players
- `current_size` - Current number of players
- `max_size` - Maximum number of players

---

Expand Down
26 changes: 14 additions & 12 deletions docs/ASYNC_RUNTIMES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Async Runtimes Guide

> ⚠️ **NOTE:** This feature is experimental/untested. Use at your own risk.
> **Note:** PresenceForge v0.1.0-dev is an early development release.
> It’s functional, but features may change or be incomplete.

## Table of Contents

Expand Down Expand Up @@ -62,13 +63,13 @@ Add to your `Cargo.toml` with **one** of these feature flags:
```toml
[dependencies]
# For Tokio
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["tokio-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["tokio-runtime"] }

# For async-std
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["async-std-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["async-std-runtime"] }

# For smol
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["smol-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["smol-runtime"] }
```

**This exact code works with all three runtimes:**
Expand All @@ -89,7 +90,7 @@ async fn setup_presence() -> Result {
let activity = ActivityBuilder::new()
.state("Playing async")
.details("Runtime-agnostic!")
.start_timestamp_now().expect("timestamp")
.start_timestamp_now()?
.build();

// Set activity
Expand Down Expand Up @@ -139,7 +140,7 @@ Add to your `Cargo.toml`:

```toml
[dependencies]
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["tokio-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["tokio-runtime"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
```

Expand All @@ -162,7 +163,7 @@ async fn main() -> Result {
let activity = ActivityBuilder::new()
.state("Playing async")
.details("Using Tokio")
.start_timestamp_now().expect("timestamp")
.start_timestamp_now()?
.build();

// Set activity
Expand Down Expand Up @@ -211,7 +212,7 @@ async fn main() -> Result {
let activity = ActivityBuilder::new()
.state(format!("Update #{}", counter))
.details("Tokio Background Task")
.start_timestamp_now().expect("timestamp")
.start_timestamp_now()?
.build();

let mut client = presence_client.lock().await;
Expand Down Expand Up @@ -319,7 +320,7 @@ async-std provides an async API similar to the standard library.

```toml
[dependencies]
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["async-std-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["async-std-runtime"] }
async-std = { version = "1", features = ["attributes"] }
```

Expand Down Expand Up @@ -418,7 +419,7 @@ smol is a small and fast async runtime.

```toml
[dependencies]
presenceforge = { git = "https://github.com/Sreehari425/presenceforge", features = ["smol-runtime"] }
presenceforge = { version = "0.1.0-dev", features = ["smol-runtime"] }
smol = "2"
```

Expand All @@ -441,7 +442,7 @@ fn main() -> Result {
let activity = ActivityBuilder::new()
.state("Playing async")
.details("Using smol")
.start_timestamp_now().expect("timestamp")
.start_timestamp_now()?
.build();

client.set_activity(&activity).await?;
Expand Down Expand Up @@ -639,7 +640,8 @@ async fn main() -> Result {
### Sync Code

```rust
use presenceforge::{DiscordIpcClient, ActivityBuilder};
use presenceforge::ActivityBuilder;
use presenceforge::sync::DiscordIpcClient;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = DiscordIpcClient::new("client_id")?;
Expand Down
Loading