diff --git a/backend/canisters/community/CHANGELOG.md b/backend/canisters/community/CHANGELOG.md index c2739a0100..39ca12259e 100644 --- a/backend/canisters/community/CHANGELOG.md +++ b/backend/canisters/community/CHANGELOG.md @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] +## [[2.0.1540](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1540-community)] - 2024-12-19 + +### Fixed + +- Fix community `RoleChanged` event deserialization ([#7098](https://github.com/open-chat-labs/open-chat/pull/7098)) + ## [[2.0.1538](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1538-community)] - 2024-12-19 ### Changed diff --git a/backend/canisters/community/impl/src/lifecycle/post_upgrade.rs b/backend/canisters/community/impl/src/lifecycle/post_upgrade.rs index 70395c3209..3ea0940d6f 100644 --- a/backend/canisters/community/impl/src/lifecycle/post_upgrade.rs +++ b/backend/canisters/community/impl/src/lifecycle/post_upgrade.rs @@ -9,7 +9,6 @@ use ic_cdk::post_upgrade; use instruction_counts_log::InstructionCountFunctionId; use stable_memory::get_reader; use tracing::info; -use utils::env::Environment; #[post_upgrade] #[trace] @@ -19,19 +18,12 @@ fn post_upgrade(args: Args) { let memory = get_upgrades_memory(); let reader = get_reader(&memory); - let (mut data, errors, logs, traces): (Data, Vec, Vec, Vec) = + let (data, errors, logs, traces): (Data, Vec, Vec, Vec) = msgpack::deserialize(reader).unwrap(); canister_logger::init_with_logs(data.test_mode, errors, logs, traces); - data.events.fix_role_changed_events(); - let env = init_env(data.rng_seed); - let now = env.now(); - for channel in data.channels.iter_mut() { - channel.chat.events.remove_spurious_video_call_in_progress(now); - } - init_state(env, data, args.wasm_version); let completed_imports = read_state(|state| state.data.groups_being_imported.completed_imports()); diff --git a/backend/canisters/community/impl/src/model/events.rs b/backend/canisters/community/impl/src/model/events.rs index d55775a6bb..4f4887edbd 100644 --- a/backend/canisters/community/impl/src/model/events.rs +++ b/backend/canisters/community/impl/src/model/events.rs @@ -1,14 +1,12 @@ use crate::model::events::stable_memory::EventsStableStorage; use chat_events::GroupGateUpdatedInternal; use serde::{Deserialize, Serialize}; -use tracing::info; use types::{ AvatarChanged, BannerChanged, BotAdded, BotRemoved, BotUpdated, ChannelDeleted, ChannelId, ChatId, CommunityMembersRemoved, - CommunityPermissionsChanged, CommunityRole, CommunityUsersBlocked, CommunityVisibilityChanged, EventIndex, + CommunityPermissionsChanged, CommunityRoleChanged, CommunityUsersBlocked, CommunityVisibilityChanged, EventIndex, EventWrapperInternal, GroupCreated, GroupDescriptionChanged, GroupFrozen, GroupInviteCodeChanged, GroupNameChanged, - GroupUnfrozen, PrimaryLanguageChanged, TimestampMillis, UserId, UsersInvited, UsersUnblocked, + GroupRulesChanged, GroupUnfrozen, PrimaryLanguageChanged, TimestampMillis, UserId, UsersInvited, UsersUnblocked, }; -use user_canister::token_swap_status::CandidType; mod stable_memory; @@ -19,54 +17,6 @@ pub struct CommunityEvents { latest_event_timestamp: TimestampMillis, } -#[derive(Serialize, Deserialize, Clone, Debug)] -pub enum CommunityEventInternalOld { - #[serde(rename = "cr", alias = "Created")] - Created(Box), - #[serde(rename = "nc", alias = "NameChanged")] - NameChanged(Box), - #[serde(rename = "dc", alias = "DescriptionChanged")] - DescriptionChanged(Box), - #[serde(rename = "rc", alias = "RulesChanged")] - RulesChangedOrRoleChanged(Box), - #[serde(rename = "ac", alias = "AvatarChanged")] - AvatarChanged(Box), - #[serde(rename = "bc", alias = "BannerChanged")] - BannerChanged(Box), - #[serde(rename = "ui", alias = "UsersInvited")] - UsersInvited(Box), - #[serde(rename = "mr", alias = "MembersRemoved")] - MembersRemoved(Box), - #[serde(rename = "ub", alias = "UsersBlocked")] - UsersBlocked(Box), - #[serde(rename = "uu", alias = "UsersUnblocked")] - UsersUnblocked(Box), - #[serde(rename = "pc", alias = "PermissionsChanged")] - PermissionsChanged(Box), - #[serde(rename = "vc", alias = "VisibilityChanged")] - VisibilityChanged(Box), - #[serde(rename = "ic", alias = "InviteCodeChanged")] - InviteCodeChanged(Box), - #[serde(rename = "fr", alias = "Frozen")] - Frozen(Box), - #[serde(rename = "uf", alias = "Unfrozen")] - Unfrozen(Box), - #[serde(rename = "gu", alias = "GateUpdated")] - GateUpdated(Box), - #[serde(rename = "cd", alias = "ChannelDeleted")] - ChannelDeleted(Box), - #[serde(rename = "pl", alias = "PrimaryLanguageChanged")] - PrimaryLanguageChanged(Box), - #[serde(rename = "gi", alias = "GroupImported")] - GroupImported(Box), - #[serde(rename = "ba")] - BotAdded(Box), - #[serde(rename = "br")] - BotRemoved(Box), - #[serde(rename = "bu")] - BotUpdated(Box), -} - #[derive(Serialize, Deserialize, Clone, Debug)] pub enum CommunityEventInternal { #[serde(rename = "cr", alias = "Created")] @@ -76,7 +26,7 @@ pub enum CommunityEventInternal { #[serde(rename = "dc", alias = "DescriptionChanged")] DescriptionChanged(Box), #[serde(rename = "rc", alias = "RulesChanged")] - RulesChanged(Box), + RulesChanged(Box), #[serde(rename = "ac", alias = "AvatarChanged")] AvatarChanged(Box), #[serde(rename = "bc", alias = "BannerChanged")] @@ -86,7 +36,7 @@ pub enum CommunityEventInternal { #[serde(rename = "mr", alias = "MembersRemoved")] MembersRemoved(Box), #[serde(rename = "rl", alias = "RoleChanged")] - RoleChanged(Box), + RoleChanged(Box), #[serde(rename = "ub", alias = "UsersBlocked")] UsersBlocked(Box), #[serde(rename = "uu", alias = "UsersUnblocked")] @@ -117,53 +67,7 @@ pub enum CommunityEventInternal { BotUpdated(Box), } -#[derive(Serialize, Deserialize, Clone, Debug)] -#[serde(untagged)] -pub enum RulesChangedOrRoleChanged { - RulesChanged(GroupRulesChanged), - RoleChanged(CommunityRoleChanged), -} - -#[derive(CandidType, Serialize, Deserialize, Clone, Debug)] -pub struct GroupRulesChanged { - pub enabled: bool, - pub prev_enabled: bool, - pub changed_by: UserId, -} - -#[derive(CandidType, Serialize, Deserialize, Clone, Debug)] -pub struct CommunityRoleChanged { - pub user_ids: Vec, - pub changed_by: UserId, - pub old_role: CommunityRole, - pub new_role: CommunityRole, -} - impl CommunityEvents { - pub fn fix_role_changed_events(&mut self) { - let mut count_updated = 0; - for event_wrapper in self.stable_events_map.read_all() { - if let CommunityEventInternalOld::RulesChangedOrRoleChanged(r) = event_wrapper.event { - if let RulesChangedOrRoleChanged::RoleChanged(role) = *r { - self.stable_events_map.insert(EventWrapperInternal { - index: event_wrapper.index, - timestamp: event_wrapper.timestamp, - correlation_id: 0, - expires_at: event_wrapper.expires_at, - event: CommunityEventInternal::RoleChanged(Box::new(types::CommunityRoleChanged { - user_ids: role.user_ids, - changed_by: role.changed_by, - old_role: role.old_role, - new_role: role.new_role, - })), - }); - count_updated += 1; - } - } - } - info!(count_updated, "Fixed community events"); - } - pub fn new(name: String, description: String, created_by: UserId, now: TimestampMillis) -> CommunityEvents { let event_index = EventIndex::default(); let event = EventWrapperInternal { diff --git a/backend/canisters/community/impl/src/model/events/stable_memory.rs b/backend/canisters/community/impl/src/model/events/stable_memory.rs index 80d0c7af4e..71eae95322 100644 --- a/backend/canisters/community/impl/src/model/events/stable_memory.rs +++ b/backend/canisters/community/impl/src/model/events/stable_memory.rs @@ -1,8 +1,8 @@ -use crate::model::events::{CommunityEventInternal, CommunityEventInternalOld}; +use crate::model::events::CommunityEventInternal; use candid::Deserialize; use serde::Serialize; -use stable_memory_map::{with_map, with_map_mut, CommunityEventKeyPrefix, KeyPrefix}; -use types::{EventIndex, EventWrapperInternal}; +use stable_memory_map::{with_map_mut, CommunityEventKeyPrefix, KeyPrefix}; +use types::EventWrapperInternal; #[derive(Serialize, Deserialize, Default)] pub struct EventsStableStorage { @@ -10,14 +10,6 @@ pub struct EventsStableStorage { } impl EventsStableStorage { - pub fn read_all(&self) -> Vec> { - with_map(|m| { - m.range(self.prefix.create_key(&EventIndex::default())..) - .map(|(_, bytes)| msgpack::deserialize_then_unwrap(&bytes)) - .collect() - }) - } - pub fn insert(&mut self, event: EventWrapperInternal) { with_map_mut(|m| m.insert(self.prefix.create_key(&event.index), event_to_bytes(event))); } diff --git a/backend/canisters/group_index/CHANGELOG.md b/backend/canisters/group_index/CHANGELOG.md index 02e5fc083b..2cddf9fc74 100644 --- a/backend/canisters/group_index/CHANGELOG.md +++ b/backend/canisters/group_index/CHANGELOG.md @@ -6,12 +6,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] +## [[2.0.1541](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1541-group_index)] - 2024-12-19 + ### Changed - Handle retry attempts when adding a new LocalGroupIndex ([#7091](https://github.com/open-chat-labs/open-chat/pull/7091)) - Add logging + skip steps that have already been completed ([#7093](https://github.com/open-chat-labs/open-chat/pull/7093)) -## [[2.0.1519](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1519-group_index)] - 2024-12-19 +### Fixed + +- Set `wasm_hash` field which was previously empty ([#7097](https://github.com/open-chat-labs/open-chat/pull/7097)) + +## [[2.0.1528](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1528-group_index)] - 2024-12-19 ### Changed diff --git a/backend/canisters/user_index/CHANGELOG.md b/backend/canisters/user_index/CHANGELOG.md index 136cc9890c..a92514ff91 100644 --- a/backend/canisters/user_index/CHANGELOG.md +++ b/backend/canisters/user_index/CHANGELOG.md @@ -6,11 +6,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] +## [[2.0.1542](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1542-user_index)] - 2024-12-19 + ### Changed - Add logging + skip steps that have already been completed ([#7093](https://github.com/open-chat-labs/open-chat/pull/7093)) - Change bot cmd number param values from u16 to f64 ([#7095](https://github.com/open-chat-labs/open-chat/pull/7095)) +### Fixed + +- Set `wasm_hash` field which was previously empty ([#7097](https://github.com/open-chat-labs/open-chat/pull/7097)) + ## [[2.0.1537](https://github.com/open-chat-labs/open-chat/releases/tag/v2.0.1537-user_index)] - 2024-12-19 ### Changed diff --git a/backend/canisters/user_index/api/src/main.rs b/backend/canisters/user_index/api/src/main.rs index 2dc4afe948..4aad21f067 100644 --- a/backend/canisters/user_index/api/src/main.rs +++ b/backend/canisters/user_index/api/src/main.rs @@ -64,5 +64,6 @@ fn main() { generate_ts_method!(user_index, submit_proof_of_unique_personhood); generate_ts_method!(user_index, suspend_user); generate_ts_method!(user_index, unsuspend_user); + generate_ts_method!(user_index, update_bot); generate_ts_method!(user_index, update_diamond_membership_subscription); } diff --git a/frontend/app/src/components/Input.svelte b/frontend/app/src/components/Input.svelte index dfdcba3ba9..80e7c3546b 100644 --- a/frontend/app/src/components/Input.svelte +++ b/frontend/app/src/components/Input.svelte @@ -15,6 +15,8 @@ children?: Snippet; onblur?: () => void; onfocus?: () => void; + oninput?: () => void; + onenter?: () => void; } @@ -40,6 +42,8 @@ pattern = undefined, onblur = undefined, onfocus = undefined, + oninput = undefined, + onenter = undefined, children, }: InputProps = $props(); @@ -61,6 +65,7 @@ value = parseInt(e.currentTarget.value, 10); } dispatch("change", value); + oninput?.(); }; export function setValue(text: string) { @@ -70,6 +75,7 @@ function keyDown(e: KeyboardEvent) { if (e.key === "Enter") { dispatch("enter"); + onenter?.(); } } diff --git a/frontend/app/src/components/bots/AutoBotBuilder.svelte b/frontend/app/src/components/bots/AutoBotBuilder.svelte index 784cc6c24f..69ab28b304 100644 --- a/frontend/app/src/components/bots/AutoBotBuilder.svelte +++ b/frontend/app/src/components/bots/AutoBotBuilder.svelte @@ -2,13 +2,13 @@ import Reload from "svelte-material-icons/Reload.svelte"; import { validEndpoint, - emptyBotInstance, OpenChat, validateBot, ValidationErrors, type ExternalBot, type SlashCommandSchema, type ValidationErrorMessages, + userStore, } from "openchat-client"; import { i18nKey } from "../../i18n/i18n"; import Input from "../Input.svelte"; @@ -23,19 +23,21 @@ import HoverIcon from "../HoverIcon.svelte"; import { iconSize } from "../../stores/iconSize"; import CommandViewer from "./CommandViewer.svelte"; + import SingleUserSelector from "../home/SingleUserSelector.svelte"; const client = getContext("client"); interface Props { valid: boolean; onUpdate: (bot: ExternalBot) => void; + candidate: ExternalBot; + nameDirty: boolean; } - let { valid = $bindable(), onUpdate }: Props = $props(); + let { valid = $bindable(), onUpdate, candidate, nameDirty }: Props = $props(); let selectedCommand = $state(undefined); let selectedCommandIndex = $state(undefined); let debug = $state(false); - let candidate = $state(emptyBotInstance()); let schemaLoaded = $state(false); let schemaLoading = $state(false); let showNext = $derived( @@ -49,7 +51,7 @@ () => [$state.snapshot(candidate)], async () => { const errors = validateBot(candidate); - if (errors.get("bot_name").length == 0) { + if (errors.get("bot_name").length == 0 && nameDirty) { errors.addErrors("bot_name", await checkUsername(candidate.name)); } return errors; @@ -100,7 +102,7 @@ // let editing = $derived(bot !== undefined); $effect(() => { - const isValid = errors.size === 0; + const isValid = errors.size === 0 && schemaLoaded; if (isValid !== valid) { valid = isValid; } @@ -123,6 +125,15 @@ selectedCommandIndex = index; } + function endpointChanged() { + schemaLoaded = false; + candidate.definition = { + kind: "bot_definition", + description: "", + commands: [], + }; + } + function loadDefinition() { if (!schemaLoading && validEndpoint(candidate.endpoint)) { schemaLoading = true; @@ -173,6 +184,22 @@ bind:value={candidate.id}> + + (candidate.ownerId = ev.detail.userId)} + on:userRemoved={(_) => (candidate.ownerId = "")} + selectedReceiver={$userStore.get(candidate.ownerId)} + placeholder={"bots.builder.ownerLabel"} + autofocus={false} /> +
{#if !errors.has("bot_endpoint")} - - + + {/if}
diff --git a/frontend/app/src/components/bots/BotAvatar.svelte b/frontend/app/src/components/bots/BotAvatar.svelte new file mode 100644 index 0000000000..a00751a01e --- /dev/null +++ b/frontend/app/src/components/bots/BotAvatar.svelte @@ -0,0 +1,12 @@ + + + diff --git a/frontend/app/src/components/bots/BotBuilder.svelte b/frontend/app/src/components/bots/BotBuilder.svelte index c744d62671..a5301da0c8 100644 --- a/frontend/app/src/components/bots/BotBuilder.svelte +++ b/frontend/app/src/components/bots/BotBuilder.svelte @@ -1,5 +1,6 @@
- +
- (bot = b)} bind:valid /> + {#if step === "choose"} + {#if myBots.length === 0} + + + + {:else} +

+ +

+
+ {#each myBots as myBot} + + +
selectBot(myBot)} class="match"> + + + +
+

+ {myBot.name} +

+

+ {myBot.definition.description} +

+
+
+ {/each} +
+ {/if} + {:else if step === "edit" && botState.current !== undefined} + (botState.current = b)} + bind:valid /> + {/if}
+ + diff --git a/frontend/app/src/components/bots/BotExplorer.svelte b/frontend/app/src/components/bots/BotExplorer.svelte index 7cfadf5e69..7f84e72415 100644 --- a/frontend/app/src/components/bots/BotExplorer.svelte +++ b/frontend/app/src/components/bots/BotExplorer.svelte @@ -1,25 +1,19 @@
- + {#if firstError !== undefined && showError}
diff --git a/frontend/app/src/components/bots/botState.ts b/frontend/app/src/components/bots/botState.ts index 7c63c414dd..6b0926b3e8 100644 --- a/frontend/app/src/components/bots/botState.ts +++ b/frontend/app/src/components/bots/botState.ts @@ -79,7 +79,7 @@ export const commands = derived( ...c, kind: b.kind, botName: b.name, - botIcon: b.avatarUrl, + avatarUrl: b.avatarUrl, botId: b.id, botEndpoint: b.endpoint, botDescription: b.definition.description, diff --git a/frontend/app/src/components/home/Home.svelte b/frontend/app/src/components/home/Home.svelte index 785fcf2ecd..6ded09c3f7 100644 --- a/frontend/app/src/components/home/Home.svelte +++ b/frontend/app/src/components/home/Home.svelte @@ -182,6 +182,7 @@ | { kind: "verify_humanity" } | { kind: "select_chat" } | { kind: "register_bot" } + | { kind: "update_bot" } | { kind: "suspended" } | { kind: "no_access" } | { kind: "new_group"; embeddedContent: boolean; candidate: CandidateGroupChat } @@ -270,7 +271,7 @@ } else if (ev instanceof RegisterBot) { modal = { kind: "register_bot" }; } else if (ev instanceof UpdateBot) { - modal = { kind: "register_bot" }; + modal = { kind: "update_bot" }; } else if (ev instanceof SummonWitch) { summonWitch(); } else if (ev instanceof RemoteVideoCallStartedEvent) { @@ -1333,7 +1334,9 @@ {:else if modal.kind === "suspended"} {:else if modal.kind === "register_bot"} - + + {:else if modal.kind === "update_bot"} + {:else if modal.kind === "no_access"} {:else if modal.kind === "not_found"} diff --git a/frontend/app/src/components/home/MakeProposalModal.svelte b/frontend/app/src/components/home/MakeProposalModal.svelte index 64cf2e07db..34dc25f96e 100644 --- a/frontend/app/src/components/home/MakeProposalModal.svelte +++ b/frontend/app/src/components/home/MakeProposalModal.svelte @@ -14,8 +14,10 @@ type Treasury, currentUser as user, cryptoBalance as cryptoBalanceStore, + currentUser, } from "openchat-client"; import { + emptyBotInstance, isPrincipalValid, isSubAccountValid, isUrl, @@ -101,7 +103,7 @@ let refreshingBalance = false; let balanceWithRefresh: BalanceWithRefresh; let achivementName = ""; - let candidateBot: ExternalBot | undefined = undefined; + let candidateBot: ExternalBot = emptyBotInstance($currentUser.userId); let candidateBotValid = false; $: errorMessage = @@ -511,6 +513,8 @@