Back stickerpacks with rooms and use appservices to do so
This commit is contained in:
parent
bac85a44a2
commit
910d4f3b56
23
README.md
23
README.md
|
@ -1,9 +1,9 @@
|
|||
# matrix-sticker-bot
|
||||
# matrix-sticker-manager
|
||||
|
||||
[![#stickerbot:t2bot.io](https://img.shields.io/badge/matrix-%23stickerbot:t2bot.io-brightgreen.svg)](https://matrix.to/#/#stickerbot:t2bot.io)
|
||||
[![TravisCI badge](https://travis-ci.org/turt2live/matrix-sticker-bot.svg?branch=master)](https://travis-ci.org/turt2live/matrix-sticker-bot)
|
||||
[![#stickermanager:t2bot.io](https://img.shields.io/badge/matrix-%23stickermanager:t2bot.io-brightgreen.svg)](https://matrix.to/#/#stickermanager:t2bot.io)
|
||||
[![TravisCI badge](https://travis-ci.org/turt2live/matrix-sticker-bot.svg?branch=master)](https://travis-ci.org/turt2live/matrix-sticker-manager)
|
||||
|
||||
A matrix bot to allow users to make their own sticker packs.
|
||||
A matrix service to allow users to make their own sticker packs.
|
||||
|
||||
# Usage
|
||||
|
||||
|
@ -19,3 +19,18 @@ A matrix bot to allow users to make their own sticker packs.
|
|||
3. `npm run build`
|
||||
4. Copy `config/default.yaml` to `config/production.yaml`
|
||||
5. Run the bot with `NODE_ENV=production node index.js`
|
||||
|
||||
You will also need to create an appservice registration file and add it to your homeserver:
|
||||
```yaml
|
||||
id: sticker-manager
|
||||
url: http://localhost:8082
|
||||
as_token: "YOUR_AS_TOKEN"
|
||||
hs_token: "YOUR_HS_TOKEN"
|
||||
sender_localpart: "stickers"
|
||||
namespaces:
|
||||
users: []
|
||||
rooms: []
|
||||
aliases:
|
||||
- exclusive: true
|
||||
regex: "#_stickerpack_.+:t2bot.io"
|
||||
```
|
|
@ -1,5 +1,9 @@
|
|||
homeserverUrl: "https://t2bot.io"
|
||||
accessToken: "YOUR_TOKEN_HERE"
|
||||
# The application service settings
|
||||
appservice:
|
||||
domainName: "t2bot.io"
|
||||
homeserverUrl: "https://t2bot.io"
|
||||
asToken: "SECRET_TOKEN_HERE"
|
||||
hsToken: "DIFFERENT_TOKEN_HERE"
|
||||
|
||||
# The webserver settings
|
||||
webserver:
|
||||
|
@ -19,17 +23,5 @@ media:
|
|||
# Requires turt2live/matrix-media-repo
|
||||
useMediaInfo: false
|
||||
|
||||
# The database options
|
||||
database:
|
||||
# The relative path to the sqlite database
|
||||
file: "stickerbot.db"
|
||||
|
||||
# Settings for controlling how logging works
|
||||
logging:
|
||||
file: logs/stickerbot.log
|
||||
console: true
|
||||
consoleLevel: info
|
||||
fileLevel: verbose
|
||||
rotate:
|
||||
size: 52428800 # bytes, default is 50mb
|
||||
count: 5
|
||||
# Where to store misc files
|
||||
dataPath: "/etc/stickerbot/data"
|
||||
|
|
2059
package-lock.json
generated
2059
package-lock.json
generated
File diff suppressed because it is too large
Load diff
29
package.json
29
package.json
|
@ -1,34 +1,25 @@
|
|||
{
|
||||
"name": "matrix-sticker-bot",
|
||||
"name": "matrix-sticker-manager",
|
||||
"version": "1.0.0",
|
||||
"description": "A matrix bot to allow user-generated sticker packs to be created",
|
||||
"description": "A matrix service to allow user-generated sticker packs to be created",
|
||||
"main": "./lib/index.js",
|
||||
"author": "Travis Ralston",
|
||||
"license": "GPL-3.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/turt2live/matrix-sticker-bot.git"
|
||||
"url": "git+https://github.com/turt2live/matrix-sticker-manager.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^9.4.6",
|
||||
"config": "^1.29.4",
|
||||
"express": "^4.16.3",
|
||||
"js-yaml": "^3.10.0",
|
||||
"matrix-bot-sdk": "^0.1.8",
|
||||
"matrix-js-snippets": "^0.2.5",
|
||||
"mkdirp": "^0.5.1",
|
||||
"node-localstorage": "^1.3.0",
|
||||
"@types/node": "^10.14.1",
|
||||
"config": "^3.0.1",
|
||||
"js-yaml": "^3.12.2",
|
||||
"matrix-bot-sdk": "^0.3.3",
|
||||
"random-string": "^0.2.0",
|
||||
"reflect-metadata": "^0.1.12",
|
||||
"sequelize": "^4.37.6",
|
||||
"sequelize-typescript": "^0.6.3",
|
||||
"sqlite": "^2.9.1",
|
||||
"striptags": "^3.1.1",
|
||||
"umzug": "^2.1.0"
|
||||
"striptags": "^3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tslint": "^5.9.1",
|
||||
"typescript": "^2.7.2"
|
||||
"tslint": "^5.14.0",
|
||||
"typescript": "^3.3.3333"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import { IFilterInfo, IStorageProvider } from "matrix-bot-sdk";
|
||||
import { LocalStorage } from "node-localstorage";
|
||||
import * as mkdirp from "mkdirp";
|
||||
|
||||
export class LocalstorageStorageProvider implements IStorageProvider {
|
||||
|
||||
private kvStore: Storage;
|
||||
|
||||
constructor(path: string) {
|
||||
mkdirp.sync(path);
|
||||
this.kvStore = new LocalStorage(path, 100 * 1024 * 1024); // quota is 100mb
|
||||
}
|
||||
|
||||
setSyncToken(token: string | null): void {
|
||||
this.kvStore.setItem("sync_token", token);
|
||||
}
|
||||
|
||||
getSyncToken(): string | null {
|
||||
return this.kvStore.getItem("sync_token");
|
||||
}
|
||||
|
||||
setFilter(filter: IFilterInfo): void {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
getFilter(): IFilterInfo {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,24 +1,19 @@
|
|||
import { MatrixClient } from "matrix-bot-sdk";
|
||||
import { LogService, MatrixClient } from "matrix-bot-sdk";
|
||||
import { StickerPackBuilder } from "./builder";
|
||||
import config from "../config";
|
||||
import { LogService } from "matrix-js-snippets";
|
||||
|
||||
export interface Sticker {
|
||||
description: string;
|
||||
contentUri: string;
|
||||
}
|
||||
import { StickerMetadata } from "../storage/StickerStore";
|
||||
|
||||
export class GatherStickersStage implements StickerPackBuilder {
|
||||
|
||||
public stickers: Sticker[] = [];
|
||||
private currentSticker: Sticker = {description: "", contentUri: ""};
|
||||
public stickers: StickerMetadata[] = [];
|
||||
private currentSticker: StickerMetadata = {description: "", contentUri: ""};
|
||||
private expectingImage = true;
|
||||
private resolveFn: (stickers: Sticker[]) => void;
|
||||
private resolveFn: (stickers: StickerMetadata[]) => void;
|
||||
|
||||
constructor(private client: MatrixClient, private roomId: string) {
|
||||
}
|
||||
|
||||
public start(): Promise<Sticker[]> {
|
||||
public start(): Promise<StickerMetadata[]> {
|
||||
return new Promise((resolve, _reject) => {
|
||||
this.resolveFn = resolve;
|
||||
});
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import { StickerPackBuilder } from "./builder";
|
||||
import { MatrixClient } from "matrix-bot-sdk";
|
||||
import { GatherStickersStage, Sticker } from "./GatherStickersStage";
|
||||
import { LogService, MatrixClient } from "matrix-bot-sdk";
|
||||
import { GatherStickersStage } from "./GatherStickersStage";
|
||||
import * as randomString from "random-string";
|
||||
import Stickerpack from "../db/models/Stickerpack";
|
||||
import StickerRecord from "../db/models/StickerRecord";
|
||||
import config from "../config";
|
||||
import { StickerMetadata, StickerStore } from "../storage/StickerStore";
|
||||
|
||||
|
||||
export class NewPackBuilder implements StickerPackBuilder {
|
||||
|
@ -13,7 +12,7 @@ export class NewPackBuilder implements StickerPackBuilder {
|
|||
private expectingName = true;
|
||||
private gatherStage: GatherStickersStage;
|
||||
|
||||
constructor(private client: MatrixClient, private roomId: string) {
|
||||
constructor(private client: MatrixClient, private roomId: string, private store: StickerStore) {
|
||||
client.sendNotice(roomId, "Woot! A new sticker pack. What should we call it?");
|
||||
this.gatherStage = new GatherStickersStage(client, roomId);
|
||||
}
|
||||
|
@ -33,24 +32,23 @@ export class NewPackBuilder implements StickerPackBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private async createStickerPack(stickers: Sticker[]): Promise<any> {
|
||||
private async createStickerPack(stickers: StickerMetadata[]): Promise<any> {
|
||||
const members = await this.client.getJoinedRoomMembers(this.roomId);
|
||||
const selfId = await this.client.getUserId();
|
||||
const creatorId = members.filter(m => m !== selfId)[0];
|
||||
if (!creatorId) throw new Error("Could not find a user ID to own this sticker pack");
|
||||
|
||||
const packId = (randomString({length: 10}) + "-" + this.name.replace(/[^a-zA-Z0-9-]/g, '-')).substring(0, 30);
|
||||
const pack = await Stickerpack.create({id: packId, creatorId: creatorId, name: this.name});
|
||||
|
||||
for (const sticker of stickers) {
|
||||
await StickerRecord.create({
|
||||
packId: packId,
|
||||
description: sticker.description,
|
||||
contentUri: sticker.contentUri,
|
||||
});
|
||||
}
|
||||
const pack = await this.store.createStickerpack({
|
||||
id: packId,
|
||||
name: this.name,
|
||||
creatorId: creatorId,
|
||||
stickers: stickers,
|
||||
});
|
||||
LogService.info("NewPackBuilder", `Pack for ${creatorId} created in room ${pack.roomId}`);
|
||||
|
||||
const slug = `${creatorId}/${packId}`;
|
||||
const slug = `pack/${creatorId}/${packId}`;
|
||||
const baseUrl = config.webserver.publicUrl;
|
||||
const url = (baseUrl.endsWith("/") ? baseUrl : baseUrl + "/") + slug;
|
||||
return this.client.sendNotice(this.roomId, "Awesome! I've created your sticker pack and published it here: " + url);
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import * as config from "config";
|
||||
import { LogConfig } from "matrix-js-snippets";
|
||||
|
||||
interface IConfig {
|
||||
homeserverUrl: string;
|
||||
accessToken: string;
|
||||
appservice: {
|
||||
domainName: string;
|
||||
homeserverUrl: string;
|
||||
asToken: string;
|
||||
hsToken: string;
|
||||
};
|
||||
webserver: {
|
||||
port: number;
|
||||
bind: string;
|
||||
|
@ -13,10 +16,7 @@ interface IConfig {
|
|||
useLocalCopy: boolean;
|
||||
useMediaInfo: boolean;
|
||||
};
|
||||
database: {
|
||||
file: string;
|
||||
};
|
||||
logging: LogConfig;
|
||||
dataPath: string;
|
||||
}
|
||||
|
||||
export default <IConfig>config;
|
|
@ -1,43 +0,0 @@
|
|||
import { Model, Sequelize } from "sequelize-typescript";
|
||||
import { LogService } from "matrix-js-snippets";
|
||||
import config from "../config";
|
||||
import * as path from "path";
|
||||
import * as Umzug from "umzug";
|
||||
import Stickerpack from "./models/Stickerpack";
|
||||
import Sticker from "./models/StickerRecord";
|
||||
|
||||
class _StickerStore {
|
||||
private sequelize: Sequelize;
|
||||
|
||||
constructor() {
|
||||
this.sequelize = new Sequelize({
|
||||
dialect: 'sqlite',
|
||||
database: "stickerbot",
|
||||
storage: config.database.file,
|
||||
username: "",
|
||||
password: "",
|
||||
logging: i => LogService.verbose("StickerStore [SQL]", i)
|
||||
});
|
||||
this.sequelize.addModels(<Array<typeof Model>>[
|
||||
Sticker,
|
||||
Stickerpack,
|
||||
]);
|
||||
}
|
||||
|
||||
public updateSchema(): Promise<any> {
|
||||
LogService.info("StickerStore", "Updating schema...");
|
||||
|
||||
const migrator = new Umzug({
|
||||
storage: "sequelize",
|
||||
storageOptions: {sequelize: this.sequelize},
|
||||
migrations: {
|
||||
params: [this.sequelize.getQueryInterface()],
|
||||
path: path.join(__dirname, "migrations"),
|
||||
},
|
||||
});
|
||||
|
||||
return migrator.up();
|
||||
}
|
||||
}
|
||||
|
||||
export const StickerStore = new _StickerStore();
|
|
@ -1,29 +0,0 @@
|
|||
import { QueryInterface } from "sequelize";
|
||||
import { DataType } from "sequelize-typescript";
|
||||
|
||||
export default {
|
||||
up: (queryInterface: QueryInterface) => {
|
||||
return Promise.resolve()
|
||||
.then(() => queryInterface.createTable("stickerpacks", {
|
||||
"id": {type: DataType.STRING, primaryKey: true, allowNull: false},
|
||||
"creatorId": {type: DataType.STRING, allowNull: false},
|
||||
"name": {type: DataType.STRING, allowNull: false},
|
||||
}))
|
||||
.then(() => queryInterface.createTable("stickers", {
|
||||
"id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false},
|
||||
"packId": {
|
||||
type: DataType.STRING,
|
||||
allowNull: false,
|
||||
references: {model: "stickerpacks", key: "id"},
|
||||
onUpdate: "cascade", onDelete: "cascade",
|
||||
},
|
||||
"description": {type: DataType.STRING, allowNull: false},
|
||||
"contentUri": {type: DataType.STRING, allowNull: false},
|
||||
}));
|
||||
},
|
||||
down: (queryInterface: QueryInterface) => {
|
||||
return Promise.resolve()
|
||||
.then(() => queryInterface.dropTable("stickers"))
|
||||
.then(() => queryInterface.dropTable("stickerpacks"));
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import { Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript";
|
||||
import Stickerpack from "./Stickerpack";
|
||||
|
||||
@Table({
|
||||
tableName: "stickers",
|
||||
underscoredAll: false,
|
||||
timestamps: false,
|
||||
})
|
||||
export default class StickerRecord extends Model<StickerRecord> {
|
||||
@PrimaryKey
|
||||
@Column
|
||||
id: number;
|
||||
|
||||
@Column
|
||||
@ForeignKey(() => Stickerpack)
|
||||
packId: string;
|
||||
|
||||
@Column
|
||||
description: string;
|
||||
|
||||
@Column
|
||||
contentUri: string;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
import { Column, Model, PrimaryKey, Table } from "sequelize-typescript";
|
||||
|
||||
@Table({
|
||||
tableName: "stickerpacks",
|
||||
underscoredAll: false,
|
||||
timestamps: false,
|
||||
})
|
||||
export default class Stickerpack extends Model<Stickerpack> {
|
||||
@PrimaryKey
|
||||
@Column
|
||||
id: string;
|
||||
|
||||
@Column
|
||||
creatorId: string;
|
||||
|
||||
@Column
|
||||
name: string;
|
||||
}
|
54
src/index.ts
54
src/index.ts
|
@ -1,24 +1,47 @@
|
|||
import { AutojoinRoomsMixin, MatrixClient, SimpleRetryJoinStrategy } from "matrix-bot-sdk";
|
||||
import config from "./config";
|
||||
import { LogService } from "matrix-js-snippets";
|
||||
import { CommandProcessor } from "./matrix/CommandProcessor";
|
||||
import { LocalstorageStorageProvider } from "./bot/LocalstorageStorageProvider";
|
||||
import { Appservice } from "matrix-bot-sdk/lib/appservice/Appservice";
|
||||
import { SimpleFsStorageProvider } from "matrix-bot-sdk/lib/storage/SimpleFsStorageProvider";
|
||||
import { BuilderRegistry } from "./bot/BuilderRegistry";
|
||||
import { StickerStore } from "./db/StickerStore";
|
||||
import { Webserver } from "./web/webserver";
|
||||
|
||||
LogService.configure(config.logging);
|
||||
const storageProvider = new LocalstorageStorageProvider("./storage");
|
||||
const client = new MatrixClient(config.homeserverUrl, config.accessToken, storageProvider);
|
||||
const commands = new CommandProcessor(client);
|
||||
import { LogService } from "matrix-bot-sdk/lib/logging/LogService";
|
||||
import Webserver from "./web/webserver";
|
||||
import * as path from "path";
|
||||
import { StickerStore } from "./storage/StickerStore";
|
||||
|
||||
async function run() {
|
||||
await StickerStore.updateSchema();
|
||||
Webserver.start();
|
||||
|
||||
// Cheat and use a client to get the user ID for the appservice bot
|
||||
const client = new MatrixClient(config.appservice.homeserverUrl, config.appservice.asToken);
|
||||
const userId = await client.getUserId();
|
||||
const localpart = userId.substring(1).split(":")[0];
|
||||
|
||||
client.on("room.message", (roomId, event) => {
|
||||
const store = new StickerStore(client);
|
||||
const commands = new CommandProcessor(client, store);
|
||||
|
||||
const appservice = new Appservice({
|
||||
bindAddress: config.webserver.bind,
|
||||
port: config.webserver.port,
|
||||
homeserverName: config.appservice.domainName,
|
||||
homeserverUrl: config.appservice.homeserverUrl,
|
||||
storage: new SimpleFsStorageProvider(path.join(config.dataPath, "bot.json")),
|
||||
registration: {
|
||||
as_token: config.appservice.asToken,
|
||||
hs_token: config.appservice.hsToken,
|
||||
id: "stickers",
|
||||
namespaces: {
|
||||
users: [{regex: "@stickers.*", exclusive: true}],
|
||||
aliases: [],
|
||||
rooms: [],
|
||||
},
|
||||
sender_localpart: localpart,
|
||||
url: "http://localhost",
|
||||
},
|
||||
joinStrategy: new SimpleRetryJoinStrategy(),
|
||||
});
|
||||
|
||||
Webserver.begin(appservice, store);
|
||||
|
||||
appservice.on("room.message", (roomId, event) => {
|
||||
if (event['sender'] === userId) return;
|
||||
if (!event['content']) return;
|
||||
if (event['type'] !== "m.room.message" && event['type'] !== "m.sticker") return; // Everything we care about is a message or sticker
|
||||
|
@ -33,9 +56,8 @@ async function run() {
|
|||
return commands.tryCommand(roomId, event);
|
||||
});
|
||||
|
||||
AutojoinRoomsMixin.setupOnClient(client);
|
||||
client.setJoinStrategy(new SimpleRetryJoinStrategy());
|
||||
return client.start();
|
||||
AutojoinRoomsMixin.setupOnAppservice(appservice);
|
||||
return appservice.begin();
|
||||
}
|
||||
|
||||
run().then(() => LogService.info("index", "Sticker bot started!"));
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { MatrixClient } from "matrix-bot-sdk";
|
||||
import { LogService } from "matrix-js-snippets";
|
||||
import { LogService, MatrixClient } from "matrix-bot-sdk";
|
||||
import * as striptags from "striptags";
|
||||
import { BuilderRegistry } from "../bot/BuilderRegistry";
|
||||
import { NewPackBuilder } from "../builders/NewPackBuilder";
|
||||
import { StickerStore } from "../storage/StickerStore";
|
||||
|
||||
export class CommandProcessor {
|
||||
constructor(private client: MatrixClient) {
|
||||
constructor(private client: MatrixClient, private store: StickerStore) {
|
||||
}
|
||||
|
||||
public async tryCommand(roomId: string, event: any): Promise<any> {
|
||||
|
@ -30,7 +30,7 @@ export class CommandProcessor {
|
|||
return this.client.sendNotice(roomId, "Oops! It looks like you're already doing something. Please finish your current operation before creating a new sticker pack.");
|
||||
}
|
||||
|
||||
BuilderRegistry.register(roomId, new NewPackBuilder(this.client, roomId)); // sends a welcome message
|
||||
BuilderRegistry.register(roomId, new NewPackBuilder(this.client, roomId, this.store)); // sends a welcome message
|
||||
} else if (command === "cancel") {
|
||||
if (BuilderRegistry.hasBuilder(roomId)) {
|
||||
BuilderRegistry.deregister(roomId);
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
import * as express from "express";
|
||||
import config from "../config";
|
||||
import { LogService } from "matrix-js-snippets";
|
||||
import Stickerpack from "../db/models/Stickerpack";
|
||||
import StickerRecord from "../db/models/StickerRecord";
|
||||
import { Appservice, LogService, MatrixClient } from "matrix-bot-sdk";
|
||||
import { StickerStore } from "../storage/StickerStore";
|
||||
|
||||
export default class Webserver {
|
||||
|
||||
private static instance: Webserver;
|
||||
|
||||
class _Webserver {
|
||||
private app: any;
|
||||
|
||||
constructor() {
|
||||
this.app = express();
|
||||
constructor(private appservice: Appservice, private store: StickerStore) {
|
||||
this.app = (<any>appservice).app; // HACK: Private variable access
|
||||
|
||||
this.app.get('/:userId/:packId', this.getStickerpack.bind(this));
|
||||
this.app.get('/pack/:userId/:packId', this.getStickerpack.bind(this));
|
||||
|
||||
// TODO: Serve a home page of some kind. Stickerpack browser?
|
||||
}
|
||||
|
||||
public start() {
|
||||
this.app.listen(config.webserver.port, config.webserver.bind, () => {
|
||||
LogService.info("webserver", "Listening on " + config.webserver.bind + ":" + config.webserver.port);
|
||||
});
|
||||
public static begin(appservice: Appservice, store: StickerStore) {
|
||||
if (Webserver.instance) throw new Error("Already started");
|
||||
Webserver.instance = new Webserver(appservice, store);
|
||||
}
|
||||
|
||||
private async getStickerpack(req, res) {
|
||||
|
@ -30,7 +29,7 @@ class _Webserver {
|
|||
const replyJson = accept.indexOf("application/json") !== -1 || packId.endsWith(".json");
|
||||
if (packId.endsWith(".json")) packId = packId.substring(0, packId.length - ".json".length);
|
||||
|
||||
const pack = await Stickerpack.findOne({where: {creatorId: userId, id: packId}});
|
||||
const pack = await this.store.getStickerpack(packId);
|
||||
if (!pack) {
|
||||
// TODO: A real 404 page
|
||||
res.status(404);
|
||||
|
@ -38,7 +37,12 @@ class _Webserver {
|
|||
return;
|
||||
}
|
||||
|
||||
const stickers = await StickerRecord.findAll({where: {packId: pack.id}});
|
||||
if (pack.creatorId !== userId) {
|
||||
// TODO: A real 400 page
|
||||
res.status(400);
|
||||
res.send({"TODO": "A real 400 page"});
|
||||
return;
|
||||
}
|
||||
|
||||
if (replyJson) {
|
||||
LogService.info("Webserver", "Serving JSON for pack " + pack.id);
|
||||
|
@ -51,13 +55,18 @@ class _Webserver {
|
|||
type: "mx-user",
|
||||
id: pack.creatorId,
|
||||
},
|
||||
stickers: stickers.map(s => {
|
||||
stickers: pack.stickers.map(s => {
|
||||
return {
|
||||
id: s.id, // arbitrary
|
||||
description: s.description,
|
||||
contentUri: s.contentUri,
|
||||
};
|
||||
}),
|
||||
subscription: {
|
||||
roomId: pack.roomId,
|
||||
roomAlias: pack.roomAlias,
|
||||
public: true,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
@ -65,6 +74,4 @@ class _Webserver {
|
|||
// TODO: A real preview page
|
||||
res.send({"TODO": "A real preview page"});
|
||||
}
|
||||
}
|
||||
|
||||
export const Webserver = new _Webserver();
|
||||
}
|
Loading…
Reference in a new issue