matrix-art

An image gallery for Matrix
git clone git://archive.git.mtrnord.blog/MTRNord/matrix-art.git
Log | Files | Refs | README | LICENSE

ImageEvent.ts (6385B)


      1 import {
      2     ExtensibleEvents,
      3     IPartialEvent,
      4     Optional,
      5     UnstableValue,
      6     EventType,
      7     isEventTypeSame,
      8     isProvided,
      9     M_TEXT,
     10     InvalidEventError,
     11     isOptionalAString,
     12     NamespacedValue,
     13     M_MESSAGE_EVENT_CONTENT,
     14     EitherAnd,
     15     M_TEXT_EVENT,
     16     ExtensibleEvent
     17 } from "matrix-events-sdk";
     18 
     19 export const M_IMAGE = new UnstableValue("m.image", "org.matrix.msc1767.image");
     20 export const M_FILE = new UnstableValue("m.file", "org.matrix.msc1767.file");
     21 export const M_THUMBNAIL = new UnstableValue("m.thumbnail", "org.matrix.msc1767.thumbnail");
     22 export const M_BLURHASH = new UnstableValue("blurhash", "xyz.amorgan.blurhash");
     23 export const MATRIX_ART_DESCRIPTION = new NamespacedValue("matrixart.description");
     24 export const MATRIX_ART_TAGS = new NamespacedValue("matrixart.tags");
     25 export const MATRIX_ART_NSFW = new NamespacedValue("matrixart.nsfw");
     26 export const MATRIX_ART_LICENSE = new NamespacedValue("matrixart.license");
     27 
     28 type ThumbnailFileEvent = ImageFields & {
     29     url: string;
     30     mimetype: string;
     31     size: number;
     32 };
     33 
     34 type ImageFields = {
     35     width: number;
     36     height: number;
     37 };
     38 
     39 type FileEvent = {
     40     url: string;
     41     name: string;
     42     mimetype: string;
     43     size: number;
     44 };
     45 
     46 export type M_IMAGE_EVENT = EitherAnd<{ [M_IMAGE.name]: ImageFields; }, { [M_IMAGE.altName]: ImageFields; }>;
     47 export type M_FILE_EVENT = EitherAnd<{ [M_FILE.name]: FileEvent; }, { [M_FILE.altName]: FileEvent; }>;
     48 export type M_THUMBNAIL_EVENT = EitherAnd<{ [M_THUMBNAIL.name]: ThumbnailFileEvent[]; }, { [M_THUMBNAIL.altName]: ThumbnailFileEvent[]; }>;
     49 export type M_BLURHASH_EVENT = EitherAnd<{ [M_BLURHASH.name]: string; }, { [M_BLURHASH.altName]: string; }>;
     50 export type MATRIX_ART_TAGS_EVENT = { ["matrixart.tags"]: string[]; };
     51 export type MATRIX_ART_DESCRIPTION_EVENT = { ["matrixart.description"]: string; };
     52 export type MATRIX_ART_NSFW_EVENT = { ["matrixart.nsfw"]: boolean; };
     53 export type MATRIX_ART_LICENSE_EVENT = { ["matrixart.license"]: string; };
     54 export type M_IMAGE_EVENT_CONTENT = M_MESSAGE_EVENT_CONTENT
     55     & M_IMAGE_EVENT
     56     & M_FILE_EVENT
     57     & M_TEXT_EVENT
     58     | M_BLURHASH_EVENT
     59     | M_THUMBNAIL_EVENT
     60     | MATRIX_ART_TAGS_EVENT
     61     | MATRIX_ART_DESCRIPTION_EVENT
     62     | MATRIX_ART_NSFW_EVENT
     63     | MATRIX_ART_LICENSE_EVENT;
     64 
     65 export class ImageEvent extends ExtensibleEvent<M_IMAGE_EVENT_CONTENT> {
     66     public readonly image!: ImageFields;
     67     public readonly text!: string;
     68     public readonly thumbnails?: ThumbnailFileEvent[];
     69     public readonly blurhash?: string;
     70     public readonly file!: FileEvent;
     71     public readonly description?: string;
     72     public readonly tags?: string[];
     73     public readonly nsfw: boolean = false;
     74     public readonly license?: string;
     75 
     76 
     77     public isEquivalentTo(primaryEventType: EventType): boolean {
     78         return isEventTypeSame(primaryEventType, M_IMAGE);
     79     }
     80     public serialize(): IPartialEvent<object> {
     81         const content: M_IMAGE_EVENT_CONTENT = {
     82             [M_TEXT.name]: this.text,
     83             [M_FILE.name]: this.file,
     84             [M_IMAGE.name]: this.image,
     85             [M_THUMBNAIL.name]: this.thumbnails,
     86             [M_BLURHASH.name]: this.blurhash,
     87             ["matrixart.description"]: this.description,
     88             ["matrixart.tags"]: this.tags,
     89             ["matrixart.nsfw"]: this.nsfw,
     90             ["matrixart.license"]: this.license,
     91         };
     92 
     93         return {
     94             type: "m.image",
     95             content: content,
     96         };
     97     }
     98 
     99     constructor(wireFormat: IPartialEvent<M_IMAGE_EVENT_CONTENT>) {
    100         super(wireFormat);
    101 
    102         const mimage = M_IMAGE.findIn<ImageFields>(this.wireContent);
    103         // Probably wrong
    104         const mtext = M_TEXT.findIn<string>(this.wireContent);
    105         const mfile = M_FILE.findIn<FileEvent>(this.wireContent);
    106         const mthumbnail = M_THUMBNAIL.findIn<ThumbnailFileEvent[]>(this.wireContent);
    107         const mblurhash = M_BLURHASH.findIn<string>(this.wireContent);
    108         const matrixart_description = MATRIX_ART_DESCRIPTION.findIn<string>(this.wireContent);
    109         const matrixart_tags = MATRIX_ART_TAGS.findIn<string[]>(this.wireContent);
    110         const matrixart_nsfw = MATRIX_ART_NSFW.findIn<boolean>(this.wireContent);
    111         const matrixart_license = MATRIX_ART_LICENSE.findIn<string>(this.wireContent);
    112 
    113         // Required fields
    114         if (isProvided(mimage)) {
    115             if (!mimage) {
    116                 throw new InvalidEventError("m.image is required to be present");
    117             }
    118             this.image = mimage;
    119         }
    120         if (isProvided(mfile)) {
    121             if (!mfile) {
    122                 throw new InvalidEventError("m.file is required to be present");
    123             }
    124             this.file = mfile;
    125         }
    126         if (isOptionalAString(mtext)) {
    127             if (!mimage) {
    128                 throw new InvalidEventError("m.text is required to be present");
    129             }
    130             // Safe but ts is stupid here
    131             this.text = mtext as string;
    132         }
    133 
    134         // Optional fields
    135         if (isProvided(mthumbnail)) {
    136             if (!Array.isArray(mthumbnail)) {
    137                 throw new InvalidEventError("m.thumbnail contents must be an array");
    138             }
    139             this.thumbnails = mthumbnail;
    140         }
    141         if (isOptionalAString(mblurhash)) {
    142             this.blurhash = mblurhash as string;
    143         }
    144         if (isOptionalAString(matrixart_description)) {
    145             this.description = matrixart_description as string;
    146         }
    147         if (isProvided(matrixart_tags)) {
    148             if (!Array.isArray(matrixart_tags)) {
    149                 throw new InvalidEventError("matrixart.tags contents must be an array");
    150             }
    151             this.tags = matrixart_tags;
    152         }
    153         if (isProvided(matrixart_nsfw)) {
    154             if (typeof matrixart_nsfw !== "boolean") {
    155                 throw new InvalidEventError("matrixart.tags contents must be an boolean");
    156             }
    157             this.nsfw = matrixart_nsfw;
    158         }
    159         if (isOptionalAString(matrixart_license)) {
    160             this.license = matrixart_license as string;
    161         }
    162     }
    163 }
    164 
    165 function parseImageEvent(wireEvent: IPartialEvent<object>): Optional<ImageEvent> {
    166     const event = wireEvent as IPartialEvent<M_IMAGE_EVENT_CONTENT>;
    167     return new ImageEvent(event);
    168 }
    169 
    170 ExtensibleEvents.registerInterpreter(M_IMAGE, parseImageEvent);
    171 ExtensibleEvents.unknownInterpretOrder.push(M_IMAGE);