mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Early support for managing bots in the room
Known drawbacks: * Cannot remove bots * Cannot use upstream neb instances
This commit is contained in:
parent
dcda2fa46e
commit
947ecd43cd
@ -5,6 +5,7 @@ import { Cache, CACHE_INTEGRATIONS } from "../../MemoryCache";
|
||||
import { Integration } from "../../integrations/Integration";
|
||||
import { ApiError } from "../ApiError";
|
||||
import { WidgetStore } from "../../db/WidgetStore";
|
||||
import { NebStore } from "../../db/NebStore";
|
||||
|
||||
export interface IntegrationsResponse {
|
||||
widgets: Widget[],
|
||||
@ -14,14 +15,18 @@ export interface IntegrationsResponse {
|
||||
export class DimensionIntegrationsService {
|
||||
|
||||
public static async getIntegrations(isEnabledCheck?: boolean): Promise<IntegrationsResponse> {
|
||||
const cachedWidgets = Cache.for(CACHE_INTEGRATIONS).get("integrations_" + isEnabledCheck);
|
||||
if (cachedWidgets) {
|
||||
return {widgets: cachedWidgets};
|
||||
const cachedIntegrations = Cache.for(CACHE_INTEGRATIONS).get("integrations_" + isEnabledCheck);
|
||||
if (cachedIntegrations) {
|
||||
return cachedIntegrations;
|
||||
}
|
||||
|
||||
const widgets = await WidgetStore.listAll(isEnabledCheck);
|
||||
Cache.for(CACHE_INTEGRATIONS).put("integrations_" + isEnabledCheck, widgets);
|
||||
return {widgets: widgets};
|
||||
const integrations = {
|
||||
widgets: await WidgetStore.listAll(isEnabledCheck),
|
||||
bots: await NebStore.listSimpleBots(), // No enabled check - managed internally
|
||||
};
|
||||
|
||||
Cache.for(CACHE_INTEGRATIONS).put("integrations_" + isEnabledCheck, integrations);
|
||||
return integrations;
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -9,6 +9,7 @@ import NebBotUser from "./models/NebBotUser";
|
||||
import NebNotificationUser from "./models/NebNotificationUser";
|
||||
import { AppserviceStore } from "./AppserviceStore";
|
||||
import config from "../config";
|
||||
import { SimpleBot } from "../integrations/SimpleBot";
|
||||
|
||||
export interface SupportedIntegration {
|
||||
type: string;
|
||||
@ -32,16 +33,19 @@ export class NebStore {
|
||||
name: "Echo",
|
||||
avatarUrl: "/img/avatars/echo.png", // TODO: Make this image
|
||||
description: "Repeats text given to it from !echo",
|
||||
simple: true,
|
||||
},
|
||||
"giphy": {
|
||||
name: "Giphy",
|
||||
avatarUrl: "/img/avatars/giphy.png",
|
||||
description: "Posts a GIF from Giphy using !giphy <query>",
|
||||
simple: true,
|
||||
},
|
||||
"guggy": {
|
||||
name: "Guggy",
|
||||
avatarUrl: "/img/avatars/guggy.png",
|
||||
description: "Send a reaction GIF using !guggy <query>",
|
||||
simple: true,
|
||||
},
|
||||
// TODO: Support Github
|
||||
// "github": {
|
||||
@ -53,11 +57,13 @@ export class NebStore {
|
||||
name: "Google",
|
||||
avatarUrl: "/img/avatars/google.png",
|
||||
description: "Searches Google Images using !google image <query>",
|
||||
simple: true,
|
||||
},
|
||||
"imgur": {
|
||||
name: "Imgur",
|
||||
avatarUrl: "/img/avatars/imgur.png",
|
||||
description: "Searches and posts images from Imgur using !imgur <query>",
|
||||
simple: true,
|
||||
},
|
||||
// TODO: Support JIRA
|
||||
// "jira": {
|
||||
@ -79,9 +85,34 @@ export class NebStore {
|
||||
name: "Wikipedia",
|
||||
avatarUrl: "/img/avatars/wikipedia.png",
|
||||
description: "Searches wikipedia using !wikipedia <query>",
|
||||
simple: true,
|
||||
},
|
||||
};
|
||||
|
||||
public static async listSimpleBots(): Promise<SimpleBot[]> {
|
||||
const configs = await NebStore.getAllConfigs();
|
||||
const integrations: { integration: NebIntegration, userId: string }[] = [];
|
||||
const hasTypes: string[] = [];
|
||||
|
||||
for (const config of configs) {
|
||||
for (const integration of config.dbIntegrations) {
|
||||
if (!integration.isEnabled) continue;
|
||||
|
||||
const metadata = NebStore.INTEGRATIONS[integration.type];
|
||||
if (!metadata || !metadata.simple) continue;
|
||||
if (hasTypes.indexOf(integration.type) !== -1) continue;
|
||||
|
||||
// TODO: Handle case of upstream bots
|
||||
const user = await NebStore.getOrCreateBotUser(config.id, integration.type);
|
||||
|
||||
integrations.push({integration: integration, userId: user.appserviceUserId});
|
||||
hasTypes.push(integration.type);
|
||||
}
|
||||
}
|
||||
|
||||
return integrations.map(i => new SimpleBot(i.integration, i.userId));
|
||||
}
|
||||
|
||||
public static async getAllConfigs(): Promise<NebConfig[]> {
|
||||
const configs = await NebConfiguration.findAll();
|
||||
return Promise.all((configs || []).map(c => NebStore.getConfig(c.id)));
|
||||
|
@ -25,7 +25,7 @@ export class Integration {
|
||||
}
|
||||
|
||||
export interface IntegrationRequirement {
|
||||
condition: "publicRoom" | "canSendEventTypes";
|
||||
condition: "publicRoom" | "canSendEventTypes" | "userInRoom";
|
||||
argument: any;
|
||||
|
||||
// For publicRoom this is true or false (boolean)
|
||||
|
13
src/integrations/SimpleBot.ts
Normal file
13
src/integrations/SimpleBot.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Integration } from "./Integration";
|
||||
import NebIntegration from "../db/models/NebIntegration";
|
||||
|
||||
export class SimpleBot extends Integration {
|
||||
constructor(bot: NebIntegration, public userId: string) {
|
||||
super(bot);
|
||||
this.category = "bot";
|
||||
this.requirements = [];
|
||||
|
||||
// We're going to go ahead and claim that none of the bots are supported in e2e rooms
|
||||
this.isEncryptionSupported = false;
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ export class NebConfig {
|
||||
public appserviceId?: string;
|
||||
public upstreamId?: number;
|
||||
public integrations: Integration[];
|
||||
public dbIntegrations: NebIntegration[];
|
||||
|
||||
public constructor(config: NebConfiguration, integrations: NebIntegration[]) {
|
||||
this.id = config.id;
|
||||
@ -15,5 +16,6 @@ export class NebConfig {
|
||||
this.appserviceId = config.appserviceId;
|
||||
this.upstreamId = config.upstreamId;
|
||||
this.integrations = integrations.map(i => new Integration(i));
|
||||
this.dbIntegrations = integrations;
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { ScalarClientApiService } from "../../shared/services/scalar/scalar-client-api.service";
|
||||
import * as _ from "lodash";
|
||||
import { ScalarServerApiService } from "../../shared/services/scalar/scalar-server-api.service";
|
||||
import { FE_Integration, FE_IntegrationRequirement } from "../../shared/models/integration";
|
||||
import { FE_Integration, FE_IntegrationRequirement, FE_SimpleBot } from "../../shared/models/integration";
|
||||
import { IntegrationsRegistry } from "../../shared/registry/integrations.registry";
|
||||
import { SessionStorage } from "../../shared/SessionStorage";
|
||||
import { AdminApiService } from "../../shared/services/admin/admin-api.service";
|
||||
@ -129,13 +129,15 @@ export class RiotHomeComponent {
|
||||
|
||||
if (integration.category === "bot") {
|
||||
// It's a bot
|
||||
const bot = <FE_SimpleBot>integration;
|
||||
// TODO: "Are you sure?" dialog
|
||||
|
||||
// let promise = null;
|
||||
const promise = Promise.resolve();
|
||||
// if (!integration._inRoom) {
|
||||
// promise = this.scalar.inviteUser(this.roomId, integration.userId);
|
||||
// } else promise = this.api.removeIntegration(this.roomId, integration.type, integration.integrationType, this.scalarToken);
|
||||
let promise:Promise<any> = Promise.resolve();
|
||||
if (!integration._inRoom) {
|
||||
promise = this.scalar.inviteUser(this.roomId, bot.userId);
|
||||
}
|
||||
// TODO: Handle removal of bots
|
||||
// else promise = this.api.removeIntegration(this.roomId, integration.type, integration.integrationType, this.scalarToken);
|
||||
// We set this ahead of the promise for debouncing
|
||||
|
||||
integration._inRoom = !integration._inRoom;
|
||||
@ -228,11 +230,16 @@ export class RiotHomeComponent {
|
||||
console.log("Failed to find integration component for category=" + category + " type=" + type);
|
||||
}
|
||||
|
||||
private updateIntegrationState(integration: FE_Integration) {
|
||||
private async updateIntegrationState(integration: FE_Integration) {
|
||||
if (!integration.requirements) return;
|
||||
|
||||
let promises = integration.requirements.map(r => this.checkRequirement(r));
|
||||
|
||||
if (integration.category === "bot") {
|
||||
const state = await this.scalar.getMembershipState(this.roomId, (<FE_SimpleBot>integration).userId);
|
||||
integration._inRoom = ["join", "invite"].indexOf(state.response.membership) !== -1;
|
||||
}
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
integration._isSupported = true;
|
||||
integration._notSupportedReason = null;
|
||||
|
@ -16,6 +16,10 @@ export interface FE_Integration {
|
||||
_notSupportedReason: string;
|
||||
}
|
||||
|
||||
export interface FE_SimpleBot extends FE_Integration {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
export interface FE_Widget extends FE_Integration {
|
||||
options: any;
|
||||
}
|
||||
|
BIN
web/public/img/avatars/echo.png
Normal file
BIN
web/public/img/avatars/echo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
Loading…
Reference in New Issue
Block a user