summaryrefslogtreecommitdiff
path: root/src/message
diff options
context:
space:
mode:
authorojacobson <ojacobson@noreply.codeberg.org>2025-07-04 05:00:21 +0200
committerojacobson <ojacobson@noreply.codeberg.org>2025-07-04 05:00:21 +0200
commitc35be3ae29e77983f013c01260dda20208175f2b (patch)
treeabf0b9d993ef03a53903aae03f375b78473952da /src/message
parent981cd3c0f4cf912c1d91ee5d9c39f5c1aa7afecf (diff)
parent9b38cb1a62ede4900fde4ba47a7b065db329e994 (diff)
Rename "channels" to "conversations."
The term "channel" for a conversational container has a long and storied history, but is mostly evocative of IRC and of other, ah, "nerd-centric" services. It does show up in more widespread contexts: Discord and Slack both refer to their primary conversational containers as "channels," for example. However, I think it's unnecessary jargon, and I'd like to do away with it. To that end, this change pervasively changes one term to the other wherever it appears, with the following exceptions: * A `channel` concept (unrelated to conversations) is also provided by an external library; we can't and shouldn't try to rename that. * The code to deal with the `pilcrow:channelData` and `pilcrow:lastActiveChannel` local storage properties is still present, to migrate existing data to new keys. It will be removed in a later change. This is a **breaking API change**. As we are not yet managing any API compatibility promises, this is formally not an issue, but it is something to be aware of practically. The major API changes are: * Paths beginning with `/api/channels` are now under `/api/conversations`, without other modifications. * Fields labelled with `channel…` terms are now labelled with `conversation…` terms. For example, a `message` `sent` event is now sent to a `conversation`, not a `channel`. This is also a **breaking UI change**. Specifically, any saved paths for `/ch/CHANNELID` will now lead to a 404. The corresponding paths are `/c/CONVERSATIONID`. While I've made an effort to migrate the location of stored data, I have not tried to provide adapters to fix this specific issue, because the disruption is short-lived and very easily addressed by opening a channel in the client UI. This change is obnoxiously large and difficult to review, for which I apologize. If this shows up in `git annotate`, please forgive me. These kinds of renamings are hard to carry out without a major disruption, especially when the concept ("channel" in this case) is used so pervasively throughout the system. I think it's worth making this change that pervasively so that we don't have an indefinitely-long tail of "well, it's a conversation in the docs, but the table is called `channel` for historical reasons" type issues. Merges conversations-not-channels into main.
Diffstat (limited to 'src/message')
-rw-r--r--src/message/app.rs36
-rw-r--r--src/message/handlers/delete/test.rs21
-rw-r--r--src/message/repo.rs45
-rw-r--r--src/message/snapshot.rs4
4 files changed, 58 insertions, 48 deletions
diff --git a/src/message/app.rs b/src/message/app.rs
index 9792c8f..bdc2164 100644
--- a/src/message/app.rs
+++ b/src/message/app.rs
@@ -4,8 +4,8 @@ use sqlx::sqlite::SqlitePool;
use super::{Body, Id, Message, repo::Provider as _};
use crate::{
- channel::{self, repo::Provider as _},
clock::DateTime,
+ conversation::{self, repo::Provider as _},
db::NotFound as _,
event::{Broadcaster, Event, Sequence, repo::Provider as _},
name,
@@ -24,23 +24,29 @@ impl<'a> Messages<'a> {
pub async fn send(
&self,
- channel: &channel::Id,
+ conversation: &conversation::Id,
sender: &User,
sent_at: &DateTime,
body: &Body,
) -> Result<Message, SendError> {
- let to_not_found = || SendError::ChannelNotFound(channel.clone());
- let to_deleted = || SendError::ChannelDeleted(channel.clone());
+ let to_not_found = || SendError::ConversationNotFound(conversation.clone());
+ let to_deleted = || SendError::ConversationDeleted(conversation.clone());
let mut tx = self.db.begin().await?;
- let channel = tx.channels().by_id(channel).await.not_found(to_not_found)?;
+ let conversation = tx
+ .conversations()
+ .by_id(conversation)
+ .await
+ .not_found(to_not_found)?;
// Ordering: don't bother allocating a sequence number before we know the channel might
// exist.
let sent = tx.sequence().next(sent_at).await?;
- let channel = channel.as_of(sent).ok_or_else(to_deleted)?;
-
- let message = tx.messages().create(&channel, sender, &sent, body).await?;
+ let conversation = conversation.as_of(sent).ok_or_else(to_deleted)?;
+ let message = tx
+ .messages()
+ .create(&conversation, sender, &sent, body)
+ .await?;
tx.commit().await?;
self.events
@@ -128,19 +134,19 @@ impl<'a> Messages<'a> {
#[derive(Debug, thiserror::Error)]
pub enum SendError {
- #[error("channel {0} not found")]
- ChannelNotFound(channel::Id),
- #[error("channel {0} deleted")]
- ChannelDeleted(channel::Id),
+ #[error("conversation {0} not found")]
+ ConversationNotFound(conversation::Id),
+ #[error("conversation {0} deleted")]
+ ConversationDeleted(conversation::Id),
#[error(transparent)]
Database(#[from] sqlx::Error),
#[error(transparent)]
Name(#[from] name::Error),
}
-impl From<channel::repo::LoadError> for SendError {
- fn from(error: channel::repo::LoadError) -> Self {
- use channel::repo::LoadError;
+impl From<conversation::repo::LoadError> for SendError {
+ fn from(error: conversation::repo::LoadError) -> Self {
+ use conversation::repo::LoadError;
match error {
LoadError::Database(error) => error.into(),
LoadError::Name(error) => error.into(),
diff --git a/src/message/handlers/delete/test.rs b/src/message/handlers/delete/test.rs
index f567eb7..371c7bf 100644
--- a/src/message/handlers/delete/test.rs
+++ b/src/message/handlers/delete/test.rs
@@ -9,8 +9,9 @@ pub async fn delete_message() {
let app = fixtures::scratch_app().await;
let sender = fixtures::identity::create(&app, &fixtures::now()).await;
- let channel = fixtures::channel::create(&app, &fixtures::now()).await;
- let message = fixtures::message::send(&app, &channel, &sender.user, &fixtures::now()).await;
+ let conversation = fixtures::conversation::create(&app, &fixtures::now()).await;
+ let message =
+ fixtures::message::send(&app, &conversation, &sender.user, &fixtures::now()).await;
// Send the request
@@ -70,8 +71,8 @@ pub async fn delete_deleted() {
let app = fixtures::scratch_app().await;
let sender = fixtures::user::create(&app, &fixtures::now()).await;
- let channel = fixtures::channel::create(&app, &fixtures::now()).await;
- let message = fixtures::message::send(&app, &channel, &sender, &fixtures::now()).await;
+ let conversation = fixtures::conversation::create(&app, &fixtures::now()).await;
+ let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::now()).await;
app.messages()
.delete(&sender, &message.id, &fixtures::now())
@@ -101,8 +102,8 @@ pub async fn delete_expired() {
let app = fixtures::scratch_app().await;
let sender = fixtures::user::create(&app, &fixtures::ancient()).await;
- let channel = fixtures::channel::create(&app, &fixtures::ancient()).await;
- let message = fixtures::message::send(&app, &channel, &sender, &fixtures::ancient()).await;
+ let conversation = fixtures::conversation::create(&app, &fixtures::ancient()).await;
+ let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::ancient()).await;
app.messages()
.expire(&fixtures::now())
@@ -132,8 +133,8 @@ pub async fn delete_purged() {
let app = fixtures::scratch_app().await;
let sender = fixtures::user::create(&app, &fixtures::ancient()).await;
- let channel = fixtures::channel::create(&app, &fixtures::ancient()).await;
- let message = fixtures::message::send(&app, &channel, &sender, &fixtures::ancient()).await;
+ let conversation = fixtures::conversation::create(&app, &fixtures::ancient()).await;
+ let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::ancient()).await;
app.messages()
.expire(&fixtures::old())
@@ -168,8 +169,8 @@ pub async fn delete_not_sender() {
let app = fixtures::scratch_app().await;
let sender = fixtures::user::create(&app, &fixtures::now()).await;
- let channel = fixtures::channel::create(&app, &fixtures::now()).await;
- let message = fixtures::message::send(&app, &channel, &sender, &fixtures::now()).await;
+ let conversation = fixtures::conversation::create(&app, &fixtures::now()).await;
+ let message = fixtures::message::send(&app, &conversation, &sender, &fixtures::now()).await;
// Send the request
diff --git a/src/message/repo.rs b/src/message/repo.rs
index e753134..9b65a67 100644
--- a/src/message/repo.rs
+++ b/src/message/repo.rs
@@ -2,8 +2,8 @@ use sqlx::{SqliteConnection, Transaction, sqlite::Sqlite};
use super::{Body, History, Id, snapshot::Message};
use crate::{
- channel::{self, Channel},
clock::DateTime,
+ conversation::{self, Conversation},
event::{Instant, Sequence},
user::{self, User},
};
@@ -23,7 +23,7 @@ pub struct Messages<'t>(&'t mut SqliteConnection);
impl Messages<'_> {
pub async fn create(
&mut self,
- channel: &Channel,
+ conversation: &Conversation,
sender: &User,
sent: &Instant,
body: &Body,
@@ -33,18 +33,18 @@ impl Messages<'_> {
let message = sqlx::query!(
r#"
insert into message
- (id, channel, sender, sent_at, sent_sequence, body, last_sequence)
+ (id, conversation, sender, sent_at, sent_sequence, body, last_sequence)
values ($1, $2, $3, $4, $5, $6, $7)
returning
id as "id: Id",
- channel as "channel: channel::Id",
+ conversation as "conversation: conversation::Id",
sender as "sender: user::Id",
sent_at as "sent_at: DateTime",
sent_sequence as "sent_sequence: Sequence",
body as "body: Body"
"#,
id,
- channel.id,
+ conversation.id,
sender.id,
sent.at,
sent.sequence,
@@ -54,7 +54,7 @@ impl Messages<'_> {
.map(|row| History {
message: Message {
sent: Instant::new(row.sent_at, row.sent_sequence),
- channel: row.channel,
+ conversation: row.conversation,
sender: row.sender,
id: row.id,
body: row.body.unwrap_or_default(),
@@ -68,12 +68,15 @@ impl Messages<'_> {
Ok(message)
}
- pub async fn live(&mut self, channel: &channel::History) -> Result<Vec<History>, sqlx::Error> {
- let channel_id = channel.id();
+ pub async fn live(
+ &mut self,
+ conversation: &conversation::History,
+ ) -> Result<Vec<History>, sqlx::Error> {
+ let conversation_id = conversation.id();
let messages = sqlx::query!(
r#"
select
- message.channel as "channel: channel::Id",
+ message.conversation as "conversation: conversation::Id",
message.sender as "sender: user::Id",
id as "id: Id",
message.body as "body: Body",
@@ -84,15 +87,15 @@ impl Messages<'_> {
from message
left join message_deleted as deleted
using (id)
- where message.channel = $1
+ where message.conversation = $1
and deleted.id is null
"#,
- channel_id,
+ conversation_id,
)
.map(|row| History {
message: Message {
sent: Instant::new(row.sent_at, row.sent_sequence),
- channel: row.channel,
+ conversation: row.conversation,
sender: row.sender,
id: row.id,
body: row.body.unwrap_or_default(),
@@ -110,7 +113,7 @@ impl Messages<'_> {
let messages = sqlx::query!(
r#"
select
- message.channel as "channel: channel::Id",
+ message.conversation as "conversation: conversation::Id",
message.sender as "sender: user::Id",
message.id as "id: Id",
message.body as "body: Body",
@@ -129,7 +132,7 @@ impl Messages<'_> {
.map(|row| History {
message: Message {
sent: Instant::new(row.sent_at, row.sent_sequence),
- channel: row.channel,
+ conversation: row.conversation,
sender: row.sender,
id: row.id,
body: row.body.unwrap_or_default(),
@@ -147,7 +150,7 @@ impl Messages<'_> {
let message = sqlx::query!(
r#"
select
- message.channel as "channel: channel::Id",
+ message.conversation as "conversation: conversation::Id",
message.sender as "sender: user::Id",
id as "id: Id",
message.body as "body: Body",
@@ -165,7 +168,7 @@ impl Messages<'_> {
.map(|row| History {
message: Message {
sent: Instant::new(row.sent_at, row.sent_sequence),
- channel: row.channel,
+ conversation: row.conversation,
sender: row.sender,
id: row.id,
body: row.body.unwrap_or_default(),
@@ -200,7 +203,7 @@ impl Messages<'_> {
// Small social responsibility hack here: when a message is deleted, its body is
// retconned to have been the empty string. Someone reading the event stream
- // afterwards, or looking at messages in the channel, cannot retrieve the
+ // afterwards, or looking at messages in the conversation, cannot retrieve the
// "deleted" message by ignoring the deletion event.
sqlx::query!(
r#"
@@ -252,7 +255,7 @@ impl Messages<'_> {
r#"
select
id as "id: Id",
- message.channel as "channel: channel::Id",
+ message.conversation as "conversation: conversation::Id",
message.sender as "sender: user::Id",
message.sent_at as "sent_at: DateTime",
message.sent_sequence as "sent_sequence: Sequence",
@@ -271,7 +274,7 @@ impl Messages<'_> {
message: Message {
sent: Instant::new(row.sent_at, row.sent_sequence),
id: row.id,
- channel: row.channel,
+ conversation: row.conversation,
sender: row.sender,
body: row.body.unwrap_or_default(),
deleted_at: row.deleted_at,
@@ -289,7 +292,7 @@ impl Messages<'_> {
r#"
select
id as "id: Id",
- message.channel as "channel: channel::Id",
+ message.conversation as "conversation: conversation::Id",
message.sender as "sender: user::Id",
message.sent_at as "sent_at: DateTime",
message.sent_sequence as "sent_sequence: Sequence",
@@ -306,7 +309,7 @@ impl Messages<'_> {
.map(|row| History {
message: Message {
sent: Instant::new(row.sent_at, row.sent_sequence),
- channel: row.channel,
+ conversation: row.conversation,
sender: row.sender,
id: row.id,
body: row.body.unwrap_or_default(),
diff --git a/src/message/snapshot.rs b/src/message/snapshot.rs
index ac067f7..12d4daa 100644
--- a/src/message/snapshot.rs
+++ b/src/message/snapshot.rs
@@ -2,13 +2,13 @@ use super::{
Body, Id,
event::{Event, Sent},
};
-use crate::{channel, clock::DateTime, event::Instant, user};
+use crate::{clock::DateTime, conversation, event::Instant, user};
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
pub struct Message {
#[serde(flatten)]
pub sent: Instant,
- pub channel: channel::Id,
+ pub conversation: conversation::Id,
pub sender: user::Id,
pub id: Id,
pub body: Body,