Compare commits

...

25 Commits
2.5.0 ... 2.6.2

Author SHA1 Message Date
12c624fa58 2.6.2 2018-05-14 14:16:56 +09:00
97c4758de2 Use _id instead of createdAt to improve performance 2018-05-14 13:58:44 +09:00
f20c08f0f7 Fix bug 2018-05-14 13:54:18 +09:00
1641d6bce2 Update add-file.ts 2018-05-14 12:47:33 +09:00
f5d2cb5c61 Improve performance 2018-05-14 09:24:49 +09:00
26941f62c6 2.6.1 2018-05-14 09:15:49 +09:00
06461bb9ee NoteのuserIdに対してインデックスを張るように 2018-05-14 09:15:43 +09:00
9f4624283d Disable prev/next 2018-05-14 09:01:37 +09:00
d4b696d03a Fix bug 2018-05-13 17:00:34 +09:00
219fdecc50 Fix bug 2018-05-13 16:52:47 +09:00
7af9ad9869 Better error handling 2018-05-13 16:26:11 +09:00
a858dd4453 2.6.0 2018-05-13 03:17:09 +09:00
f47377d181 ✌️ 2018-05-13 03:16:31 +09:00
bc197bc958 Add index 2018-05-13 03:13:55 +09:00
1836dd7312 Merge branch 'master' of https://github.com/syuilo/misskey 2018-05-13 03:08:33 +09:00
b844a8e9d5 Add note 2018-05-13 03:08:00 +09:00
a4ed163b62 Merge pull request #1576 from mei23/mei-preview
Fix url preview
2018-05-10 06:36:19 +09:00
f40e1ff0cc Fix cause error in case preview has data URI 2018-05-10 01:08:33 +09:00
d261fdbbc0 Fix can't preview some url 2018-05-09 20:14:34 +09:00
6b0a42af27 Merge pull request #1575 from mei23/mei-listlm
Fix list load-more is not working
2018-05-09 05:15:51 +09:00
107d9fd2c8 Fix list load-more is not working 2018-05-09 04:56:07 +09:00
4116b9eaf2 Provide originalNotesCount and originalUsersCount 2018-05-08 07:19:23 +09:00
ecd71ef5ff Fix bug 2018-05-08 07:08:02 +09:00
058602352c Fix #1574 2018-05-08 07:03:06 +09:00
59c39fab13 Update setup.ja.md 2018-05-08 04:04:18 +09:00
19 changed files with 80 additions and 124 deletions

View File

@ -67,3 +67,15 @@ web-push generate-vapid-keys
1. `git reset --hard && git pull origin master` 1. `git reset --hard && git pull origin master`
2. `npm install` 2. `npm install`
3. `npm run build` 3. `npm run build`
## メモリが足りなくてビルドできない場合
Misskeyの(クライアントの)ビルドには、目安として8GBくらいのメモリを必要とします。
VPSなどでビルドする時は、もしかしたらメモリが足りなくなる可能性があります。
そうなった場合、もしVPSではなくあなたのPCが十分なメモリを搭載しているなら、あなたのPC上でビルドし、生成されたファイルをVPSにFTPでアップロードする方法を採ることができます。
1. あなたのPC上にMisskeyをインストールする
2. 設定ファイルを用意する。設定ファイルは、サーバーに合わせた設定にします。
3. npm run webpack
4. built/client をサーバーにアップロードする
5. サーバー上で、npm run gulp
6. 完了

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "2.5.0", "version": "2.6.2",
"clientVersion": "1.0.5241", "clientVersion": "1.0.5260",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,

View File

@ -45,7 +45,7 @@ export default Vue.extend({
} else if (url.hostname == 'youtu.be') { } else if (url.hostname == 'youtu.be') {
this.youtubeId = url.pathname; this.youtubeId = url.pathname;
} else { } else {
fetch('/url?url=' + this.url).then(res => { fetch('/url?url=' + encodeURIComponent(this.url)).then(res => {
res.json().then(info => { res.json().then(info => {
this.title = info.title; this.title = info.title;
this.description = info.description; this.description = info.description;

View File

@ -62,7 +62,7 @@ export default Vue.extend({
more() { more() {
this.moreFetching = true; this.moreFetching = true;
(this as any).api('notes/list-timeline', { (this as any).api('notes/user-list-timeline', {
listId: this.list.id, listId: this.list.id,
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,

View File

@ -1,9 +1,11 @@
<template> <template>
<mk-ui> <mk-ui>
<main v-if="!fetching"> <main v-if="!fetching">
<a v-if="note.next" :href="note.next">%fa:angle-up%%i18n:@next%</a>
<mk-note-detail :note="note"/> <mk-note-detail :note="note"/>
<a v-if="note.prev" :href="note.prev">%fa:angle-down%%i18n:@prev%</a> <footer>
<router-link v-if="note.next" :to="note.next">%fa:angle-left% %i18n:@next%</router-link>
<router-link v-if="note.prev" :to="note.prev">%i18n:@prev% %fa:angle-right%</router-link>
</footer>
</main> </main>
</mk-ui> </mk-ui>
</template> </template>
@ -48,17 +50,12 @@ main
padding 16px padding 16px
text-align center text-align center
> a > footer
display inline-block margin-top 16px
&:first-child > a
margin-bottom 4px display inline-block
margin 0 16px
&:last-child
margin-top 4px
> [data-fa]
margin-right 4px
> .mk-note-detail > .mk-note-detail
margin 0 auto margin 0 auto

View File

@ -62,7 +62,7 @@ export default Vue.extend({
more() { more() {
this.moreFetching = true; this.moreFetching = true;
(this as any).api('notes/list-timeline', { (this as any).api('notes/user-list-timeline', {
listId: this.list.id, listId: this.list.id,
limit: fetchLimit + 1, limit: fetchLimit + 1,
untilId: (this.$refs.timeline as any).tail().id, untilId: (this.$refs.timeline as any).tail().id,

View File

@ -6,8 +6,8 @@
<mk-note-detail :note="note"/> <mk-note-detail :note="note"/>
</div> </div>
<footer> <footer>
<a v-if="note.prev" :href="note.prev">%fa:angle-left% %i18n:@prev%</a> <router-link v-if="note.prev" :to="note.prev">%fa:angle-left% %i18n:@prev%</router-link>
<a v-if="note.next" :href="note.next">%i18n:@next% %fa:angle-right%</a> <router-link v-if="note.next" :to="note.next">%i18n:@next% %fa:angle-right%</router-link>
</footer> </footer>
</main> </main>
</mk-ui> </mk-ui>

View File

@ -9,6 +9,7 @@ import User from './user';
import DriveFileThumbnail, { deleteDriveFileThumbnail } from './drive-file-thumbnail'; import DriveFileThumbnail, { deleteDriveFileThumbnail } from './drive-file-thumbnail';
const DriveFile = monkDb.get<IDriveFile>('driveFiles.files'); const DriveFile = monkDb.get<IDriveFile>('driveFiles.files');
DriveFile.createIndex('md5');
DriveFile.createIndex('metadata.uri', { sparse: true, unique: true }); DriveFile.createIndex('metadata.uri', { sparse: true, unique: true });
export default DriveFile; export default DriveFile;

View File

@ -15,9 +15,8 @@ import Notification, { deleteNotification } from './notification';
import Following from './following'; import Following from './following';
const Note = db.get<INote>('notes'); const Note = db.get<INote>('notes');
Note.createIndex('uri', { sparse: true, unique: true }); Note.createIndex('uri', { sparse: true, unique: true });
Note.createIndex('userId');
export default Note; export default Note;
export function isValidText(text: string): boolean { export function isValidText(text: string): boolean {
@ -271,41 +270,10 @@ export const pack = async (
// When requested a detailed note data // When requested a detailed note data
if (opts.detail) { if (opts.detail) {
// Get previous note info //#region 重いので廃止
_note.prev = (async () => { _note.prev = null;
const prev = await Note.findOne({ _note.next = null;
userId: _note.userId, //#endregion
_id: {
$lt: id
}
}, {
fields: {
_id: true
},
sort: {
_id: -1
}
});
return prev ? prev._id.toHexString() : null;
})();
// Get next note info
_note.next = (async () => {
const next = await Note.findOne({
userId: _note.userId,
_id: {
$gt: id
}
}, {
fields: {
_id: true
},
sort: {
_id: 1
}
});
return next ? next._id.toHexString() : null;
})();
if (_note.replyId) { if (_note.replyId) {
// Populate reply to note // Populate reply to note

View File

@ -14,7 +14,7 @@ export default async (job: kue.Job, done): Promise<void> => {
done(); done();
} else { } else {
console.warn(`deliver failed: ${res.statusMessage}`); console.warn(`deliver failed: ${res.statusMessage}`);
done(new Error(res.statusMessage)); done(res);
} }
} }
}; };

View File

@ -43,27 +43,21 @@ function parse(html: string): string {
break; break;
case 'a': case 'a':
const cls = node.attrs const txt = getText(node);
? (node.attrs.find(x => x.name == 'class') || { value: '' }).value.split(' ')
: [];
// for Mastodon // メンション
if (cls.includes('mention')) { if (txt.startsWith('@')) {
const mention = getText(node); const part = txt.split('@');
const part = mention.split('@');
if (part.length == 2) { if (part.length == 2) {
//#region ホスト名部分が省略されているので復元する //#region ホスト名部分が省略されているので復元する
const href = new URL(node.attrs.find(x => x.name == 'href').value); const href = new URL(node.attrs.find(x => x.name == 'href').value);
const acct = mention + '@' + href.hostname; const acct = txt + '@' + href.hostname;
text += acct; text += acct;
break; break;
//#endregion //#endregion
} else if (part.length == 3) { } else if (part.length == 3) {
text += mention; text += txt;
break; break;
} }
} }

View File

@ -57,6 +57,8 @@ export default (
.count({ .count({
recipientId: userId, recipientId: userId,
isRead: false isRead: false
}, {
limit: 1
}); });
if (count == 0) { if (count == 0) {

View File

@ -43,6 +43,8 @@ export default (
.count({ .count({
notifieeId: userId, notifieeId: userId,
isRead: false isRead: false
}, {
limit: 1
}); });
if (count == 0) { if (count == 0) {

View File

@ -38,12 +38,9 @@ module.exports = (params, user) => new Promise(async (res, rej) => {
if (pollErr) return rej('invalid poll param'); if (pollErr) return rej('invalid poll param');
const query = { const query = {
createdAt: { _id: { $gte: new Date(Date.now() - ms('1days')) },
$gte: new Date(Date.now() - ms('1days')) renoteCount: { $gt: 0 },
}, '_user.host': null
renoteCount: {
$gt: 0
}
} as any; } as any;
if (reply != undefined) { if (reply != undefined) {

View File

@ -1,48 +1,26 @@
/**
* Module dependencies
*/
import Note from '../../../models/note'; import Note from '../../../models/note';
import User from '../../../models/user'; import User from '../../../models/user';
/** /**
* @swagger * Get the misskey's statistics
* /stats:
* note:
* summary: Show the misskey's statistics
* responses:
* 200:
* description: Success
* schema:
* type: object
* properties:
* notesCount:
* description: count of all notes of misskey
* type: number
* usersCount:
* description: count of all users of misskey
* type: number
*
* default:
* description: Failed
* schema:
* $ref: "#/definitions/Error"
*/
/**
* Show the misskey's statistics
*
* @param {any} params
* @return {Promise<any>}
*/ */
module.exports = params => new Promise(async (res, rej) => { module.exports = params => new Promise(async (res, rej) => {
const notesCount = await Note const notesCount = await Note.count();
.count();
const usersCount = await User const usersCount = await User.count();
.count();
const originalNotesCount = await Note.count({
'_user.host': null
});
const originalUsersCount = await User.count({
host: null
});
res({ res({
notesCount: notesCount, notesCount,
usersCount: usersCount usersCount,
originalNotesCount,
originalUsersCount
}); });
}); });

View File

@ -87,7 +87,7 @@ router.get('/url', require('./url-preview'));
//#region for crawlers //#region for crawlers
// User // User
router.get('/@:user', async ctx => { router.get('/@:user', async (ctx, next) => {
const { username, host } = parseAcct(ctx.params.user); const { username, host } = parseAcct(ctx.params.user);
const user = await User.findOne({ const user = await User.findOne({
usernameLower: username.toLowerCase(), usernameLower: username.toLowerCase(),
@ -97,7 +97,8 @@ router.get('/@:user', async ctx => {
if (user != null) { if (user != null) {
await ctx.render('user', { user }); await ctx.render('user', { user });
} else { } else {
ctx.status = 404; // リモートユーザーなので
await next();
} }
}); });

View File

@ -14,8 +14,8 @@ module.exports = async (ctx: Koa.Context) => {
function wrap(url: string): string { function wrap(url: string): string {
return url != null return url != null
? url.startsWith('https://') ? url.startsWith('https://') || url.startsWith('data:')
? url ? url
: `https://images.weserv.nl/?url=${url.replace(/^http:\/\//, '')}` : `https://images.weserv.nl/?url=${encodeURIComponent(url.replace(/^http:\/\//, ''))}`
: null; : null;
} }

View File

@ -118,7 +118,8 @@ const addFile = async (
// Check if there is a file with the same hash // Check if there is a file with the same hash
const much = await DriveFile.findOne({ const much = await DriveFile.findOne({
md5: hash, md5: hash,
'metadata.userId': user._id 'metadata.userId': user._id,
'metadata.deletedAt': { $exists: false }
}); });
if (much !== null) { if (much !== null) {

View File

@ -392,14 +392,17 @@ export default async (user: IUser, data: {
} }
} }
//#region TODO: これ重い
// 今までで同じ投稿をRenoteしているか // 今までで同じ投稿をRenoteしているか
const existRenote = await Note.findOne({ //const existRenote = await Note.findOne({
userId: user._id, // userId: user._id,
renoteId: data.renote._id, // renoteId: data.renote._id,
_id: { // _id: {
$ne: note._id // $ne: note._id
} // }
}); //});
const existRenote = null;
//#endregion
if (!existRenote) { if (!existRenote) {
// Update renoteee status // Update renoteee status