Skip to content

Commit

Permalink
Merge pull request #59 from polyphony-chat/gateway
Browse files Browse the repository at this point in the history
Obligatory merge from gateway to main
  • Loading branch information
bitfl0wer authored Oct 17, 2024
2 parents f3d1914 + 463699a commit 20a8711
Show file tree
Hide file tree
Showing 26 changed files with 2,230 additions and 243 deletions.

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

2 changes: 2 additions & 0 deletions .vscode/ltex.dictionary.en-US.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
str
&message
1 change: 1 addition & 0 deletions .vscode/ltex.hiddenFalsePositives.en-US.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"rule":"MORFOLOGIK_RULE_EN_US","sentence":"^\\Qreturn Ok(Event::Heartbeat(from_str(&message)?))\\E$"}
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ tokio-tungstenite = { version = "0.23.1", features = [
] }
pubserve = { version = "1.1.0", features = ["async", "send"] }
parking_lot = { version = "0.12.3", features = ["deadlock_detection"] }
sqlx-pg-uint = { version = "0.7.2", features = ["serde"] }
sqlx-pg-uint = { version = "0.8.0", features = ["serde"] }

[dev-dependencies]
rusty-hook = "0.11.2"
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ Whether you are using Docker or not, you will need to have the following install

- [Rust](https://www.rust-lang.org/tools/install)
- [git](https://git-scm.com/downloads)
- [`sqlx-cli`](https://crates.io/crates/sqlx-cli)

If your development environment is hosted on a Windows machine, please additionally make sure that
you have a bash shell available to execute pre-commit hooks. This can be done by installing
[Git Bash](https://git-scm.com/downloads) or
[Windows Subsystem for Linux 2](https://learn.microsoft.com/en-us/windows/wsl/install) and, additionally,
configuring your IDE correctly.

See the instructions below for guidance on how to run the project.

### Non-Docker

Expand Down
7 changes: 7 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# To-do list for bitfl0wer

- Take care of gateway_task
- Find out how sequence numbers work and increment them properly
- Find out where the stupid opcode 2 send comes from
- On death of connection: Remove session id from database
- Maybe this and the "create resumable" thing can be consolidated?
49 changes: 49 additions & 0 deletions fixtures/notes.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
BEGIN;
INSERT INTO user_settings (
index, afk_timeout, allow_accessibility_detection, animate_emoji, animate_stickers,
contact_sync_enabled, convert_emoticons, custom_status, default_guilds_restricted,
detect_platform_accounts, developer_mode, disable_games_tab, enable_tts_command,
explicit_content_filter, friend_source_flags, gateway_connected, gif_auto_play,
guild_folders, guild_positions, inline_attachment_media, inline_embed_media,
locale, message_display_compact, native_phone_integration_enabled, render_embeds,
render_reactions, restricted_guilds, show_current_game, status,
stream_notifications_enabled, theme, timezone_offset
)
VALUES
(7251169922837909504, 300, true, true, 1, true, true, 'Working on project', false, true, true, false,
true, 2, 'friends', true, true, 'folder_data', 'positions_data', true, true,
'en-US', false, true, true, true, 'restricted_guilds_data', true, 'online', true,
'dark', -7),
(7251169922837909505, 600, false, false, 0, false, false, 'Available', false, false, false, true,
false, 0, NULL, false, false, NULL, NULL, false, false, 'fr-FR', true, false,
false, false, NULL, false, 'away', false, 'light', 1);

INSERT INTO users (
id, username, discriminator, avatar, accent_color, banner, theme_colors, pronouns,
phone, desktop, mobile, premium, premium_type, bot, bio, system, nsfw_allowed,
mfa_enabled, webauthn_enabled, totp_secret, totp_last_ticket, created_at,
premium_since, verified, disabled, deleted, email, flags, public_flags,
purchased_flags, premium_usage_flags, rights, data, fingerprints, extended_settings,
settings_index, relevant_events
)
VALUES
(7250861145186111490, 'john_doe_notes', '1296', 'avatar1.png', 16777215, 'banner1.png', NULL,
'he/him', '+1234567890', true, false, true, 1, false, 'This is my bio', false,
true, true, true, 'secret123', 'ticket456', '2024-01-01 12:00:00',
'2024-01-02 12:00:00', true, false, false, '[email protected]', 100, 10,
5, 1, 100, '{"hash": "$2b$14$AbcNYTh5GcOYaB4v4P7OWeGW0hQkd/ysvmY4fGyIA/tyEnK0chGNu", "valid_tokens_since": "2024-10-07T20:22:06.162070616Z"}', 'fingerprint1', '{"setting": "value"}', 7251169922837909504,
'[]'),
(7250861145186111491, 'jane_smith_notes', '5678', 'avatar2.png', 123456, NULL, NULL,
'she/her', NULL, false, true, false, 0, false, '', false,
false, false, false, NULL, NULL, '2024-02-01 15:30:00',
NULL, false, false, false, '[email protected]', 50, 5,
0, 0, 50, '{"hash": "$2b$14$AbcNYTh5GcOYaB4v4P7OWeGW0hQkd/ysvmY4fGyIA/tyEnK0chGNu", "valid_tokens_since": "2024-10-07T20:22:06.162070616Z"}', 'fingerprint2', '{"setting": "another_value"}', 7251169922837909505,
'[]');
COMMIT;

INSERT INTO notes (
content, author_id, target_id
)
VALUES
('This is a note', 7250861145186111490, 7250861145186111491),
('This is another note', 7250861145186111491, 7250861145186111490);
58 changes: 58 additions & 0 deletions fixtures/private_channels.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
-- Create two users with two respective user_settings, one DM channel, and add both users to that DM channel.
BEGIN;
INSERT INTO user_settings (
index, afk_timeout, allow_accessibility_detection, animate_emoji, animate_stickers,
contact_sync_enabled, convert_emoticons, custom_status, default_guilds_restricted,
detect_platform_accounts, developer_mode, disable_games_tab, enable_tts_command,
explicit_content_filter, friend_source_flags, gateway_connected, gif_auto_play,
guild_folders, guild_positions, inline_attachment_media, inline_embed_media,
locale, message_display_compact, native_phone_integration_enabled, render_embeds,
render_reactions, restricted_guilds, show_current_game, status,
stream_notifications_enabled, theme, timezone_offset
)
VALUES
(7250861145186111495, 300, true, true, 1, true, true, 'Working on project', false, true, true, false,
true, 2, 'friends', true, true, 'folder_data', 'positions_data', true, true,
'en-US', false, true, true, true, 'restricted_guilds_data', true, 'online', true,
'dark', -7),
(7250861145186111496, 600, false, false, 0, false, false, 'Available', false, false, false, true,
false, 0, NULL, false, false, NULL, NULL, false, false, 'fr-FR', true, false,
false, false, NULL, false, 'away', false, 'light', 1);

INSERT INTO users (
id, username, discriminator, avatar, accent_color, banner, theme_colors, pronouns,
phone, desktop, mobile, premium, premium_type, bot, bio, system, nsfw_allowed,
mfa_enabled, webauthn_enabled, totp_secret, totp_last_ticket, created_at,
premium_since, verified, disabled, deleted, email, flags, public_flags,
purchased_flags, premium_usage_flags, rights, data, fingerprints, extended_settings,
settings_index, relevant_events
)
VALUES
(7250861145186111490, 'john_doe_private_channels', '1296', 'avatar1.png', 16777215, 'banner1.png', NULL,
'he/him', '+1234567890', true, false, true, 1, false, 'This is my bio', false,
true, true, true, 'secret123', 'ticket456', '2024-01-01 12:00:00',
'2024-01-02 12:00:00', true, false, false, '[email protected]', 100, 10,
5, 1, 100, '{"hash": "$2b$14$AbcNYTh5GcOYaB4v4P7OWeGW0hQkd/ysvmY4fGyIA/tyEnK0chGNu", "valid_tokens_since": "2024-10-07T20:22:06.162070616Z"}', 'fingerprint1', '{"setting": "value"}', 7250861145186111495,
'[]'),
(7250861145186111491, 'jane_smith_private_channels', '5678', 'avatar2.png', 123456, NULL, NULL,
'she/her', NULL, false, true, false, 0, false, '', false,
false, false, false, NULL, NULL, '2024-02-01 15:30:00',
NULL, false, false, false, '[email protected]', 50, 5,
0, 0, 50, '{"hash": "$2b$14$AbcNYTh5GcOYaB4v4P7OWeGW0hQkd/ysvmY4fGyIA/tyEnK0chGNu", "valid_tokens_since": "2024-10-07T20:22:06.162070616Z"}', 'fingerprint2', '{"setting": "another_value"}', 7250861145186111496,
'[]');
COMMIT;

INSERT INTO channels (
id, created_at, name, icon, type, last_message_id, guild_id, parent_id, owner_id, last_pin_timestamp,
default_auto_archive_duration, "position", permission_overwrites, video_quality_mode, bitrate, user_limit, nsfw,
rate_limit_per_user, topic, retention_policy_id, flags, default_thread_rate_limit_per_user
)
VALUES (
7250859537236758528, current_timestamp, NULL, NULL, 1, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL,NULL, NULL, NULL, false, 0, NULL, NULL,
0, 0
);

INSERT INTO recipients (id, channel_id, user_id, closed) VALUES
(7250860729446699008, 7250859537236758528, 7250861145186111490, false),
(7250861145186111494, 7250859537236758528, 7250861145186111491, false);
12 changes: 11 additions & 1 deletion migrations/20231007011933_channels.sql
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
create table if not exists channels
(
id numeric(20, 0) not null constraint chk_id_range check (id >= 0 AND id <= 18446744073709551615) primary key,
created_at timestamp not null,
created_at timestamptz not null,
name varchar(255) null,
icon text null,
type int not null,
Expand All @@ -12,6 +12,8 @@ create table if not exists channels
last_pin_timestamp int null,
default_auto_archive_duration int null,
position int null,
managed boolean null,
rtc_region varchar(255) null,
permission_overwrites text null,
video_quality_mode int null,
bitrate int null,
Expand All @@ -22,6 +24,14 @@ create table if not exists channels
retention_policy_id varchar(255) null,
flags int not null,
default_thread_rate_limit_per_user int not null,
default_sort_order numeric(3, 0) null constraint chk_default_sort_order check (default_sort_order >= 0 AND default_sort_order <= 255),
-- v foreign key constraint is added in emojis migration
-- TODO: I am unsure if deserializing a channel object from the database will work with the default_reaction_emoji field. Test it
default_reaction_emoji numeric(20, 0) null constraint chk_default_reaction_emoji check (default_reaction_emoji >= 0 AND default_reaction_emoji <= 18446744073709551615),
default_forum_layout numeric(3, 0) null constraint chk_default_forum_layout check (default_forum_layout >= 0 AND default_forum_layout <= 255),
available_tags jsonb null constraint chk_available_tags check (jsonb_typeof(available_tags) = 'array') default '[]',
applied_tags jsonb null constraint chk_applied_tags check (jsonb_typeof(applied_tags) = 'array') default '[]',
application_id numeric(20, 0) null constraint chk_application_id_range check (application_id >= 0 AND application_id <= 18446744073709551615),
constraint FK_3274522d14af40540b1a883fc80
foreign key (parent_id) references channels (id),
constraint FK_3873ed438575cce703ecff4fc7b
Expand Down
5 changes: 4 additions & 1 deletion migrations/20231007012108_emojis.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ create table if not exists emojis
on delete cascade,
constraint FK_fa7ddd5f9a214e28ce596548421
foreign key (user_id) references users (id)
);
);

ALTER TABLE channels
ADD CONSTRAINT FK_emoji_id_emojis_id FOREIGN KEY (default_reaction_emoji) REFERENCES emojis(id);
12 changes: 7 additions & 5 deletions migrations/20231007012149_notes.sql
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
CREATE SEQUENCE notes_index_seq;

create table if not exists notes
(
id varchar(255) not null primary key,
content varchar(255) not null,
owner_id numeric(20, 0) null constraint chk_owner_id_range check (owner_id >= 0 AND owner_id <= 18446744073709551615),
index numeric(20, 0) not null default nextval('notes_index_seq') constraint chk_index_range check (index >= 0 and index <= 18446744073709551615) primary key,
content varchar(256) not null,
author_id numeric(20, 0) null constraint chk_author_id_range check (author_id >= 0 AND author_id <= 18446744073709551615),
target_id numeric(20, 0) null constraint chk_target_id_range check (target_id >= 0 AND target_id <= 18446744073709551615),
constraint IDX_74e6689b9568cc965b8bfc9150
unique (owner_id, target_id),
unique (author_id, target_id),
constraint FK_23e08e5b4481711d573e1abecdc
foreign key (target_id) references users (id)
on delete cascade,
constraint FK_f9e103f8ae67cb1787063597925
foreign key (owner_id) references users (id)
foreign key (author_id) references users (id)
on delete cascade
);
4 changes: 3 additions & 1 deletion migrations/20231007012343_sessions.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
CREATE SEQUENCE sessions_index_seq;

create table if not exists sessions
(
id numeric(20, 0) not null constraint chk_id_range check (id >= 0 AND id <= 18446744073709551615) primary key,
index numeric(20, 0) not null default nextval('user_settings_index_seq') constraint chk_index_range check (index >= 0 and index <= 18446744073709551615) primary key,
user_id numeric(20, 0) null constraint chk_user_id_range check (user_id >= 0 AND user_id <= 18446744073709551615),
session_id numeric(20, 0) not null constraint chk_session_id_range check (session_id >= 0 AND session_id <= 18446744073709551615),
activities text null,
Expand Down
14 changes: 4 additions & 10 deletions prepare-sqlx-if-needed.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
#!/bin/bash

if git diff --quiet HEAD -- "./migrations"; then
echo "No changes in migrations folder"
exit 0
else
echo "Changes in migrations folder detected, running sqlx prepare"
cargo sqlx prepare --all -- --all-targets --all-features
git add .sqlx/*
exit_code=$?
cargo sqlx prepare --all -- --all-targets --all-features
git add .sqlx/*
exit_code=$?

exit $exit_code
fi
exit $exit_code
25 changes: 25 additions & 0 deletions src/database/entities/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,4 +377,29 @@ impl Channel {
.map(|_| ())
.map_err(Error::from)
}

/// Get all private channels of a user. Only queries channels which are not marked as closed.
pub async fn get_private_of_user(user_id: Snowflake, db: &PgPool) -> Result<Vec<Self>, Error> {
sqlx::query_as(
"SELECT c.* FROM recipients r
JOIN channels c ON r.channel_id = c.id
WHERE r.user_id = $1 AND r.closed = false",
)
.bind(user_id)
.fetch_all(db)
.await
.map_err(Error::Sqlx)
}
}

#[cfg(test)]
mod channel_unit_tests {
#[sqlx::test(fixtures(path = "../../../fixtures", scripts("private_channels")))]
async fn get_private_of_user(pool: sqlx::PgPool) {
let channels = super::Channel::get_private_of_user(7250861145186111490.into(), &pool)
.await
.unwrap();
assert_eq!(channels.len(), 1);
assert_eq!(channels[0].id, 7250859537236758528.into());
}
}
2 changes: 2 additions & 0 deletions src/database/entities/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub use guild_template::*;
pub use invite::*;
pub use member::*;
pub use message::*;
pub use note::*;
pub use read_state::*;
pub use recipient::*;
pub use relationship::*;
Expand All @@ -36,6 +37,7 @@ mod guild_template;
mod invite;
mod member;
mod message;
mod note;
mod read_state;
mod recipient;
mod relationship;
Expand Down
68 changes: 68 additions & 0 deletions src/database/entities/note.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::ops::{Deref, DerefMut};

use chorus::types::{Snowflake, UserNote};
use serde::{Deserialize, Serialize};

use crate::errors::Error;

#[derive(sqlx::FromRow, Debug, Clone, Serialize, Deserialize)]
/// A note that a user has written about another user. The target user may be the author of the note.
pub struct Note {
#[sqlx(flatten)]
inner: UserNote,
}

impl Deref for Note {
type Target = UserNote;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

impl DerefMut for Note {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}

impl Note {
pub fn into_inner(self) -> UserNote {
self.inner
}

pub fn as_inner(&self) -> &UserNote {
&self.inner
}

pub fn as_inner_mut(&mut self) -> &mut UserNote {
&mut self.inner
}

/// Retrieve all notes from a user by their ID
pub async fn get_by_author_id(
author_id: Snowflake,
db: &sqlx::PgPool,
) -> Result<Vec<Self>, Error> {
sqlx::query_as("SELECT * from notes WHERE author_id = $1")
.bind(author_id)
.fetch_all(db)
.await
.map_err(Error::Sqlx)
}
}

#[cfg(test)]
mod note_unit_tests {
#[sqlx::test(fixtures(path = "../../../fixtures", scripts("notes")))]
async fn test_get_by_author_id(db: sqlx::PgPool) {
let notes = super::Note::get_by_author_id(7250861145186111490.into(), &db)
.await
.unwrap();
assert_eq!(notes.len(), 1);
let note = notes[0].as_inner();
assert_eq!(note.author_id, 7250861145186111490.into());
assert_eq!(note.target_id, 7250861145186111491.into());
assert_eq!(note.content, "This is a note");
}
}
Loading

0 comments on commit 20a8711

Please sign in to comment.