Merge branch 'develop' into twemoji
This commit is contained in:
		
						commit
						136f23c7ad
					
				|  | @ -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 | ||||
|  |  | |||
							
								
								
									
										41
									
								
								.travis.yml
								
								
								
								
							
							
						
						
									
										41
									
								
								.travis.yml
								
								
								
								
							|  | @ -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 | ||||
|  | @ -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`. | ||||
|  |  | |||
|  | @ -4,7 +4,6 @@ | |||
| ================================================================ | ||||
| 
 | ||||
| [](https://circleci.com/gh/syuilo/misskey) | ||||
| [![][travis-badge]][travis-link] | ||||
| [![][dependencies-badge]][dependencies-link] | ||||
| [](http://makeapullrequest.com) | ||||
| 
 | ||||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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以上) | ||||
| 
 | ||||
| ##### オプション | ||||
|  |  | |||
|  | @ -1077,8 +1077,9 @@ 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: "保存しました" | ||||
|  | @ -1151,6 +1152,9 @@ admin/views/announcements.vue: | |||
|   title: "タイトル" | ||||
|   text: "内容" | ||||
|   saved: "保存しました" | ||||
|   _remove: | ||||
|     are-you-sure: "「$1」を削除しますか?" | ||||
|     removed: "削除しました" | ||||
| 
 | ||||
| admin/views/hashtags.vue: | ||||
|   hided-tags: "Hidden Tags" | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| { | ||||
| 	"name": "misskey", | ||||
| 	"author": "syuilo <i@syuilo.com>", | ||||
| 	"version": "10.38.6", | ||||
| 	"clientVersion": "1.0.11516", | ||||
| 	"version": "10.38.7", | ||||
| 	"clientVersion": "1.0.11530", | ||||
| 	"codename": "nighthike", | ||||
| 	"main": "./built/index.js", | ||||
| 	"private": true, | ||||
|  |  | |||
|  | @ -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,18 +46,31 @@ 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.$swal({ | ||||
| 					type: 'success', | ||||
| 					text: '%i18n:@saved%' | ||||
| 				}); | ||||
| 				if (!silent) { | ||||
| 					this.$swal({ | ||||
| 						type: 'success', | ||||
| 						text: '%i18n:@saved%' | ||||
| 					}); | ||||
| 				} | ||||
| 			}).catch(e => { | ||||
| 				this.$swal({ | ||||
| 					type: 'error', | ||||
|  |  | |||
|  | @ -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; | ||||
| 		}); | ||||
| 	}, | ||||
| 
 | ||||
|  | @ -69,7 +72,8 @@ 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.$swal({ | ||||
| 					type: 'success', | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -107,8 +107,6 @@ export type Source = { | |||
| 		engine: string; | ||||
| 		timeout: number; | ||||
| 	}; | ||||
| 
 | ||||
| 	maxNoteTextLength?: number; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  |  | |||
|  | @ -43,4 +43,9 @@ export type IMeta = { | |||
| 	disableLocalTimeline?: boolean; | ||||
| 	hidedTags?: string[]; | ||||
| 	bannerUrl?: string; | ||||
| 
 | ||||
| 	/** | ||||
| 	 * Max allowed note text length in charactors | ||||
| 	 */ | ||||
| 	maxNoteTextLength?: number; | ||||
| }; | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
|  |  | |||
|  | @ -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 }); | ||||
|  |  | |||
|  | @ -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, | ||||
| 
 | ||||
|  |  | |||
|  | @ -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': '投稿内容' | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue