UNPKG

plxnner

Version:

An elegant open-source planner for Instagram

232 lines (195 loc) 5.6 kB
import MediaImage from "../media/mediaImage.class" import MediaVideo from "../media/mediaVideo.class" import MediaAlbum from "../media/mediaAlbum.class" import MediaIframe from "../media/mediaIframe.class" import { fulfillMediaFilesForExport } from "../../utils/utilsUserExport" export default class UserMedia implements IUserMedia { public readonly user: IUser public structure: IPlatformStructureUserMedia = { collections: {} } public collections: IUserMediaCollections = {} private collection: IMediaCollection = 'posts' as IMediaCollection constructor(user: IUser) { this.user = user } /** * Return available collections from current platform structure */ public get structureCollectionKeys(): IMediaCollection[] { return Object.keys(this.structure.collections) .map(key => key as IMediaCollection) } /** * Get user active media collections */ public get collectionKeys() { return Object.keys(this.collections) } /** * Check if this user has an active collection * * @param collectionName */ public hasCollection(collectionName: string): boolean { return Object.prototype.hasOwnProperty.call( this.collections, collectionName, ) } public setActiveCollection(collection: IMediaCollection) { this.collection = collection } /** * Get active collection */ public get activeCollection() { return this.collection } /** * Fetch single media from raw media configuration * * @param collection * @param mediaSlug */ public fetchSingleMedia(collection: IMediaCollection, mediaSlug: string) { // @ts-expect-error const rawMedia = this.user.raw.media[collection].find(rawMedia => rawMedia.slug === mediaSlug) if (!rawMedia) { return null } return UserMedia.newMedia(this.user, rawMedia, collection, 'config') } /** * Effectively run the media parsing * for each available collection * * @private */ public importRawUserMediaConfig(from: IMediaFrom = 'config') { this.reset() for (const collection of this.structureCollectionKeys) { if (this.user.raw.media.hasOwnProperty(collection)) { for (const rawMedia of this.user.raw.media[collection]) { this.addMedia(rawMedia, collection, { addMethod: 'push', from }) } } } } public reset() { for (const collection of this.structureCollectionKeys) { this.collections[collection] = [] } } /** * Add a media to specific collection * * @param rawMedia * @param collection * @param options */ public addMedia( rawMedia: string | IRawMedia | File, collection: IMediaCollection = "posts", options: { addMethod: IMediaAddMethod, from: IMediaFrom } = { addMethod: 'push', from: 'config' } ) { const media = UserMedia.newMedia(this.user, rawMedia, collection, options.from) this.collections[collection][options.addMethod](media) // refresh posts count this.user.profile.setPostsCount(this.collections["posts"].length) } /** * Export media */ public async export(): Promise<IUserExportedMedia> { const exportedMedia: IUserExportedMedia = {} for await (const collectionKey of this.collectionKeys) { exportedMedia[collectionKey] = await fulfillMediaFilesForExport( this.collections[collectionKey], ) } return exportedMedia } /** * Static method that create media instance based on its type * * @param user * @param rawMedia * @param collection * @param from */ public static newMedia( user: IUser, rawMedia: string | IRawMedia | File, collection: IMediaCollection = "posts", from: IMediaFrom = "client" ): any { const mediaType = UserMedia.detectMediaType(rawMedia) switch (mediaType) { case "image": return new MediaImage(user, rawMedia, collection, from) case "video": return new MediaVideo(user, rawMedia, collection, from) case "album": if (typeof rawMedia === "string") { throw Error("Album media cannot be a string") } // @ts-expect-error todo fix types return new MediaAlbum(user, rawMedia, collection, from) case "iframe": if (typeof rawMedia === "string") { throw Error("Album media cannot be a string") } return new MediaIframe(user, rawMedia, collection, from) } } /** * Detect media type * * @param rawMedia */ public static detectMediaType(rawMedia: string | IRawMedia | File): IMediaType { let filename = "" switch (typeof rawMedia) { case "string": // shortened media import filename = rawMedia break case "object": // shortened album import if (Array.isArray(rawMedia)) { return "album" } if (rawMedia.type && rawMedia.type.includes('/')) { return rawMedia.type.split('/')[0] as IMediaType } // regular media import if (rawMedia.type) { return rawMedia.type as IMediaType } // fallback if (!(rawMedia instanceof File) && rawMedia.file && rawMedia.file) { filename = rawMedia.file.name } else { if (typeof rawMedia.name === "string") { filename = rawMedia.name } } } switch (getFileExtension(filename)) { case "mp4": return "video" default: return "image" } } }