Skip to content
This repository has been archived by the owner on Aug 10, 2023. It is now read-only.

Commit

Permalink
Sticker pack administration
Browse files Browse the repository at this point in the history
The first step towards #156
  • Loading branch information
turt2live committed May 13, 2018
1 parent e2ed9a8 commit e8274c9
Show file tree
Hide file tree
Showing 25 changed files with 1,356 additions and 1 deletion.
4 changes: 4 additions & 0 deletions config/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ homeserver:
# through the normal federation process.
#federationUrl: "https://t2bot.io:8448"

# The URL that Dimension will redirect media requests to for downloading media such as
# stickers. If not supplied or left empty Dimension will use the clientServerUrl.
#mediaUrl: "https://t2bot.io"

# The access token Dimension should use for miscellaneous access to the homeserver. This
# should be for a valid user.
accessToken: "something"
Expand Down
40 changes: 40 additions & 0 deletions scripts/stickerpack-to-migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const request = require('request');

const packId = Number(process.argv[2]);
if (!packId) {
console.error("No sticker pack ID provided");
process.exit(1);
}

const url = process.argv[3];
if (!url) {
console.error("No sticker pack URL provided");
process.exit(1);
}

request(url, (err, response) => {
if (err) {
console.error(err);
process.exit(2);
}

if (!response.body) {
console.error("No response body");
process.exit(3);
}

if (typeof(response.body) === "string") {
response.body = JSON.parse(response.body);
}

const migrationLines = [];
for (const pack of response.body) {
migrationLines.push(
'{ packId: ' + packId + ', name: "Sticker", description: "' + pack.filename + '", ' +
'imageMxc: "' + pack.mxc + '", thumbnailMxc: "' + pack.thumbnail + '", mimetype: "' + pack.mimetype + '", ' +
'thumbnailWidth: ' + pack.thumbnail_width + ', thumbnailHeight: ' + pack.thumbnail_height + ' },'
);
}

console.log(migrationLines.join("\n"));
});
3 changes: 2 additions & 1 deletion src/MemoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ export const CACHE_UPSTREAM = "upstream";
export const CACHE_SCALAR_ACCOUNTS = "scalar-accounts";
export const CACHE_WIDGET_TITLES = "widget-titles";
export const CACHE_FEDERATION = "federation";
export const CACHE_IRC_BRIDGE = "irc-bridge";
export const CACHE_IRC_BRIDGE = "irc-bridge";
export const CACHE_STICKERS = "stickers";
118 changes: 118 additions & 0 deletions src/api/admin/AdminStickerService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
import { AdminService } from "./AdminService";
import { Cache, CACHE_STICKERS } from "../../MemoryCache";
import StickerPack from "../../db/models/StickerPack";
import Sticker from "../../db/models/Sticker";
import { ApiError } from "../ApiError";

export interface MemoryStickerPack {
id: number;
displayName: string;
avatarUrl: string;
description: string;
isEnabled: boolean;
author: {
type: string;
name: string;
reference: string;
};
license: {
name: string;
urlPath: string;
};
stickers: {
id: number;
name: string;
description: string;
image: {
mxc: string;
mimetype: string;
};
thumbnail: {
mxc: string;
width: number;
height: number;
};
}[];
}

interface SetEnabledRequest {
isEnabled: boolean;
}

/**
* Administrative API for configuring stickers
*/
@Path("/api/v1/dimension/admin/stickers")
export class AdminStickerService {

public static async getStickerPacks(enabledOnly: boolean = false): Promise<MemoryStickerPack[]> {
const cachedPacks = Cache.for(CACHE_STICKERS).get("packs");
if (cachedPacks) {
if (enabledOnly) return cachedPacks.filter(p => p.isEnabled);
return cachedPacks;
}

const dbPacks = await StickerPack.findAll();
const packs: MemoryStickerPack[] = [];
for (const pack of dbPacks) {
const stickers = await Sticker.findAll({where: {packId: pack.id}});
packs.push(<MemoryStickerPack>{
id: pack.id,
displayName: pack.name,
avatarUrl: pack.avatarUrl,
description: pack.description,
isEnabled: pack.isEnabled,
author: {
type: pack.authorType,
name: pack.authorName,
reference: pack.authorReference,
},
license: {
name: pack.license,
urlPath: pack.licensePath,
},
stickers: stickers.map(s => {
return {
id: s.id,
name: s.name,
description: s.description,
image: {
mxc: s.imageMxc,
mimetype: s.mimetype,
},
thumbnail: {
mxc: s.thumbnailMxc,
width: s.thumbnailWidth,
height: s.thumbnailHeight,
},
}
}),
});
}

Cache.for(CACHE_STICKERS).put("packs", packs);
if (enabledOnly) return packs.filter(p => p.isEnabled);
return packs;
}

@GET
@Path("packs")
public async getStickerPacks(@QueryParam("scalar_token") scalarToken: string): Promise<MemoryStickerPack[]> {
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
return await AdminStickerService.getStickerPacks();
}

@POST
@Path("packs/:id/enabled")
public async setPackEnabled(@QueryParam("scalar_token") scalarToken: string, @PathParam("id") packId: number, request: SetEnabledRequest): Promise<any> {
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
const pack = await StickerPack.findByPrimary(packId);
if (!pack) throw new ApiError(404, "Sticker pack not found");

pack.isEnabled = request.isEnabled;
await pack.save();

return {}; // 200 OK
}
}
18 changes: 18 additions & 0 deletions src/api/dimension/DimensionMediaService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { GET, Path, PathParam, QueryParam, Return } from "typescript-rest";
import { MatrixLiteClient } from "../../matrix/MatrixLiteClient";
import config from "../../config";

/**
* API for interacting with matrix media
*/
@Path("/api/v1/dimension/media")
export class DimensionMediaService {

@GET
@Path("thumbnail/:serverName/:contentId")
public async getThumbnail(@PathParam("serverName") serverName: string, @PathParam("contentId") contentId: string, @QueryParam("width") width: number, @QueryParam("height") height: number, @QueryParam("method") method: "scale" | "crop" = "scale", @QueryParam("animated") isAnimated = true): Promise<any> {
const client = new MatrixLiteClient(config.homeserver.accessToken);
const url = await client.getThumbnailUrl(serverName, contentId, width, height, method, isAnimated);
return new Return.MovedTemporarily(url);
}
}
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface DimensionConfig {
accessToken: string;
clientServerUrl: string;
federationUrl: string;
mediaUrl: string;
};
widgetBlacklist: string[];
database: {
Expand Down
4 changes: 4 additions & 0 deletions src/db/DimensionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import Webhook from "./models/Webhook";
import BridgeRecord from "./models/BridgeRecord";
import IrcBridgeRecord from "./models/IrcBridgeRecord";
import IrcBridgeNetwork from "./models/IrcBridgeNetwork";
import StickerPack from "./models/StickerPack";
import Sticker from "./models/Sticker";

class _DimensionStore {
private sequelize: Sequelize;
Expand Down Expand Up @@ -47,6 +49,8 @@ class _DimensionStore {
BridgeRecord,
IrcBridgeRecord,
IrcBridgeNetwork,
StickerPack,
Sticker,
]);
}

Expand Down
Loading

0 comments on commit e8274c9

Please sign in to comment.