Skip to content

Commit

Permalink
A chunk of bots progress (#7049)
Browse files Browse the repository at this point in the history
  • Loading branch information
julianjelfs authored Dec 12, 2024
1 parent 0d8776a commit ee91b5a
Show file tree
Hide file tree
Showing 101 changed files with 2,848 additions and 723 deletions.
2 changes: 2 additions & 0 deletions backend/canisters/community/api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ fn main() {
generate_ts_method!(community, video_call_participants);

generate_ts_method!(community, accept_p2p_swap);
generate_ts_method!(community, add_bot);
generate_ts_method!(community, add_members_to_channel);
generate_ts_method!(community, add_reaction);
generate_ts_method!(community, block_user);
Expand All @@ -122,6 +123,7 @@ fn main() {
generate_ts_method!(community, register_poll_vote);
generate_ts_method!(community, register_proposal_vote);
generate_ts_method!(community, register_proposal_vote_v2);
generate_ts_method!(community, remove_bot);
generate_ts_method!(community, remove_member_from_channel);
generate_ts_method!(community, remove_member);
generate_ts_method!(community, remove_reaction);
Expand Down
2 changes: 2 additions & 0 deletions backend/canisters/group/api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ fn main() {
generate_ts_method!(group, video_call_participants);

generate_ts_method!(group, accept_p2p_swap);
generate_ts_method!(group, add_bot);
generate_ts_method!(group, add_reaction);
generate_ts_method!(group, block_user);
generate_ts_method!(group, cancel_invites);
Expand All @@ -96,6 +97,7 @@ fn main() {
generate_ts_method!(group, register_poll_vote);
generate_ts_method!(group, register_proposal_vote);
generate_ts_method!(group, register_proposal_vote_v2);
generate_ts_method!(group, remove_bot);
generate_ts_method!(group, remove_participant);
generate_ts_method!(group, remove_reaction);
generate_ts_method!(group, report_message);
Expand Down
3 changes: 3 additions & 0 deletions backend/canisters/user_index/api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ fn main() {
std::fs::remove_dir_all(&directory).unwrap();
}

generate_ts_method!(user_index, bot_updates);
generate_ts_method!(user_index, check_username);
generate_ts_method!(user_index, chit_leaderboard);
generate_ts_method!(user_index, current_user);
generate_ts_method!(user_index, external_achievements);
generate_ts_method!(user_index, diamond_membership_fees);
generate_ts_method!(user_index, explore_bots);
generate_ts_method!(user_index, platform_moderators);
generate_ts_method!(user_index, platform_moderators_group);
generate_ts_method!(user_index, platform_operators);
Expand All @@ -55,6 +57,7 @@ fn main() {

generate_ts_method!(user_index, delete_user);
generate_ts_method!(user_index, pay_for_diamond_membership);
generate_ts_method!(user_index, register_bot);
generate_ts_method!(user_index, set_diamond_membership_fees);
generate_ts_method!(user_index, set_display_name);
generate_ts_method!(user_index, set_user_upgrade_concurrency);
Expand Down
4 changes: 2 additions & 2 deletions backend/libraries/types/src/bots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub enum SlashCommandParamType {
pub struct StringParam {
pub min_length: u16,
pub max_length: u16,
#[ts(as = "SlashCommandOptionChoiceString")]
#[ts(as = "Vec<SlashCommandOptionChoiceString>")]
pub choices: Vec<SlashCommandOptionChoice<String>>,
}

Expand All @@ -46,7 +46,7 @@ pub struct StringParam {
pub struct NumberParam {
pub min_length: u16,
pub max_length: u16,
#[ts(as = "SlashCommandOptionChoiceU16")]
#[ts(as = "Vec<SlashCommandOptionChoiceU16>")]
pub choices: Vec<SlashCommandOptionChoice<u16>>,
}

Expand Down
37 changes: 37 additions & 0 deletions frontend/app/public/assets/bot_avatar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 0 additions & 6 deletions frontend/app/src/components/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import InstallPrompt from "./home/InstallPrompt.svelte";
import NotificationsBar from "./home/NotificationsBar.svelte";
import { reviewingTranslations } from "../i18n/i18n";
import { bots as botsStore } from "./bots/botState";
overrideItemIdKeyNameBeforeInitialisingDndZones("_id");
Expand Down Expand Up @@ -116,11 +115,6 @@
$identityState.kind === "upgrading_user" || $identityState.kind === "upgrade_user",
);
$effect(() => {
// TODO - this will not be like this in the end but just for now ...
client.getBots(false).then((bots) => botsStore.set(bots));
});
$effect(() => {
// subscribe to the rtl store so that we can set the overall page direction at the right time
document.dir = $rtlStore ? "rtl" : "ltr";
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/src/components/UsernameInput.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
function checkUsername(value: string) {
const promise = client
.checkUsername(value)
.checkUsername(value, false)
.then((resp) => {
if (promise !== currentPromise) {
return;
Expand Down
34 changes: 16 additions & 18 deletions frontend/app/src/components/bots/BotBuilder.svelte
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts">
import {
emptyBotInstance,
emptySlashCommandPermissions,
validateBot,
ValidationErrors,
type ExternalBot,
type SlashCommandPermissions,
type SlashCommandSchema,
} from "openchat-client";
import { i18nKey } from "../../i18n/i18n";
Expand Down Expand Up @@ -33,10 +33,7 @@
let errors = $derived.by(
debouncedDerived(
() => [$state.snapshot(candidate)],
() => {
console.log("Validating candidate");
return validateBot(candidate);
},
() => validateBot(candidate),
300,
new ValidationErrors(),
),
Expand All @@ -53,12 +50,11 @@
});
$effect(() => {
console.log("Candidate updated");
onUpdate($state.snapshot(candidate));
});
function botAvatarSelected(ev: CustomEvent<{ url: string; data: Uint8Array }>) {
candidate.avatar = ev.detail.url;
candidate.avatarUrl = ev.detail.url;
}
function onSubmit(e: Event) {
Expand All @@ -85,16 +81,7 @@
name: "",
description: "",
params: [],
permissions: emptyPermissions(),
};
}
function emptyPermissions(): SlashCommandPermissions {
return {
chatPermissions: [],
communityPermissions: [],
messagePermissions: [],
threadPermissions: [],
permissions: emptySlashCommandPermissions(),
};
}
</script>
Expand All @@ -114,10 +101,21 @@
<EditableAvatar
overlayIcon
size={"medium"}
image={candidate.avatar}
image={candidate.avatarUrl}
on:imageSelected={botAvatarSelected} />
</div>

<Legend required label={i18nKey("bots.builder.principalLabel")}></Legend>
<ValidatingInput
autofocus
minlength={3}
maxlength={50}
invalid={errors.has("bot_principal")}
placeholder={i18nKey("bots.builder.principalPlaceholder")}
error={errors.get("bot_principal")}
bind:value={candidate.id}>
</ValidatingInput>

<Legend
required
label={i18nKey("bots.builder.nameLabel")}
Expand Down
61 changes: 53 additions & 8 deletions frontend/app/src/components/bots/BotBuilderModal.svelte
Original file line number Diff line number Diff line change
@@ -1,25 +1,70 @@
<script lang="ts">
import { currentUser, emptyBotInstance, OpenChat } from "openchat-client";
import { i18nKey } from "../../i18n/i18n";
import ModalContent from "../ModalContent.svelte";
import Translatable from "../Translatable.svelte";
import BotBuilder from "./BotBuilder.svelte";
import Button from "../Button.svelte";
import { mobileWidth } from "../../stores/screenDimensions";
import { getContext } from "svelte";
import { toastStore } from "../../stores/toast";
import ButtonGroup from "../ButtonGroup.svelte";
// This is just a dummy modal for dev purposes. For the real thing the bot builder
// will be embedded in the make proposal UI
const client = getContext<OpenChat>("client");
interface Props {
onClose: () => void;
}
let { onClose }: Props = $props();
let valid = $state(false);
let registering = $state(false);
let bot = $state(emptyBotInstance());
function onUpdate() {}
function register() {
if (bot !== undefined && valid) {
registering = true;
const snapshot = $state.snapshot(bot);
client
.registerBot({
...snapshot,
ownerId: $currentUser.userId,
})
.then((success) => {
if (!success) {
toastStore.showFailureToast(i18nKey("Unable to register test bot"));
} else {
console.log("Bot registered");
onClose();
}
})
.finally(() => (registering = false));
}
}
</script>

<ModalContent on:close>
<ModalContent on:close={onClose}>
<div class="header" slot="header">
<Translatable resourceKey={i18nKey("bots.builder.title")}></Translatable>
</div>
<div class="body" slot="body">
<BotBuilder {onUpdate} bind:valid />
<BotBuilder onUpdate={(b) => (bot = b)} bind:valid />
</div>
<div class="footer" slot="footer">
<ButtonGroup>
<Button secondary small={!$mobileWidth} tiny={$mobileWidth} on:click={onClose}>
<Translatable resourceKey={i18nKey("cancel")} />
</Button>
<Button
on:click={register}
disabled={!valid || registering}
loading={registering}
small={!$mobileWidth}
tiny={$mobileWidth}>
<Translatable resourceKey={i18nKey("Register")} />
</Button>
</ButtonGroup>
</div>
</ModalContent>

<style lang="scss">
</style>
76 changes: 76 additions & 0 deletions frontend/app/src/components/bots/BotExplorer.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<script lang="ts">
import { i18nKey, type CommunitySummary, type OpenChat } from "openchat-client";
import Search from "../Search.svelte";
import { getContext } from "svelte";
import { botSearchState } from "../../stores/search.svelte";
import Button from "../Button.svelte";
import Translatable from "../Translatable.svelte";
import BotMatch from "./BotMatch.svelte";
const client = getContext<OpenChat>("client");
const PAGE_SIZE = 50;
interface Props {
community: CommunitySummary;
}
let { community }: Props = $props();
let initialised = $state(false);
let searching = $state(false);
let more = $derived(botSearchState.total > botSearchState.results.length);
function onSearchEntered(reset = false) {
searching = true;
if (reset) {
botSearchState.reset();
} else {
botSearchState.nextPage();
}
console.log("Search entered: ", botSearchState.term);
client
.exploreBots(
botSearchState.term === "" ? undefined : botSearchState.term,
botSearchState.index,
PAGE_SIZE,
)
.then((results) => {
console.log("Results: ", results);
if (results.kind === "success") {
if (reset) {
botSearchState.results = results.matches;
} else {
botSearchState.appendResults(results.matches);
}
botSearchState.total = results.total;
}
})
.finally(() => (searching = false));
}
$effect(() => {
if (!initialised) {
onSearchEntered(true);
initialised = true;
}
});
</script>

<Search
on:searchEntered={() => onSearchEntered(true)}
searching={false}
bind:searchTerm={botSearchState.term}
placeholder={i18nKey("search")} />

{#if more}
<div class="more">
<Button disabled={searching} loading={searching} on:click={() => onSearchEntered(false)}
><Translatable resourceKey={i18nKey("bots.explorer.loadMore")} /></Button>
</div>
{/if}

{#each botSearchState.results as match}
<BotMatch {community} {match} />
{/each}

<style lang="scss"></style>
Loading

0 comments on commit ee91b5a

Please sign in to comment.