mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-26 11:43:59 -05:00
ImgurBackend: Add Imgur MediaBackend
Add node-fetch dependency. This was chosen as other libs we use already use node-fetch. Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
parent
c64ca9c012
commit
a00a093a14
5 changed files with 100 additions and 1 deletions
|
@ -34,6 +34,7 @@
|
||||||
"@nestjs/typeorm": "7.1.5",
|
"@nestjs/typeorm": "7.1.5",
|
||||||
"@types/bcrypt": "3.0.0",
|
"@types/bcrypt": "3.0.0",
|
||||||
"@types/cron": "1.7.2",
|
"@types/cron": "1.7.2",
|
||||||
|
"@types/node-fetch": "^2.5.8",
|
||||||
"@types/passport-http-bearer": "1.0.36",
|
"@types/passport-http-bearer": "1.0.36",
|
||||||
"bcrypt": "5.0.1",
|
"bcrypt": "5.0.1",
|
||||||
"class-transformer": "0.4.0",
|
"class-transformer": "0.4.0",
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
"file-type": "16.2.0",
|
"file-type": "16.2.0",
|
||||||
"joi": "17.4.0",
|
"joi": "17.4.0",
|
||||||
"nest-router": "1.0.9",
|
"nest-router": "1.0.9",
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
"passport": "0.4.1",
|
"passport": "0.4.1",
|
||||||
"passport-http-bearer": "1.0.1",
|
"passport-http-bearer": "1.0.1",
|
||||||
"raw-body": "2.4.1",
|
"raw-body": "2.4.1",
|
||||||
|
|
83
src/media/backends/imgur-backend.ts
Normal file
83
src/media/backends/imgur-backend.ts
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import mediaConfiguration from '../../config/media.config';
|
||||||
|
import { ConsoleLoggerService } from '../../logger/console-logger.service';
|
||||||
|
import { MediaBackend } from '../media-backend.interface';
|
||||||
|
import { BackendData } from '../media-upload.entity';
|
||||||
|
import { MediaConfig } from '../../config/media.config';
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
import { MediaBackendError } from '../../errors/errors';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ImgurBackend implements MediaBackend {
|
||||||
|
private config: MediaConfig['backend']['imgur'];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly logger: ConsoleLoggerService,
|
||||||
|
@Inject(mediaConfiguration.KEY)
|
||||||
|
private mediaConfig: MediaConfig,
|
||||||
|
) {
|
||||||
|
this.logger.setContext(ImgurBackend.name);
|
||||||
|
this.config = mediaConfig.backend.imgur;
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveFile(
|
||||||
|
buffer: Buffer,
|
||||||
|
fileName: string,
|
||||||
|
): Promise<[string, BackendData]> {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('image', buffer.toString('base64'));
|
||||||
|
params.append('type', 'base64');
|
||||||
|
try {
|
||||||
|
const result = await fetch('https://api.imgur.com/3/image', {
|
||||||
|
method: 'POST',
|
||||||
|
body: params,
|
||||||
|
headers: { Authorization: `Client-ID ${this.config.clientID}` },
|
||||||
|
})
|
||||||
|
.then(ImgurBackend.checkStatus)
|
||||||
|
.then((res) => res.json());
|
||||||
|
this.logger.debug(`Response: ${JSON.stringify(result)}`, 'saveFile');
|
||||||
|
this.logger.log(`Uploaded ${fileName}`, 'saveFile');
|
||||||
|
return [result.data.link, result.data.deletehash];
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error(`error: ${e.message}`, e.stack, 'saveFile');
|
||||||
|
throw new MediaBackendError(`Could not save '${fileName}' on imgur`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteFile(fileName: string, backendData: BackendData): Promise<void> {
|
||||||
|
if (backendData === null) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const result = await fetch(
|
||||||
|
`https://api.imgur.com/3/image/${backendData}`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: { Authorization: `Client-ID ${this.config.clientID}` },
|
||||||
|
},
|
||||||
|
).then(ImgurBackend.checkStatus);
|
||||||
|
this.logger.debug(`Response: ${result}`, 'saveFile');
|
||||||
|
this.logger.log(`Deleted ${fileName}`, 'deleteFile');
|
||||||
|
return;
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error(`error: ${e.message}`, e.stack, 'deleteFile');
|
||||||
|
throw new MediaBackendError(`Could not delete '${fileName}' on imgur`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static checkStatus(res) {
|
||||||
|
if (res.ok) {
|
||||||
|
// res.status >= 200 && res.status < 300
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
throw new MediaBackendError(res.statusText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ import { UsersModule } from '../users/users.module';
|
||||||
import { FilesystemBackend } from './backends/filesystem-backend';
|
import { FilesystemBackend } from './backends/filesystem-backend';
|
||||||
import { MediaUpload } from './media-upload.entity';
|
import { MediaUpload } from './media-upload.entity';
|
||||||
import { MediaService } from './media.service';
|
import { MediaService } from './media.service';
|
||||||
|
import { ImgurBackend } from './backends/imgur-backend';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -22,7 +23,7 @@ import { MediaService } from './media.service';
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
],
|
],
|
||||||
providers: [MediaService, FilesystemBackend],
|
providers: [MediaService, FilesystemBackend, ImgurBackend],
|
||||||
exports: [MediaService],
|
exports: [MediaService],
|
||||||
})
|
})
|
||||||
export class MediaModule {}
|
export class MediaModule {}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { FilesystemBackend } from './backends/filesystem-backend';
|
||||||
import { MediaBackend } from './media-backend.interface';
|
import { MediaBackend } from './media-backend.interface';
|
||||||
import { MediaUpload } from './media-upload.entity';
|
import { MediaUpload } from './media-upload.entity';
|
||||||
import { MediaUploadUrlDto } from './media-upload-url.dto';
|
import { MediaUploadUrlDto } from './media-upload-url.dto';
|
||||||
|
import { ImgurBackend } from './backends/imgur-backend';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MediaService {
|
export class MediaService {
|
||||||
|
@ -158,6 +159,8 @@ export class MediaService {
|
||||||
switch (this.mediaConfig.backend.use) {
|
switch (this.mediaConfig.backend.use) {
|
||||||
case 'filesystem':
|
case 'filesystem':
|
||||||
return BackendType.FILESYSTEM;
|
return BackendType.FILESYSTEM;
|
||||||
|
case 'imgur':
|
||||||
|
return BackendType.IMGUR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +168,8 @@ export class MediaService {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BackendType.FILESYSTEM:
|
case BackendType.FILESYSTEM:
|
||||||
return this.moduleRef.get(FilesystemBackend);
|
return this.moduleRef.get(FilesystemBackend);
|
||||||
|
case BackendType.IMGUR:
|
||||||
|
return this.moduleRef.get(ImgurBackend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1033,6 +1033,14 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
||||||
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
|
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
|
||||||
|
|
||||||
|
"@types/node-fetch@^2.5.8":
|
||||||
|
version "2.5.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb"
|
||||||
|
integrity sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
form-data "^3.0.0"
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "14.14.28"
|
version "14.14.28"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.28.tgz#cade4b64f8438f588951a6b35843ce536853f25b"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.28.tgz#cade4b64f8438f588951a6b35843ce536853f25b"
|
||||||
|
|
Loading…
Reference in a new issue