This commit is contained in:
parent
7432de3d33
commit
c3b3b9b9a6
|
@ -14,7 +14,7 @@ RUN pacman -S --noconfirm pacman
|
||||||
RUN pacman-db-upgrade
|
RUN pacman-db-upgrade
|
||||||
RUN pacman -S --noconfirm archlinux-keyring
|
RUN pacman -S --noconfirm archlinux-keyring
|
||||||
RUN pacman -Syyu --noconfirm
|
RUN pacman -Syyu --noconfirm
|
||||||
RUN pacman -S --noconfirm git nodejs npm mongodb redis imagemagick
|
RUN pacman -S --noconfirm git nodejs npm mongodb redis
|
||||||
|
|
||||||
COPY misskey.sh /root/misskey.sh
|
COPY misskey.sh /root/misskey.sh
|
||||||
RUN chmod u+x /root/misskey.sh
|
RUN chmod u+x /root/misskey.sh
|
||||||
|
|
|
@ -25,7 +25,6 @@ Please install and setup these softwares:
|
||||||
* *Node.js* and *npm*
|
* *Node.js* and *npm*
|
||||||
* **[MongoDB](https://www.mongodb.com/)** >= 3.6
|
* **[MongoDB](https://www.mongodb.com/)** >= 3.6
|
||||||
* **[Redis](https://redis.io/)**
|
* **[Redis](https://redis.io/)**
|
||||||
* **[ImageMagick](http://www.imagemagick.org/script/index.php)** >= 7.0
|
|
||||||
|
|
||||||
##### Optional
|
##### Optional
|
||||||
* [Elasticsearch](https://www.elastic.co/) - used to provide searching feature instead of MongoDB
|
* [Elasticsearch](https://www.elastic.co/) - used to provide searching feature instead of MongoDB
|
||||||
|
|
|
@ -25,7 +25,6 @@ adduser --disabled-password --disabled-login misskey
|
||||||
* *Node.js* と *npm*
|
* *Node.js* と *npm*
|
||||||
* **[MongoDB](https://www.mongodb.com/)** (3.6以上)
|
* **[MongoDB](https://www.mongodb.com/)** (3.6以上)
|
||||||
* **[Redis](https://redis.io/)**
|
* **[Redis](https://redis.io/)**
|
||||||
* **[ImageMagick](http://www.imagemagick.org/script/index.php)**
|
|
||||||
|
|
||||||
##### オプション
|
##### オプション
|
||||||
* [Elasticsearch](https://www.elastic.co/) - 検索機能を向上させるために用います。
|
* [Elasticsearch](https://www.elastic.co/) - 検索機能を向上させるために用います。
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
"@types/deep-equal": "1.0.1",
|
"@types/deep-equal": "1.0.1",
|
||||||
"@types/elasticsearch": "5.0.25",
|
"@types/elasticsearch": "5.0.25",
|
||||||
"@types/file-type": "5.2.1",
|
"@types/file-type": "5.2.1",
|
||||||
"@types/gm": "1.18.0",
|
|
||||||
"@types/gulp": "3.8.36",
|
"@types/gulp": "3.8.36",
|
||||||
"@types/gulp-htmlmin": "1.3.32",
|
"@types/gulp-htmlmin": "1.3.32",
|
||||||
"@types/gulp-mocha": "0.0.32",
|
"@types/gulp-mocha": "0.0.32",
|
||||||
|
@ -73,6 +72,7 @@
|
||||||
"@types/request-promise-native": "1.0.15",
|
"@types/request-promise-native": "1.0.15",
|
||||||
"@types/rimraf": "2.0.2",
|
"@types/rimraf": "2.0.2",
|
||||||
"@types/seedrandom": "2.4.27",
|
"@types/seedrandom": "2.4.27",
|
||||||
|
"@types/sharp": "0.17.9",
|
||||||
"@types/showdown": "1.7.5",
|
"@types/showdown": "1.7.5",
|
||||||
"@types/single-line-log": "1.1.0",
|
"@types/single-line-log": "1.1.0",
|
||||||
"@types/speakeasy": "2.0.2",
|
"@types/speakeasy": "2.0.2",
|
||||||
|
@ -108,7 +108,6 @@
|
||||||
"file-loader": "1.1.11",
|
"file-loader": "1.1.11",
|
||||||
"file-type": "8.1.0",
|
"file-type": "8.1.0",
|
||||||
"fuckadblock": "3.2.1",
|
"fuckadblock": "3.2.1",
|
||||||
"gm": "1.23.1",
|
|
||||||
"gulp": "3.9.1",
|
"gulp": "3.9.1",
|
||||||
"gulp-cssnano": "2.1.3",
|
"gulp-cssnano": "2.1.3",
|
||||||
"gulp-htmlmin": "4.0.0",
|
"gulp-htmlmin": "4.0.0",
|
||||||
|
@ -165,7 +164,6 @@
|
||||||
"parse5": "5.0.0",
|
"parse5": "5.0.0",
|
||||||
"portscanner": "2.2.0",
|
"portscanner": "2.2.0",
|
||||||
"progress-bar-webpack-plugin": "1.11.0",
|
"progress-bar-webpack-plugin": "1.11.0",
|
||||||
"prominence": "0.2.0",
|
|
||||||
"promise-sequential": "1.1.1",
|
"promise-sequential": "1.1.1",
|
||||||
"pug": "2.0.3",
|
"pug": "2.0.3",
|
||||||
"punycode": "2.1.1",
|
"punycode": "2.1.1",
|
||||||
|
@ -181,6 +179,7 @@
|
||||||
"s-age": "1.1.2",
|
"s-age": "1.1.2",
|
||||||
"sass-loader": "7.0.3",
|
"sass-loader": "7.0.3",
|
||||||
"seedrandom": "2.4.3",
|
"seedrandom": "2.4.3",
|
||||||
|
"sharp": "0.20.5",
|
||||||
"showdown": "1.8.6",
|
"showdown": "1.8.6",
|
||||||
"showdown-highlightjs-extension": "0.1.2",
|
"showdown-highlightjs-extension": "0.1.2",
|
||||||
"single-line-log": "1.1.2",
|
"single-line-log": "1.1.2",
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import * as stream from 'stream';
|
|
||||||
import * as Gm from 'gm';
|
|
||||||
import { IDriveFile, getDriveFileBucket } from '../models/drive-file';
|
|
||||||
|
|
||||||
const gm = Gm.subClass({
|
|
||||||
imageMagick: true
|
|
||||||
});
|
|
||||||
|
|
||||||
export default async function(file: IDriveFile): Promise<stream.Readable> {
|
|
||||||
if (!/^image\/.*$/.test(file.contentType)) return null;
|
|
||||||
|
|
||||||
const bucket = await getDriveFileBucket();
|
|
||||||
const readable = bucket.openDownloadStream(file._id);
|
|
||||||
|
|
||||||
const g = gm(readable);
|
|
||||||
|
|
||||||
const stream = g
|
|
||||||
.resize(256, 256)
|
|
||||||
.compress('jpeg')
|
|
||||||
.quality(70)
|
|
||||||
.interlace('line')
|
|
||||||
.stream();
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@ export default class {
|
||||||
public showAll(): void {
|
public showAll(): void {
|
||||||
this.show('MongoDB', 'mongo --version', x => x.match(/^MongoDB shell version:? v(.*)\r?\n/));
|
this.show('MongoDB', 'mongo --version', x => x.match(/^MongoDB shell version:? v(.*)\r?\n/));
|
||||||
this.show('Redis', 'redis-server --version', x => x.match(/v=([0-9\.]*)/));
|
this.show('Redis', 'redis-server --version', x => x.match(/v=([0-9\.]*)/));
|
||||||
this.show('ImageMagick', 'magick -version', x => x.match(/^Version: ImageMagick ([^ ]*)/));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public show(serviceName: string, command: string, transform: (x: string) => RegExpMatchArray): void {
|
public show(serviceName: string, command: string, transform: (x: string) => RegExpMatchArray): void {
|
||||||
|
|
|
@ -37,6 +37,7 @@ export type IMetadata = {
|
||||||
storage?: string;
|
storage?: string;
|
||||||
storageProps?: any;
|
storageProps?: any;
|
||||||
isSensitive?: boolean;
|
isSensitive?: boolean;
|
||||||
|
isRemote?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IDriveFile = {
|
export type IDriveFile = {
|
||||||
|
@ -160,7 +161,7 @@ export const pack = (
|
||||||
|
|
||||||
_target.url = _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`;
|
_target.url = _file.metadata.url ? _file.metadata.url : `${config.drive_url}/${_target.id}/${encodeURIComponent(_target.name)}`;
|
||||||
_target.src = _file.metadata.url;
|
_target.src = _file.metadata.url;
|
||||||
_target.isRemote = _file.metadata.withoutChunks;
|
_target.isRemote = _file.metadata.isRemote;
|
||||||
|
|
||||||
if (_target.properties == null) _target.properties = {};
|
if (_target.properties == null) _target.properties = {};
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,11 @@ import * as stream from 'stream';
|
||||||
|
|
||||||
import * as mongodb from 'mongodb';
|
import * as mongodb from 'mongodb';
|
||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
import * as _gm from 'gm';
|
|
||||||
import * as debug from 'debug';
|
import * as debug from 'debug';
|
||||||
import fileType = require('file-type');
|
import fileType = require('file-type');
|
||||||
const prominence = require('prominence');
|
|
||||||
import * as Minio from 'minio';
|
import * as Minio from 'minio';
|
||||||
import * as uuid from 'uuid';
|
import * as uuid from 'uuid';
|
||||||
|
import * as sharp from 'sharp';
|
||||||
|
|
||||||
import DriveFile, { IMetadata, getDriveFileBucket, IDriveFile } from '../../models/drive-file';
|
import DriveFile, { IMetadata, getDriveFileBucket, IDriveFile } from '../../models/drive-file';
|
||||||
import DriveFolder from '../../models/drive-folder';
|
import DriveFolder from '../../models/drive-folder';
|
||||||
|
@ -19,10 +18,6 @@ import { isLocalUser, IUser, IRemoteUser } from '../../models/user';
|
||||||
import delFile from './delete-file';
|
import delFile from './delete-file';
|
||||||
import config from '../../config';
|
import config from '../../config';
|
||||||
|
|
||||||
const gm = _gm.subClass({
|
|
||||||
imageMagick: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const log = debug('misskey:drive:add-file');
|
const log = debug('misskey:drive:add-file');
|
||||||
|
|
||||||
async function save(readable: stream.Readable, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> {
|
async function save(readable: stream.Readable, name: string, type: string, hash: string, size: number, metadata: any): Promise<IDriveFile> {
|
||||||
|
@ -53,6 +48,8 @@ async function save(readable: stream.Readable, name: string, type: string, hash:
|
||||||
});
|
});
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
|
} else {
|
||||||
|
throw 'unknown storage type';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Get MongoDB GridFS bucket
|
// Get MongoDB GridFS bucket
|
||||||
|
@ -228,42 +225,37 @@ export default async function(
|
||||||
|
|
||||||
let propPromises: Array<Promise<void>> = [];
|
let propPromises: Array<Promise<void>> = [];
|
||||||
|
|
||||||
const isImage = ['image/jpeg', 'image/gif', 'image/png'].includes(mime);
|
const isImage = ['image/jpeg', 'image/gif', 'image/png', 'image/webp'].includes(mime);
|
||||||
|
|
||||||
if (isImage) {
|
if (isImage) {
|
||||||
|
const img = sharp(path);
|
||||||
|
|
||||||
// Calc width and height
|
// Calc width and height
|
||||||
const calcWh = async () => {
|
const calcWh = async () => {
|
||||||
log('calculate image width and height...');
|
log('calculate image width and height...');
|
||||||
|
|
||||||
// Calculate width and height
|
// Calculate width and height
|
||||||
const g = gm(fs.createReadStream(path), name);
|
const meta = await img.metadata();
|
||||||
const size = await prominence(g).size();
|
|
||||||
|
|
||||||
log(`image width and height is calculated: ${size.width}, ${size.height}`);
|
log(`image width and height is calculated: ${meta.width}, ${meta.height}`);
|
||||||
|
|
||||||
properties['width'] = size.width;
|
properties['width'] = meta.width;
|
||||||
properties['height'] = size.height;
|
properties['height'] = meta.height;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calc average color
|
// Calc average color
|
||||||
const calcAvg = async () => {
|
const calcAvg = async () => {
|
||||||
log('calculate average color...');
|
log('calculate average color...');
|
||||||
|
|
||||||
const info = await prominence(gm(fs.createReadStream(path), name)).identify();
|
const info = await (img as any).stats();
|
||||||
const isTransparent = info ? info['Channel depth'].Alpha != null : false;
|
|
||||||
|
|
||||||
const buffer = await prominence(gm(fs.createReadStream(path), name)
|
const r = Math.round(info.channels[0].mean);
|
||||||
.setFormat('ppm')
|
const g = Math.round(info.channels[1].mean);
|
||||||
.resize(1, 1)) // 1pxのサイズに縮小して平均色を取得するというハック
|
const b = Math.round(info.channels[2].mean);
|
||||||
.toBuffer();
|
|
||||||
|
|
||||||
const r = buffer.readUInt8(buffer.length - 3);
|
|
||||||
const g = buffer.readUInt8(buffer.length - 2);
|
|
||||||
const b = buffer.readUInt8(buffer.length - 1);
|
|
||||||
|
|
||||||
log(`average color is calculated: ${r}, ${g}, ${b}`);
|
log(`average color is calculated: ${r}, ${g}, ${b}`);
|
||||||
|
|
||||||
const value = isTransparent ? [r, g, b, 255] : [r, g, b];
|
const value = info.isOpaque ? [r, g, b] : [r, g, b, 255];
|
||||||
|
|
||||||
properties['avgColor'] = value;
|
properties['avgColor'] = value;
|
||||||
};
|
};
|
||||||
|
@ -282,6 +274,7 @@ export default async function(
|
||||||
comment: comment,
|
comment: comment,
|
||||||
properties: properties,
|
properties: properties,
|
||||||
withoutChunks: isLink,
|
withoutChunks: isLink,
|
||||||
|
isRemote: isLink,
|
||||||
isSensitive: sensitive
|
isSensitive: sensitive
|
||||||
} as IMetadata;
|
} as IMetadata;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue