Skip to content

Commit 591d25c

Browse files
feat: some fixes, features, and README
1 parent fe6ce75 commit 591d25c

File tree

5 files changed

+90
-5
lines changed

5 files changed

+90
-5
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
MATRIX_HOMESERVER=https://matrix.org
22
MATRIX_USERNAME=your_username
33
MATRIX_PASSWORD=your_password
4+
IGNORE_BRIDGE_USERS=false

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Matrix Wiki Link Bot
2+
3+
A simple Matrix bot that listens for commands starting with `.wiki` and responds with links from a configured JSON store.
4+
5+
## Configuration
6+
7+
The bot is configured via environment variables.
8+
9+
| Variable | Description | Default |
10+
|----------|-------------|---------|
11+
| `MATRIX_HOMESERVER` | The URL of your Matrix homeserver (e.g., `https://matrix.org`). | |
12+
| `MATRIX_USERNAME` | The bot's Matrix username. | |
13+
| `MATRIX_PASSWORD` | The bot's Matrix password. | |
14+
| `IGNORE_BRIDGE_USERS`| If set to `true`, the bot will ignore messages from senders whose MXID starts with `@discord_`. | `false` |
15+
16+
## Usage
17+
18+
### Docker
19+
20+
1. Copy `docker-compose.example.yml` to `docker-compose.yml` and `links.json` to a local file.
21+
2. Update the environment variables in `docker-compose.yml`.
22+
3. Populate `links.json` with your key-value pairs.
23+
4. Run the bot:
24+
25+
```bash
26+
docker-compose up -d
27+
```
28+
29+
### Local Development
30+
31+
1. Copy `.env.example` to `.env`.
32+
2. Update `.env` with your credentials.
33+
3. Run the bot:
34+
35+
```bash
36+
cargo run
37+
```
38+
39+
## Commands
40+
41+
- `.wiki list`: Lists all available wiki keys.
42+
- `.wiki <term>`: Fetches the link associated with `<term>` from the `links.json` file.

docker-compose.example.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ services:
55
- MATRIX_HOMESERVER=https://matrix.org
66
- MATRIX_USERNAME=your_username
77
- MATRIX_PASSWORD=your_password
8+
- IGNORE_BRIDGE_USERS=false
89
volumes:
910
- ./links.json:/usr/local/bin/links.json
1011
restart: unless-stopped

src/links.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ impl LinkStore {
1717
pub fn get(&self, key: &str) -> Option<&String> {
1818
self.links.get(key)
1919
}
20+
21+
pub fn list_keys(&self) -> Vec<String> {
22+
let mut keys: Vec<String> = self.links.keys().cloned().collect();
23+
keys.sort();
24+
keys
25+
}
2026
}
2127

2228
#[cfg(test)]

src/main.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,63 @@ async fn main() -> Result<()> {
3737

3838
client.matrix_auth().login_username(&username, &password).await?;
3939

40+
let ignore_bridge_users = env::var("IGNORE_BRIDGE_USERS")
41+
.map(|v| v.to_lowercase() == "true")
42+
.unwrap_or(false);
43+
44+
let start_time = std::time::SystemTime::now()
45+
.duration_since(std::time::UNIX_EPOCH)
46+
.expect("Time went backwards")
47+
.as_millis() as u64;
48+
4049
// Share link_store with event handler
4150
let store_clone = link_store.clone();
4251

4352
client.add_event_handler(move |event: OriginalSyncRoomMessageEvent, room: Room| {
4453
let store = store_clone.clone();
4554
async move {
55+
let sender = event.sender.as_str();
56+
if ignore_bridge_users && sender.starts_with("@discord_") {
57+
return;
58+
}
59+
60+
if u64::from(event.origin_server_ts.get()) < start_time {
61+
return;
62+
}
63+
4664
let RoomMessageEventContent { msgtype, .. } = event.content;
4765

4866
if let MessageType::Text(text_content) = msgtype {
4967
let body = text_content.body;
50-
if body.starts_with(".wiki ") {
51-
let argument = body.trim_start_matches(".wiki ").trim();
52-
if let Some(link) = store.get(argument) {
53-
let response = format!("Link for {}: {}", argument, link);
68+
if body == ".wiki" || body.starts_with(".wiki ") {
69+
let argument = body.trim_start_matches(".wiki").trim();
70+
if argument.is_empty() {
71+
let response = "Use .wiki list to print all available links";
72+
let content = RoomMessageEventContent::text_plain(response);
73+
if let Err(e) = room.send(content).await {
74+
eprintln!("Failed to send message: {}", e);
75+
}
76+
} else if argument == "list" {
77+
let keys = store.list_keys();
78+
let response = if keys.is_empty() {
79+
"No wiki links available.".to_string()
80+
} else {
81+
format!("Available wiki links: {}", keys.join(", "))
82+
};
83+
let content = RoomMessageEventContent::text_plain(response);
84+
if let Err(e) = room.send(content).await {
85+
eprintln!("Failed to send message: {}", e);
86+
}
87+
} else if let Some(link) = store.get(argument) {
88+
let response = format!("Link for {}: {}\n(Use .wiki list to print all available links)", argument, link);
5489
// Send response
5590
let content = RoomMessageEventContent::text_plain(response);
5691
if let Err(e) = room.send(content).await {
5792
eprintln!("Failed to send message: {}", e);
5893
}
5994
} else {
6095
// Optional: reply not found, or just ignore
61-
let response = format!("No wiki link found for '{}'", argument);
96+
let response = format!("No wiki link found for '{}'\n(Use .wiki list to print all available links)", argument);
6297
let content = RoomMessageEventContent::text_plain(response);
6398
if let Err(e) = room.send(content).await {
6499
eprintln!("Failed to send message: {}", e);

0 commit comments

Comments
 (0)