Compare commits
27 Commits
Author | SHA1 | Date | |
---|---|---|---|
1c25dbed66 | |||
7e8c5c0c3c | |||
0b747b901c | |||
8dd5051201 | |||
f7b0fedc9d | |||
0411d0b242 | |||
3fcc793269 | |||
fd27a0efef | |||
4474a2568e | |||
9d944243a3 | |||
8ef38ebab1 | |||
f457a23eab | |||
5d1eeaf1d8 | |||
77f732c6a4 | |||
ac07f04ad8 | |||
dddd760efd | |||
0f7fbacb17 | |||
2697107770 | |||
e1e1cd0574 | |||
93786aa510 | |||
d8b9a8715b | |||
e8783b15b1 | |||
0995d5c5a2 | |||
0852045928 | |||
04de0e9a50 | |||
951b693d17 | |||
308f357c4f |
@ -68,6 +68,29 @@ drive:
|
||||
# accessKey:
|
||||
# secretKey:
|
||||
|
||||
# S3 example
|
||||
# storage: 'minio'
|
||||
# bucket: bucket-name
|
||||
# prefix: files
|
||||
# config:
|
||||
# endPoint: s3-us-west-2.amazonaws.com
|
||||
# region: us-west-2
|
||||
# secure: true
|
||||
# accessKey: XXX
|
||||
# secretKey: YYY
|
||||
|
||||
# S3 example (with CDN, custom domain)
|
||||
# storage: 'minio'
|
||||
# bucket: drive.example.com
|
||||
# prefix: files
|
||||
# baseUrl: https://drive.example.com
|
||||
# config:
|
||||
# endPoint: s3-us-west-2.amazonaws.com
|
||||
# region: us-west-2
|
||||
# secure: true
|
||||
# accessKey: XXX
|
||||
# secretKey: YYY
|
||||
|
||||
#
|
||||
# Below settings are optional
|
||||
#
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <i@syuilo.com>",
|
||||
"version": "5.1.0",
|
||||
"clientVersion": "1.0.7561",
|
||||
"version": "5.3.0",
|
||||
"clientVersion": "1.0.7588",
|
||||
"codename": "nighthike",
|
||||
"main": "./built/index.js",
|
||||
"private": true,
|
||||
@ -98,7 +98,7 @@
|
||||
"diskusage": "0.2.4",
|
||||
"dompurify": "1.0.5",
|
||||
"elasticsearch": "15.1.1",
|
||||
"element-ui": "2.4.4",
|
||||
"element-ui": "2.4.5",
|
||||
"emojilib": "2.3.0",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "5.0.1",
|
||||
@ -194,7 +194,7 @@
|
||||
"ts-node": "7.0.0",
|
||||
"tslint": "5.10.0",
|
||||
"typescript": "2.9.2",
|
||||
"typescript-eslint-parser": "16.0.1",
|
||||
"typescript-eslint-parser": "17.0.0",
|
||||
"uglify-es": "3.3.9",
|
||||
"url-loader": "1.0.1",
|
||||
"uuid": "3.3.2",
|
||||
|
@ -92,7 +92,7 @@ export default Vue.component('misskey-flavored-markdown', {
|
||||
case 'hashtag':
|
||||
return createElement('a', {
|
||||
attrs: {
|
||||
href: `${url}/tags/${token.hashtag}`,
|
||||
href: `${url}/tags/${encodeURIComponent(token.hashtag)}`,
|
||||
target: '_blank'
|
||||
}
|
||||
}, token.content);
|
||||
|
@ -11,7 +11,7 @@
|
||||
<div>
|
||||
<div v-for="stat in stats" :key="stat.tag">
|
||||
<div class="tag">
|
||||
<router-link :to="`/tags/${ stat.tag }`" :title="stat.tag">#{{ stat.tag }}</router-link>
|
||||
<router-link :to="`/tags/${ encodeURIComponent(stat.tag) }`" :title="stat.tag">#{{ stat.tag }}</router-link>
|
||||
<p>{{ '%i18n:@count%'.replace('{}', stat.usersCount) }}</p>
|
||||
</div>
|
||||
<x-chart class="chart" :src="stat.chart"/>
|
||||
|
@ -38,7 +38,13 @@
|
||||
<button class="poll" title="%i18n:@create-poll%" @click="poll = true">%fa:chart-pie%</button>
|
||||
<button class="poll" title="内容を隠す" @click="useCw = !useCw">%fa:eye-slash%</button>
|
||||
<button class="geo" title="位置情報を添付する" @click="geo ? removeGeo() : setGeo()">%fa:map-marker-alt%</button>
|
||||
<button class="visibility" title="公開範囲" @click="setVisibility" ref="visibilityButton">%fa:lock%</button>
|
||||
<button class="visibility" title="公開範囲" @click="setVisibility" ref="visibilityButton">
|
||||
<span v-if="visibility === 'public'">%fa:globe%</span>
|
||||
<span v-if="visibility === 'home'">%fa:home%</span>
|
||||
<span v-if="visibility === 'followers'">%fa:unlock%</span>
|
||||
<span v-if="visibility === 'specified'">%fa:envelope%</span>
|
||||
<span v-if="visibility === 'private'">%fa:lock%</span>
|
||||
</button>
|
||||
<p class="text-count" :class="{ over: text.length > 1000 }">{{ 1000 - text.length }}</p>
|
||||
<button :class="{ posting }" class="submit" :disabled="!canPost" @click="post">
|
||||
{{ posting ? '%i18n:@posting%' : submitText }}<mk-ellipsis v-if="posting"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<p>%i18n:@followers%</p><a>{{ u.followersCount }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<mk-follow-button v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="u"/>
|
||||
<mk-follow-button v-if="$store.getters.isSignedIn && u.id != $store.state.i.id" :user="u"/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="profile">
|
||||
<div class="friend-form" v-if="$store.getters.isSignedIn && $store.state.i.id != user.id">
|
||||
<div class="profile" v-if="$store.getters.isSignedIn">
|
||||
<div class="friend-form" v-if="$store.state.i.id != user.id">
|
||||
<mk-follow-button :user="user" size="big"/>
|
||||
<p class="followed" v-if="user.isFollowed">%i18n:@follows-you%</p>
|
||||
<p class="stalk" v-if="user.isFollowing">
|
||||
@ -9,7 +9,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="action-form">
|
||||
<button class="mute ui" @click="user.isMuted ? unmute() : mute()">
|
||||
<button class="mute ui" @click="user.isMuted ? unmute() : mute()" v-if="$store.state.i.id != user.id">
|
||||
<span v-if="user.isMuted">%fa:eye% %i18n:@unmute%</span>
|
||||
<span v-if="!user.isMuted">%fa:eye-slash% %i18n:@mute%</span>
|
||||
</button>
|
||||
|
@ -53,6 +53,7 @@ export type Source = {
|
||||
storage: string;
|
||||
bucket?: string;
|
||||
prefix?: string;
|
||||
baseUrl?: string;
|
||||
config?: any;
|
||||
};
|
||||
|
||||
|
@ -12,13 +12,16 @@ const queue = new Queue('misskey', {
|
||||
},
|
||||
|
||||
removeOnSuccess: true,
|
||||
removeOnFailure: true
|
||||
removeOnFailure: true,
|
||||
getEvents: false,
|
||||
sendEvents: false,
|
||||
storeJobs: false
|
||||
});
|
||||
|
||||
export function createHttpJob(data: any) {
|
||||
return queue.createJob(data)
|
||||
.retries(4)
|
||||
.backoff('exponential', 16384) // 16s
|
||||
//.retries(4)
|
||||
//.backoff('exponential', 16384) // 16s
|
||||
.save();
|
||||
}
|
||||
|
||||
@ -32,5 +35,5 @@ export function deliver(user: ILocalUser, content: any, to: any) {
|
||||
}
|
||||
|
||||
export default function() {
|
||||
queue.process(8, http);
|
||||
queue.process(128, http);
|
||||
}
|
||||
|
@ -14,6 +14,34 @@ import htmlToMFM from '../../../mfm/html-to-mfm';
|
||||
|
||||
const log = debug('misskey:activitypub');
|
||||
|
||||
function validatePerson(x: any) {
|
||||
if (x == null) {
|
||||
return new Error('invalid person: object is null');
|
||||
}
|
||||
|
||||
if (x.type != 'Person' && x.type != 'Service') {
|
||||
return new Error(`invalid person: object is not a person or service '${x.type}'`);
|
||||
}
|
||||
|
||||
if (typeof x.preferredUsername !== 'string') {
|
||||
return new Error('invalid person: preferredUsername is not a string');
|
||||
}
|
||||
|
||||
if (typeof x.inbox !== 'string') {
|
||||
return new Error('invalid person: inbox is not a string');
|
||||
}
|
||||
|
||||
if (!validateUsername(x.preferredUsername)) {
|
||||
return new Error('invalid person: invalid username');
|
||||
}
|
||||
|
||||
if (!isValidName(x.name == '' ? null : x.name)) {
|
||||
return new Error('invalid person: invalid name');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Personをフェッチします。
|
||||
*
|
||||
@ -47,28 +75,10 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs
|
||||
|
||||
const object = await resolver.resolve(value) as any;
|
||||
|
||||
if (object == null) {
|
||||
throw new Error('invalid person: object is null');
|
||||
}
|
||||
const err = validatePerson(object);
|
||||
|
||||
if (object.type != 'Person' && object.type != 'Service') {
|
||||
throw new Error(`invalid person: object is not a person or service '${object.type}'`);
|
||||
}
|
||||
|
||||
if (typeof object.preferredUsername !== 'string') {
|
||||
throw new Error('invalid person: preferredUsername is not a string');
|
||||
}
|
||||
|
||||
if (typeof object.inbox !== 'string') {
|
||||
throw new Error('invalid person: inbox is not a string');
|
||||
}
|
||||
|
||||
if (!validateUsername(object.preferredUsername)) {
|
||||
throw new Error('invalid person: invalid username');
|
||||
}
|
||||
|
||||
if (!isValidName(object.name == '' ? null : object.name)) {
|
||||
throw new Error('invalid person: invalid name');
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
const person: IPerson = object;
|
||||
@ -198,12 +208,10 @@ export async function updatePerson(value: string | IObject, resolver?: Resolver)
|
||||
|
||||
const object = await resolver.resolve(value) as any;
|
||||
|
||||
if (
|
||||
object == null ||
|
||||
object.type !== 'Person'
|
||||
) {
|
||||
log(`invalid person: ${JSON.stringify(object, null, 2)}`);
|
||||
throw new Error('invalid person');
|
||||
const err = validatePerson(object);
|
||||
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
const person: IPerson = object;
|
||||
|
@ -52,7 +52,7 @@ export default (endpoint: string, user: IUser, app: IApp, data: any, file?: any)
|
||||
|
||||
const time = after - before;
|
||||
|
||||
if (time > 500) {
|
||||
if (time > 1000) {
|
||||
console.warn(`SLOW API CALL DETECTED: ${ep.name} (${ time }ms)`);
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -25,7 +25,14 @@ async function save(readable: stream.Readable, name: string, type: string, hash:
|
||||
const minio = new Minio.Client(config.drive.config);
|
||||
const id = uuid.v4();
|
||||
const obj = `${config.drive.prefix}/${id}`;
|
||||
await minio.putObject(config.drive.bucket, obj, readable);
|
||||
|
||||
const baseUrl = config.drive.baseUrl
|
||||
|| `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }`;
|
||||
|
||||
await minio.putObject(config.drive.bucket, obj, readable, size, {
|
||||
'Content-Type': type,
|
||||
'Cache-Control': 'max-age=31536000, immutable'
|
||||
});
|
||||
|
||||
Object.assign(metadata, {
|
||||
withoutChunks: true,
|
||||
@ -33,7 +40,7 @@ async function save(readable: stream.Readable, name: string, type: string, hash:
|
||||
storageProps: {
|
||||
id: id
|
||||
},
|
||||
url: `${ config.drive.config.secure ? 'https' : 'http' }://${ config.drive.config.endPoint }${ config.drive.config.port ? ':' + config.drive.config.port : '' }/${ config.drive.bucket }/${ obj }`
|
||||
url: `${ baseUrl }/${ obj }`
|
||||
});
|
||||
|
||||
const file = await DriveFile.insert({
|
||||
@ -242,6 +249,7 @@ export default async function(
|
||||
const calcAvg = async () => {
|
||||
log('calculate average color...');
|
||||
|
||||
try {
|
||||
const info = await (img as any).stats();
|
||||
|
||||
const r = Math.round(info.channels[0].mean);
|
||||
@ -253,6 +261,7 @@ export default async function(
|
||||
const value = info.isOpaque ? [r, g, b] : [r, g, b, 255];
|
||||
|
||||
properties['avgColor'] = value;
|
||||
} catch (e) { }
|
||||
};
|
||||
|
||||
propPromises = [calcWh(), calcAvg()];
|
||||
|
Reference in New Issue
Block a user