mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 04:55:42 +09:00
feat(threads): thread and forum API, admin, schemas and docs (#3251)
This commit is contained in:
1 parent
5f4295e399
commit
3f4160b138
495 files changed
+39232
-1215
No files matched your search
@@ -433,6 +433,19 @@ fn deserialize_instance_config_response_with_unknown_keys() {
|
||||
"max_counter": 1000,
|
||||
"future_captcha_knob": 1
|
||||
},
|
||||
"channel_threads": {
|
||||
"enabled": true,
|
||||
"config_version": 3,
|
||||
"ever_enabled": true,
|
||||
"guild_basis_points": 0,
|
||||
"guild_salt": "channel-threads-guild-v1",
|
||||
"enabled_guild_ids": ["1600000000000000001"],
|
||||
"disabled_guild_ids": [],
|
||||
"user_basis_points": 10000,
|
||||
"user_salt": "channel-threads-user-v1",
|
||||
"included_user_ids": [],
|
||||
"excluded_user_ids": []
|
||||
},
|
||||
"experiment_delivery": {"poll_interval_seconds": 300, "poll_jitter_percent": 15},
|
||||
"registration": {
|
||||
"mode": "open",
|
||||
@@ -595,6 +608,9 @@ fn deserialize_instance_config_response_with_unknown_keys() {
|
||||
assert!(resp.push_relay.relay_consent_accepted);
|
||||
assert!(resp.captcha.enabled);
|
||||
assert_eq!(resp.captcha.max_counter, 1000);
|
||||
assert!(resp.channel_threads.enabled);
|
||||
assert_eq!(resp.channel_threads.config_version, 3);
|
||||
assert_eq!(resp.channel_threads.enabled_guild_ids.len(), 1);
|
||||
assert_eq!(resp.experiment_delivery.poll_interval_seconds, 300);
|
||||
assert!(resp.policy.single_community_guild_id.is_none());
|
||||
assert_eq!(resp.policy.services.gif_enabled, Some(true));
|
||||
@@ -662,6 +678,63 @@ fn deserialize_instance_config_response_with_unknown_keys() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_channel_threads_config() {
|
||||
let config: types::ChannelThreadsConfigResponse = serde_json::from_str(
|
||||
r#"{
|
||||
"enabled": true,
|
||||
"config_version": 12,
|
||||
"ever_enabled": true,
|
||||
"guild_basis_points": 50,
|
||||
"guild_salt": "channel-threads-guild-v2",
|
||||
"enabled_guild_ids": ["1600000000000000001"],
|
||||
"disabled_guild_ids": ["1600000000000000002", "1600000000000000003"],
|
||||
"user_basis_points": 10000,
|
||||
"user_salt": "channel-threads-user-v1",
|
||||
"included_user_ids": [],
|
||||
"excluded_user_ids": ["1500000000000000001"],
|
||||
"future_threads_knob": 1
|
||||
}"#,
|
||||
)
|
||||
.expect("a channel threads config must deserialize");
|
||||
|
||||
assert!(config.enabled);
|
||||
assert!(config.ever_enabled);
|
||||
assert_eq!(config.config_version, 12);
|
||||
assert_eq!(config.guild_basis_points, 50);
|
||||
assert_eq!(config.guild_salt, "channel-threads-guild-v2");
|
||||
assert_eq!(config.enabled_guild_ids, vec!["1600000000000000001"]);
|
||||
assert_eq!(config.disabled_guild_ids.len(), 2);
|
||||
assert_eq!(config.user_basis_points, 10000);
|
||||
assert_eq!(config.excluded_user_ids, vec!["1500000000000000001"]);
|
||||
|
||||
let absent: types::ChannelThreadsConfigResponse =
|
||||
serde_json::from_str("{}").expect("an api without the experiment still deserializes");
|
||||
assert!(!absent.enabled);
|
||||
assert!(!absent.ever_enabled);
|
||||
assert_eq!(absent.guild_salt, types::CHANNEL_THREADS_DEFAULT_GUILD_SALT);
|
||||
assert_eq!(absent.user_salt, types::CHANNEL_THREADS_DEFAULT_USER_SALT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serialize_channel_threads_update_never_sends_server_owned_fields() {
|
||||
let update = types::InstanceConfigUpdateRequest {
|
||||
channel_threads: Some(types::ChannelThreadsConfigUpdateRequest {
|
||||
enabled: Some(true),
|
||||
enabled_guild_ids: Some(vec!["1600000000000000001".to_owned()]),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
};
|
||||
assert_eq!(
|
||||
serde_json::to_value(&update).unwrap(),
|
||||
serde_json::json!({"channel_threads": {
|
||||
"enabled": true,
|
||||
"enabled_guild_ids": ["1600000000000000001"],
|
||||
}})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_push_relay_config() {
|
||||
let accepted: types::PushRelayConfigResponse = serde_json::from_str(
|
||||
@@ -1084,3 +1157,48 @@ fn account_identity_lock_is_unknown_when_the_api_omits_it() {
|
||||
assert_eq!(identity.mode, types::AccountIdentityMode::Email);
|
||||
assert_eq!(identity.locked, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_guild_threads_response() {
|
||||
let json = r#"{
|
||||
"threads": [
|
||||
{
|
||||
"id": "1600000000000000010",
|
||||
"type": 12,
|
||||
"guild_id": "1600000000000000001",
|
||||
"parent_id": "1600000000000000002",
|
||||
"owner_id": "1500000000000000001",
|
||||
"name": "secret plans",
|
||||
"last_message_id": null,
|
||||
"last_pin_timestamp": null,
|
||||
"rate_limit_per_user": 0,
|
||||
"flags": 0,
|
||||
"thread_metadata": {
|
||||
"archived": true,
|
||||
"auto_archive_duration": 4320,
|
||||
"archive_timestamp": "2026-09-27T12:00:00.000Z",
|
||||
"locked": false,
|
||||
"invitable": false,
|
||||
"create_timestamp": "2026-09-26T12:00:00.000Z"
|
||||
},
|
||||
"message_count": 3,
|
||||
"total_message_sent": 4,
|
||||
"member_count": 2
|
||||
}
|
||||
]
|
||||
}"#;
|
||||
let generated: generated_types::ListGuildThreadsResponse =
|
||||
serde_json::from_str(json).expect("the generated client must accept the thread list");
|
||||
assert_eq!(generated.threads.len(), 1);
|
||||
let resp: types::ListGuildThreadsResponse = serde_json::from_str(json).unwrap();
|
||||
let thread = &resp.threads[0];
|
||||
assert_eq!(thread.channel_type, 12);
|
||||
assert_eq!(thread.name.as_deref(), Some("secret plans"));
|
||||
assert_eq!(thread.member_count, Some(2));
|
||||
assert!(
|
||||
thread
|
||||
.thread_metadata
|
||||
.as_ref()
|
||||
.is_some_and(|m| m.archived && !m.locked)
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user