Compare commits

...

17 Commits

Author SHA1 Message Date
syuilo
712802e682 10.38.7 2018-11-05 11:11:23 +09:00
syuilo
abe99c3c73 Update locales/ja-JP.yml 2018-11-05 11:10:02 +09:00
syuilo
d7a3b71028 投稿の最大文字数情報を設定ファイルではなくDBに保存するように 2018-11-05 11:09:05 +09:00
syuilo
10c434f24a Remove Travis
Closes #3109
2018-11-05 10:52:07 +09:00
syuilo
fe46c53ea6 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-11-05 10:48:51 +09:00
syuilo
cdd123dfd3 [doc] specify node version 2018-11-05 10:48:40 +09:00
Acid Chicken (硫酸鶏)
a1a3ee44b5 Implement /api/v1/custom_emojis (#3116) 2018-11-05 10:45:57 +09:00
syuilo
a86c419f95 Merge branch 'develop' of https://github.com/syuilo/misskey into develop 2018-11-05 10:40:15 +09:00
syuilo
e3ec0ad97e [Client] Improve admin panel usability 2018-11-05 10:40:01 +09:00
Acid Chicken (硫酸鶏)
75791981ce Fix #3115 2018-11-05 10:34:53 +09:00
syuilo
e813fe16b9 [API] Better validation of admin/emoji/add 2018-11-05 10:33:49 +09:00
syuilo
42ac7b954d Improve admin panel usability 2018-11-05 10:32:45 +09:00
syuilo
c1bbf5dab6 [Client] Fix error 2018-11-05 10:29:57 +09:00
Aya Morisawa
e16dc2a910 Update README.md (#3112) 2018-11-05 01:57:08 +09:00
syuilo
e236c05d79 10.38.6 2018-11-05 01:43:31 +09:00
syuilo
454c1e3faf [API] Fix bug 2018-11-05 01:42:41 +09:00
syuilo
43daf814df [Client] 絵文字登録フォームに便利情報を表示 2018-11-05 01:33:06 +09:00
24 changed files with 156 additions and 98 deletions

View File

@@ -167,6 +167,3 @@ drive:
# external: true
# engine: http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-misskey-api.cgi?{{host}}+{{user}}+{{limit}}+{{offset}}
# timeout: 300000
# Max allowed note text length in charactors
maxNoteTextLength: 1000

View File

@@ -1,41 +0,0 @@
# travis file
# https://docs.travis-ci.com/user/customizing-the-build
notifications:
email: false
branches:
except:
- l10n_master
language: node_js
node_js:
- 11.0.0
env:
- CXX=g++-4.8 NODE_ENV=production
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
cache:
directories:
- node_modules
services:
- mongodb
- redis-server
before_script:
- npm install
# 設定ファイルを配置
- cp ./.ci/default.yml ./.config
- cp ./.ci/test.yml ./.config
- travis_wait npm run build

View File

@@ -23,5 +23,5 @@ Please use [Crowdin](https://crowdin.com/project/misskey) for localization.
* Test codes are located in `/test`.
## Continuous integration
Misskey uses Travis for automated test.
Configuration files are located in `/.travis`.
Misskey uses CircleCI for automated test.
Configuration files are located in `/.circleci`.

View File

@@ -4,7 +4,6 @@
================================================================
[![CircleCI](https://circleci.com/gh/syuilo/misskey.svg?style=svg)](https://circleci.com/gh/syuilo/misskey)
[![][travis-badge]][travis-link]
[![][dependencies-badge]][dependencies-link]
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
@@ -44,7 +43,7 @@ Easiest way to tell your emotions. Misskey allows you to add various type of rea
<h3 align="left">Interface</h3>
<p align="left">
No UI fits for everyone. Therefore, Misskey has a highly customizable UI for your taste. You can edit layouts of your timeline, place selectable widgets you can easily move and create your unique home as this place will be your home.
Highly customizable UI for your taste. We understand no UI fits for everyone. You can edit layouts of your timeline, place selectable widgets you can easily move and create your unique home as this place will be your home.
</p>
---
@@ -124,8 +123,6 @@ Misskey is an open-source software licensed under the [GNU AGPLv3](LICENSE).
[agpl-3.0]: https://www.gnu.org/licenses/agpl-3.0.en.html
[agpl-3.0-badge]: https://img.shields.io/badge/license-AGPL--3.0-444444.svg?style=flat-square
[travis-link]: https://travis-ci.org/syuilo/misskey
[travis-badge]: http://img.shields.io/travis/syuilo/misskey/master.svg?style=flat-square
[dependencies-link]: https://david-dm.org/syuilo/misskey
[dependencies-badge]: https://img.shields.io/david/syuilo/misskey.svg?style=flat-square

View File

@@ -22,7 +22,7 @@ adduser --disabled-password --disabled-login misskey
Please install and setup these softwares:
#### Dependencies :package:
* **[Node.js](https://nodejs.org/en/)**
* **[Node.js](https://nodejs.org/en/)** >= 10.0.0
* **[MongoDB](https://www.mongodb.com/)** >= 3.6
##### Optional

View File

@@ -22,7 +22,7 @@ adduser --disabled-password --disabled-login misskey
これらのソフトウェアをインストール・設定してください:
#### 依存関係 :package:
* **[Node.js](https://nodejs.org/en/)**
* **[Node.js](https://nodejs.org/en/)** (10.0.0以上)
* **[MongoDB](https://www.mongodb.com/)** (3.6以上)
##### オプション

View File

@@ -1077,10 +1077,12 @@ admin/views/instance.vue:
instance-name: "インスタンス名"
instance-description: "インスタンスの紹介"
banner-url: "バナー画像URL"
disableRegistration: "ユーザー登録の受付を停止する"
disableLocalTimeline: "ローカルタイムラインを無効にする"
max-note-text-length: "投稿の最大文字数"
disable-registration: "ユーザー登録の受付を停止する"
disable-local-timeline: "ローカルタイムラインを無効にする"
invite: "招待"
save: "保存"
saved: "保存しました"
admin/views/charts.vue:
title: "チャート"
@@ -1131,10 +1133,16 @@ admin/views/emoji.vue:
aliases-desc: "スペースで区切って複数設定できます。"
url: "絵文字画像URL"
add: "追加"
info: "50KB以下のPNG画像をおすすめします。"
added: "絵文字を登録しました"
emojis:
title: "絵文字一覧"
update: "更新"
remove: "削除"
updated: "更新しました"
remove-emoji:
are-you-sure: "「$1」を削除しますか"
removed: "削除しました"
admin/views/announcements.vue:
announcements: "お知らせ"
@@ -1143,6 +1151,10 @@ admin/views/announcements.vue:
add: "追加"
title: "タイトル"
text: "内容"
saved: "保存しました"
_remove:
are-you-sure: "「$1」を削除しますか"
removed: "削除しました"
admin/views/hashtags.vue:
hided-tags: "Hidden Tags"

View File

@@ -1,8 +1,8 @@
{
"name": "misskey",
"author": "syuilo <i@syuilo.com>",
"version": "10.38.5",
"clientVersion": "1.0.11513",
"version": "10.38.7",
"clientVersion": "1.0.11530",
"codename": "nighthike",
"main": "./built/index.js",
"private": true,

View File

@@ -10,7 +10,7 @@
<span>%i18n:@text%</span>
</ui-textarea>
<ui-horizon-group>
<ui-button @click="save">%fa:save R% %i18n:@save%</ui-button>
<ui-button @click="save()">%fa:save R% %i18n:@save%</ui-button>
<ui-button @click="remove(i)">%fa:trash-alt R% %i18n:@remove%</ui-button>
</ui-horizon-group>
</section>
@@ -46,17 +46,36 @@ export default Vue.extend({
},
remove(i) {
this.announcements = this.announcements.filter((_, j) => j !== i);
this.save();
this.$swal({
type: 'warning',
text: '%i18n:@_remove.are-you-sure%'.replace('$1', this.announcements.find((_, j) => j == i).title),
showCancelButton: true
}).then(res => {
if (!res.value) return;
this.announcements = this.announcements.filter((_, j) => j !== i);
this.save(true);
this.$swal({
type: 'success',
text: '%i18n:@_remove.removed%'
});
});
},
save() {
save(silent) {
(this as any).api('admin/update-meta', {
broadcasts: this.announcements
}).then(() => {
//(this as any).os.apis.dialog({ text: `Saved` });
if (!silent) {
this.$swal({
type: 'success',
text: '%i18n:@saved%'
});
}
}).catch(e => {
//(this as any).os.apis.dialog({ text: `Failed ${e}` });
this.$swal({
type: 'error',
text: e
});
});
}
}

View File

@@ -16,6 +16,7 @@
<ui-input v-model="url">
<span>%i18n:@add-emoji.url%</span>
</ui-input>
<ui-info>%i18n:@add-emoji.info%</ui-info>
<ui-button @click="add">%i18n:@add-emoji.add%</ui-button>
</section>
</ui-card>
@@ -68,15 +69,22 @@ export default Vue.extend({
url: this.url,
aliases: this.aliases.split(' ')
}).then(() => {
//(this as any).os.apis.dialog({ text: `Added` });
this.$swal({
type: 'success',
text: '%i18n:@add-emoji.added%'
});
this.fetchEmojis();
}).catch(e => {
//(this as any).os.apis.dialog({ text: `Failed ${e}` });
this.$swal({
type: 'error',
text: e
});
});
},
fetchEmojis() {
(this as any).api('admin/emoji/list').then(emojis => {
emojis.reverse();
emojis.forEach(e => e.aliases = (e.aliases || []).join(' '));
this.emojis = emojis;
});
@@ -89,20 +97,40 @@ export default Vue.extend({
url: emoji.url,
aliases: emoji.aliases.split(' ')
}).then(() => {
//(this as any).os.apis.dialog({ text: `Updated` });
this.$swal({
type: 'success',
text: '%i18n:@updated%'
});
}).catch(e => {
//(this as any).os.apis.dialog({ text: `Failed ${e}` });
this.$swal({
type: 'error',
text: e
});
});
},
removeEmoji(emoji) {
(this as any).api('admin/emoji/remove', {
id: emoji.id
}).then(() => {
//(this as any).os.apis.dialog({ text: `Removed` });
this.fetchEmojis();
}).catch(e => {
//(this as any).os.apis.dialog({ text: `Failed ${e}` });
this.$swal({
type: 'warning',
text: '%i18n:@remove-emoji.are-you-sure%'.replace('$1', emoji.name),
showCancelButton: true
}).then(res => {
if (!res.value) return;
(this as any).api('admin/emoji/remove', {
id: emoji.id
}).then(() => {
this.$swal({
type: 'success',
text: '%i18n:@remove-emoji.removed%'
});
this.fetchEmojis();
}).catch(e => {
this.$swal({
type: 'error',
text: e
});
});
});
}
}

View File

@@ -6,6 +6,7 @@
<ui-input v-model="name">%i18n:@instance-name%</ui-input>
<ui-textarea v-model="description">%i18n:@instance-description%</ui-textarea>
<ui-input v-model="bannerUrl">%i18n:@banner-url%</ui-input>
<ui-input v-model="maxNoteTextLength">%i18n:@max-note-text-length%</ui-input>
<ui-button @click="updateMeta">%i18n:@save%</ui-button>
</section>
</ui-card>
@@ -39,6 +40,7 @@ export default Vue.extend({
bannerUrl: null,
name: null,
description: null,
maxNoteTextLength: null,
inviteCode: null,
};
},
@@ -48,6 +50,7 @@ export default Vue.extend({
this.bannerUrl = meta.bannerUrl;
this.name = meta.name;
this.description = meta.description;
this.maxNoteTextLength = meta.maxNoteTextLength;
});
},
@@ -56,7 +59,10 @@ export default Vue.extend({
(this as any).api('admin/invite').then(x => {
this.inviteCode = x.code;
}).catch(e => {
//(this as any).os.apis.dialog({ text: `Failed ${e}` });
this.$swal({
type: 'error',
text: e
});
});
},
@@ -66,11 +72,18 @@ export default Vue.extend({
disableLocalTimeline: this.disableLocalTimeline,
bannerUrl: this.bannerUrl,
name: this.name,
description: this.description
description: this.description,
maxNoteTextLength: parseInt(this.maxNoteTextLength, 10)
}).then(() => {
//(this as any).os.apis.dialog({ text: `Saved` });
this.$swal({
type: 'success',
text: '%i18n:@saved%'
});
}).catch(e => {
//(this as any).os.apis.dialog({ text: `Failed ${e}` });
this.$swal({
type: 'error',
text: e
});
});
}
}

View File

@@ -12,7 +12,11 @@
<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
inject: ['horizonGrouped'],
inject: {
horizonGrouped: {
default: false
}
},
props: {
type: {
type: String,

View File

@@ -41,7 +41,11 @@ import Vue from 'vue';
const getPasswordStrength = require('syuilo-password-strength');
export default Vue.extend({
inject: ['horizonGrouped'],
inject: {
horizonGrouped: {
default: false
}
},
props: {
value: {
required: false

View File

@@ -49,8 +49,6 @@ export default function load() {
if (config.localDriveCapacityMb == null) config.localDriveCapacityMb = 256;
if (config.remoteDriveCapacityMb == null) config.remoteDriveCapacityMb = 8;
if (config.maxNoteTextLength == null) config.maxNoteTextLength = 1000;
return Object.assign(config, mixin);
}

View File

@@ -107,8 +107,6 @@ export type Source = {
engine: string;
timeout: number;
};
maxNoteTextLength?: number;
};
/**

View File

@@ -43,4 +43,9 @@ export type IMeta = {
disableLocalTimeline?: boolean;
hidedTags?: string[];
bannerUrl?: string;
/**
* Max allowed note text length in charactors
*/
maxNoteTextLength?: number;
};

View File

@@ -11,7 +11,6 @@ import Reaction from './note-reaction';
import { packMany as packFileMany, IDriveFile } from './drive-file';
import Favorite from './favorite';
import Following from './following';
import config from '../config';
import Emoji from './emoji';
const Note = db.get<INote>('notes');
@@ -27,10 +26,6 @@ Note.createIndex({ createdAt: -1 });
Note.createIndex({ score: -1 }, { sparse: true });
export default Note;
export function isValidText(text: string): boolean {
return length(text.trim()) <= config.maxNoteTextLength && text.trim() != '';
}
export function isValidCw(text: string): boolean {
return length(text.trim()) <= 100;
}

View File

@@ -12,15 +12,15 @@ export const meta = {
params: {
name: {
validator: $.str
validator: $.str.min(1)
},
url: {
validator: $.str
validator: $.str.min(1)
},
aliases: {
validator: $.arr($.str).optional,
validator: $.arr($.str.min(1)).optional,
default: [] as string[]
}
}

View File

@@ -59,6 +59,13 @@ export const meta = {
'ja-JP': 'インスタンスの紹介文'
}
},
maxNoteTextLength: {
validator: $.num.optional.min(1),
desc: {
'ja-JP': '投稿の最大文字数'
}
}
}
};
@@ -93,6 +100,10 @@ export default define(meta, (ps) => new Promise(async (res, rej) => {
set.description = ps.description;
}
if (ps.maxNoteTextLength) {
set.maxNoteTextLength = ps.maxNoteTextLength;
}
await Meta.update({}, {
$set: set
}, { upsert: true });

View File

@@ -26,7 +26,7 @@ export const meta = {
export default define(meta, (ps, user) => new Promise(async (res, rej) => {
const folders = await DriveFolder
.find({
name: name,
name: ps.name,
userId: user._id,
parentId: ps.parentId
});

View File

@@ -62,7 +62,7 @@ export default define(meta, (ps, me) => new Promise(async (res, rej) => {
swPublickey: config.sw ? config.sw.public_key : null,
hidedTags: (me && me.isAdmin) ? met.hidedTags : undefined,
bannerUrl: met.bannerUrl,
maxNoteTextLength: config.maxNoteTextLength,
maxNoteTextLength: met.maxNoteTextLength || 1000,
emojis: emojis,

View File

@@ -1,10 +1,20 @@
import $ from 'cafy'; import ID, { transform, transformMany } from '../../../../misc/cafy-id';
const ms = require('ms');
import Note, { INote, isValidText, isValidCw, pack } from '../../../../models/note';
import { length } from 'stringz';
import Note, { INote, isValidCw, pack } from '../../../../models/note';
import User, { IUser } from '../../../../models/user';
import DriveFile, { IDriveFile } from '../../../../models/drive-file';
import create from '../../../../services/note/create';
import define from '../../define';
import Meta from '../../../../models/meta';
let maxNoteTextLength = 1000;
setInterval(() => {
Meta.findOne({}).then(m => {
if (m.maxNoteTextLength) maxNoteTextLength = m.maxNoteTextLength;
});
}, 3000);
export const meta = {
stability: 'stable',
@@ -40,7 +50,9 @@ export const meta = {
},
text: {
validator: $.str.optional.nullable.pipe(isValidText),
validator: $.str.optional.nullable.pipe(text =>
length(text.trim()) <= maxNoteTextLength && text.trim() != ''
),
default: null as any,
desc: {
'ja-JP': '投稿内容'

View File

@@ -4,12 +4,18 @@ import { toASCII } from 'punycode';
import config from '../../config';
import Meta from '../../models/meta';
import { ObjectID } from 'bson';
import Emoji from '../../models/emoji';
const pkg = require('../../../package.json');
// Init router
const router = new Router();
router.get('/v1/custom_emojis', async ctx => ctx.body = {});
router.get('/v1/custom_emojis', async ctx => ctx.body =
await Emoji.find({ host: null }, {
fields: {
_id: false
}
}));
router.get('/v1/instance', async ctx => { // TODO: This is a temporary implementation. Consider creating helper methods!
const meta = await Meta.findOne() || {};

View File

@@ -109,7 +109,7 @@ if (!config.github || !redis) {
}
const params = {
redirect_uri: `${config.url}:8089/api/gh/cb`,
redirect_uri: `${config.url}/api/gh/cb`,
scope: ['read:user'],
state: uuid()
};
@@ -122,7 +122,7 @@ if (!config.github || !redis) {
const sessid = uuid();
const params = {
redirect_uri: `${config.url}:8089/api/gh/cb`,
redirect_uri: `${config.url}/api/gh/cb`,
scope: ['read:user'],
state: uuid()
};