Merge branch 'develop'
This commit is contained in:
		
						commit
						d040dc19bc
					
				
					 35 changed files with 295 additions and 99 deletions
				
			
		| 
						 | 
				
			
			@ -118,7 +118,6 @@ export default Vue.extend({
 | 
			
		|||
				fileType: image,
 | 
			
		||||
				excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
 | 
			
		||||
				limit: 9,
 | 
			
		||||
				untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
			
		||||
			}).then(notes => {
 | 
			
		||||
				for (const note of notes) {
 | 
			
		||||
					for (const file of note.files) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,6 @@ export default Vue.extend({
 | 
			
		|||
			fileType: image,
 | 
			
		||||
			excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
 | 
			
		||||
			limit: 9,
 | 
			
		||||
			untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
			
		||||
		}).then(notes => {
 | 
			
		||||
			for (const note of notes) {
 | 
			
		||||
				for (const file of note.files) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
<template>
 | 
			
		||||
<mk-ui>
 | 
			
		||||
	<b-card :header="$t('header')">
 | 
			
		||||
	<b-card :header="$t('manage-apps')">
 | 
			
		||||
		<b-button to="/app/new" variant="primary">{{ $t('create-app') }}</b-button>
 | 
			
		||||
		<hr>
 | 
			
		||||
		<div class="apps">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,35 +1,22 @@
 | 
			
		|||
<template>
 | 
			
		||||
<mk-ui>
 | 
			
		||||
	<b-card :header="$t('header')">
 | 
			
		||||
	<b-card :header="$t('new-app')">
 | 
			
		||||
		<b-alert show variant="info"><fa icon="info-circle"/> {{ $t('new-app-info') }}</b-alert>
 | 
			
		||||
		<b-form @submit.prevent="onSubmit" autocomplete="off">
 | 
			
		||||
			<b-form-group :label="$t('app-name')" :description="$t('description')">
 | 
			
		||||
				<b-form-input v-model="name" type="text" :placeholder="$t('placeholder')" autocomplete="off" required/>
 | 
			
		||||
			<b-form-group :label="$t('app-name')" :description="$t('app-name-desc')">
 | 
			
		||||
				<b-form-input v-model="name" type="text" :placeholder="$t('app-name-placeholder')" autocomplete="off" required/>
 | 
			
		||||
			</b-form-group>
 | 
			
		||||
			<b-form-group :label="$t('app-overview')" :description="$t('description')">
 | 
			
		||||
				<b-textarea v-model="description" :placeholder="$t('placeholder')" autocomplete="off" required></b-textarea>
 | 
			
		||||
			<b-form-group :label="$t('app-overview')" :description="$t('app-overview-desc')">
 | 
			
		||||
				<b-textarea v-model="description" :placeholder="$t('app-overview-placeholder')" autocomplete="off" required></b-textarea>
 | 
			
		||||
			</b-form-group>
 | 
			
		||||
			<b-form-group :label="$t('callback-url')" :description="$t('description')">
 | 
			
		||||
				<b-input v-model="cb" type="url" placeholder="ex) https://your.app.example.com/callback.php" autocomplete="off"/>
 | 
			
		||||
			<b-form-group :label="$t('callback-url')" :description="$t('callback-url-desc')">
 | 
			
		||||
				<b-input v-model="cb" type="url" :placeholder="$t('callback-url-placeholder')" autocomplete="off"/>
 | 
			
		||||
			</b-form-group>
 | 
			
		||||
			<b-card :header="$t('header')">
 | 
			
		||||
				<b-form-group :description="$t('description')">
 | 
			
		||||
			<b-card :header="$t('authority')">
 | 
			
		||||
				<b-form-group :description="$t('authority-desc')">
 | 
			
		||||
					<b-alert show variant="warning"><fa icon="exclamation-triangle"/> {{ $t('authority-warning') }}</b-alert>
 | 
			
		||||
					<b-form-checkbox-group v-model="permission" stacked>
 | 
			
		||||
						<b-form-checkbox value="read:account">{{ $t('read:account') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:account">{{ $t('write:account') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:notes">{{ $t('write:notes') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="read:reactions">{{ $t('read:reactions') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:reactions">{{ $t('write:reactions') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="read:following">{{ $t('read:following') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:following">{{ $t('write:following') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="read:mutes">{{ $t('read:mutes') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:mutes">{{ $t('write:mutes') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="read:blocks">{{ $t('read:blocks') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:blocks">{{ $t('write:blocks') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="read:drive">{{ $t('read:drive') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:drive">{{ $t('write:drive') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="read:notifications">{{ $t('read:notifications') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox value="write:notifications">{{ $t('write:notifications') }}</b-form-checkbox>
 | 
			
		||||
						<b-form-checkbox v-for="v in permissionsList" :value="v" :key="v">{{ $t(`@.permissions.${v}`) }} ({{ v }})</b-form-checkbox>
 | 
			
		||||
					</b-form-checkbox-group>
 | 
			
		||||
				</b-form-group>
 | 
			
		||||
			</b-card>
 | 
			
		||||
| 
						 | 
				
			
			@ -43,6 +30,8 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
import Vue from 'vue';
 | 
			
		||||
import i18n from '../../i18n';
 | 
			
		||||
import { kinds } from '../../../../server/api/kinds';
 | 
			
		||||
 | 
			
		||||
export default Vue.extend({
 | 
			
		||||
	i18n: i18n('dev/views/new-app.vue'),
 | 
			
		||||
	data() {
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +40,8 @@ export default Vue.extend({
 | 
			
		|||
			description: '',
 | 
			
		||||
			cb: '',
 | 
			
		||||
			nidState: null,
 | 
			
		||||
			permission: []
 | 
			
		||||
			permission: [],
 | 
			
		||||
			permissionsList: kinds
 | 
			
		||||
		};
 | 
			
		||||
	},
 | 
			
		||||
	methods: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,7 +39,7 @@
 | 
			
		|||
					<span :data-active="src == 'messages'" @click="src = 'messages'"><fa :icon="['far', 'envelope']"/> {{ $t('messages') }}<i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes"><fa icon="circle"/></i></span>
 | 
			
		||||
					<template v-if="lists">
 | 
			
		||||
						<div class="hr" v-if="lists.length > 0"></div>
 | 
			
		||||
						<span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id"><fa icon="list"/> {{ l.title }}</span>
 | 
			
		||||
						<span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id"><fa icon="list"/> {{ l.name }}</span>
 | 
			
		||||
					</template>
 | 
			
		||||
					<div class="hr" v-if="$store.state.settings.tagTimelines && $store.state.settings.tagTimelines.length > 0"></div>
 | 
			
		||||
					<span v-for="tl in $store.state.settings.tagTimelines" :data-active="src == 'tag' && tagTl == tl" @click="src = 'tag'; tagTl = tl" :key="tl.id"><fa icon="hashtag"/> {{ tl.title }}</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,6 @@ export default Vue.extend({
 | 
			
		|||
	mounted() {
 | 
			
		||||
		this.$root.api('users/notes', {
 | 
			
		||||
			userId: this.user.id,
 | 
			
		||||
			untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
			
		||||
		}).then(notes => {
 | 
			
		||||
			this.notes = notes;
 | 
			
		||||
			this.fetching = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,6 @@ export default Vue.extend({
 | 
			
		|||
			fileType: image,
 | 
			
		||||
			excludeNsfw: !this.$store.state.device.alwaysShowNsfw,
 | 
			
		||||
			limit: 9,
 | 
			
		||||
			untilDate: new Date().getTime() + 1000 * 86400 * 365
 | 
			
		||||
		}).then(notes => {
 | 
			
		||||
			for (const note of notes) {
 | 
			
		||||
				for (const file of note.files) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ export class AppRepository extends Repository<App> {
 | 
			
		|||
		return {
 | 
			
		||||
			id: app.id,
 | 
			
		||||
			name: app.name,
 | 
			
		||||
			callbackUrl: app.callbackUrl,
 | 
			
		||||
			...(opts.includeSecret ? { secret: app.secret } : {}),
 | 
			
		||||
			...(me ? {
 | 
			
		||||
				isAuthorized: await AccessTokens.count({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,8 @@ export class AuthSessionRepository extends Repository<AuthSession> {
 | 
			
		|||
 | 
			
		||||
		return await rap({
 | 
			
		||||
			id: session.id,
 | 
			
		||||
			app: Apps.pack(session.appId, me)
 | 
			
		||||
			app: Apps.pack(session.appId, me),
 | 
			
		||||
			token: session.token
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	public getPublicUrl(file: DriveFile, thumbnail = false): string | null {
 | 
			
		||||
		return thumbnail ? (file.thumbnailUrl || file.webpublicUrl || null) : (file.webpublicUrl || file.thumbnailUrl || file.url);
 | 
			
		||||
		return thumbnail ? (file.thumbnailUrl || file.webpublicUrl || null) : (file.webpublicUrl || file.url);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public async clacDriveUsageOf(user: User['id'] | User): Promise<number> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,3 +115,8 @@ export function cumulativeSum(xs: number[]): number[] {
 | 
			
		|||
	for (let i = 1; i < ys.length; i++) ys[i] += ys[i - 1];
 | 
			
		||||
	return ys;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Object.fromEntries()
 | 
			
		||||
export function fromEntries(xs: [string, any][]): { [x: string]: any; } {
 | 
			
		||||
	return xs.reduce((obj, [k, v]) => Object.assign(obj, { [k]: v }), {} as { [x: string]: any; });
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ import $ from 'cafy';
 | 
			
		|||
import define from '../../define';
 | 
			
		||||
import { Apps } from '../../../../models';
 | 
			
		||||
import { genId } from '../../../../misc/gen-id';
 | 
			
		||||
import { unique } from '../../../../prelude/array';
 | 
			
		||||
 | 
			
		||||
export const meta = {
 | 
			
		||||
	tags: ['app'],
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +35,9 @@ export default define(meta, async (ps, user) => {
 | 
			
		|||
	// Generate secret
 | 
			
		||||
	const secret = rndstr('a-zA-Z0-9', 32);
 | 
			
		||||
 | 
			
		||||
	// for backward compatibility
 | 
			
		||||
	const permission = unique(ps.permission.map(v => v.replace(/^(.+)(\/|-)(read|write)$/, '$3:$1')));
 | 
			
		||||
 | 
			
		||||
	// Create account
 | 
			
		||||
	const app = await Apps.save({
 | 
			
		||||
		id: genId(),
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +45,7 @@ export default define(meta, async (ps, user) => {
 | 
			
		|||
		userId: user ? user.id : null,
 | 
			
		||||
		name: ps.name,
 | 
			
		||||
		description: ps.description,
 | 
			
		||||
		permission: ps.permission,
 | 
			
		||||
		permission,
 | 
			
		||||
		callbackUrl: ps.callbackUrl,
 | 
			
		||||
		secret: secret
 | 
			
		||||
	});
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'favorites-read',
 | 
			
		||||
	kind: 'read:favorites',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		limit: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'messaging-read',
 | 
			
		||||
	kind: 'read:messaging',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		limit: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'messaging-read',
 | 
			
		||||
	kind: 'read:messaging',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		userId: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'messaging-write',
 | 
			
		||||
	kind: 'write:messaging',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		userId: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'messaging-write',
 | 
			
		||||
	kind: 'write:messaging',
 | 
			
		||||
 | 
			
		||||
	limit: {
 | 
			
		||||
		duration: ms('1hour'),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'messaging-write',
 | 
			
		||||
	kind: 'write:messaging',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		messageId: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'favorite-write',
 | 
			
		||||
	kind: 'write:favorites',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		noteId: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'favorite-write',
 | 
			
		||||
	kind: 'write:favorites',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		noteId: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,7 @@ export default define(meta, async (ps, user) => {
 | 
			
		|||
	const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
 | 
			
		||||
 | 
			
		||||
	const query = Notes.createQueryBuilder('note')
 | 
			
		||||
		.addSelect('note.score')
 | 
			
		||||
		.where('note.userHost IS NULL')
 | 
			
		||||
		.andWhere(`note.createdAt > :date`, { date: new Date(Date.now() - day) })
 | 
			
		||||
		.andWhere(`note.visibility = 'public'`)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@ export const meta = {
 | 
			
		|||
 | 
			
		||||
	requireCredential: true,
 | 
			
		||||
 | 
			
		||||
	kind: 'vote-write',
 | 
			
		||||
	kind: 'write:votes',
 | 
			
		||||
 | 
			
		||||
	params: {
 | 
			
		||||
		noteId: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								src/server/api/kinds.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/server/api/kinds.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
export const kinds = [
 | 
			
		||||
	'read:account',
 | 
			
		||||
	'write:account',
 | 
			
		||||
	'read:blocks',
 | 
			
		||||
	'write:blocks',
 | 
			
		||||
	'read:drive',
 | 
			
		||||
	'write:drive',
 | 
			
		||||
	'read:favorites',
 | 
			
		||||
	'write:favorites',
 | 
			
		||||
	'read:following',
 | 
			
		||||
	'write:following',
 | 
			
		||||
	'read:messaging',
 | 
			
		||||
	'write:messaging',
 | 
			
		||||
	'read:mutes',
 | 
			
		||||
	'write:mutes',
 | 
			
		||||
	'write:notes',
 | 
			
		||||
	'read:notifications',
 | 
			
		||||
	'write:notifications',
 | 
			
		||||
	'read:reactions',
 | 
			
		||||
	'write:reactions',
 | 
			
		||||
	'write:votes'
 | 
			
		||||
];
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +1,49 @@
 | 
			
		|||
import config from '../../../config';
 | 
			
		||||
import endpoints from '../endpoints';
 | 
			
		||||
import * as locale from '../../../../locales/';
 | 
			
		||||
import { fromEntries } from '../../../prelude/array';
 | 
			
		||||
import { kinds as kindsList } from '../kinds';
 | 
			
		||||
 | 
			
		||||
export interface IKindInfo {
 | 
			
		||||
	endpoints: string[];
 | 
			
		||||
	descs: { [x: string]: string; };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function kinds() {
 | 
			
		||||
	const kinds = fromEntries(
 | 
			
		||||
		kindsList
 | 
			
		||||
			.map(k => [k, {
 | 
			
		||||
					endpoints: [],
 | 
			
		||||
					descs: fromEntries(
 | 
			
		||||
						Object.keys(locale)
 | 
			
		||||
							.map(l => [l, locale[l].common.permissions[k] as string] as [string, string])
 | 
			
		||||
						) as { [x: string]: string; }
 | 
			
		||||
				}] as [ string, IKindInfo ])
 | 
			
		||||
			) as { [x: string]: IKindInfo; };
 | 
			
		||||
 | 
			
		||||
	const errors = [] as string[][];
 | 
			
		||||
 | 
			
		||||
	for (const endpoint of endpoints.filter(ep => !ep.meta.secure)) {
 | 
			
		||||
		if (endpoint.meta.kind) {
 | 
			
		||||
			const kind = endpoint.meta.kind;
 | 
			
		||||
			if (kind in kinds) kinds[kind].endpoints.push(endpoint.name);
 | 
			
		||||
			else errors.push([kind, endpoint.name]);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (errors.length > 0) throw Error('\n  ' + errors.map((e) => `Unknown kind (permission) "${e[0]}" found at ${e[1]}.`).join('\n  '));
 | 
			
		||||
 | 
			
		||||
	return kinds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getDescription(lang = 'ja-JP'): string {
 | 
			
		||||
	const permissionTable = (Object.entries(kinds()) as [string, IKindInfo][])
 | 
			
		||||
		.map(e => `|${e[0]}|${e[1].descs[lang]}|${e[1].endpoints.map(f => `[${f}](#operation/${f})`).join(', ')}|`)
 | 
			
		||||
		.join('\n');
 | 
			
		||||
 | 
			
		||||
	const descriptions = {
 | 
			
		||||
		'ja-JP': `**Misskey is a decentralized microblogging platform.**
 | 
			
		||||
 | 
			
		||||
export const description = `
 | 
			
		||||
## Usage
 | 
			
		||||
**APIはすべてPOSTでリクエスト/レスポンスともにJSON形式です。**
 | 
			
		||||
一部のAPIはリクエストに認証情報(APIキー)が必要です。リクエストの際に\`i\`というパラメータでAPIキーを添付してください。
 | 
			
		||||
| 
						 | 
				
			
			@ -44,4 +87,12 @@ APIキーの生成方法を擬似コードで表すと次のようになりま
 | 
			
		|||
\`\`\` js
 | 
			
		||||
const i = sha256(userToken + secretKey);
 | 
			
		||||
\`\`\`
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
## Permissions
 | 
			
		||||
|Permisson (kind)|Description|Endpoints|
 | 
			
		||||
|:--|:--|:--|
 | 
			
		||||
${permissionTable}
 | 
			
		||||
`
 | 
			
		||||
	} as { [x: string]: string };
 | 
			
		||||
	return lang in descriptions ? descriptions[lang] : descriptions['ja-JP'];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ import { Context } from 'cafy';
 | 
			
		|||
import config from '../../../config';
 | 
			
		||||
import { errors as basicErrors } from './errors';
 | 
			
		||||
import { schemas } from './schemas';
 | 
			
		||||
import { description } from './description';
 | 
			
		||||
import { getDescription } from './description';
 | 
			
		||||
import { convertOpenApiSchema } from '../../../misc/schema';
 | 
			
		||||
 | 
			
		||||
export function genOpenapiSpec(lang = 'ja-JP') {
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +13,7 @@ export function genOpenapiSpec(lang = 'ja-JP') {
 | 
			
		|||
		info: {
 | 
			
		||||
			version: 'v1',
 | 
			
		||||
			title: 'Misskey API',
 | 
			
		||||
			description: '**Misskey is a decentralized microblogging platform.**\n\n' + description,
 | 
			
		||||
			description: getDescription(lang),
 | 
			
		||||
			'x-logo': { url: '/assets/api-doc.png' }
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +110,10 @@ export function genOpenapiSpec(lang = 'ja-JP') {
 | 
			
		|||
 | 
			
		||||
		let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : 'No description provided.') + '\n\n';
 | 
			
		||||
		desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`;
 | 
			
		||||
		if (endpoint.meta.kind) desc += ` / **Permission**: *${endpoint.meta.kind}*`;
 | 
			
		||||
		if (endpoint.meta.kind) {
 | 
			
		||||
			const kind = endpoint.meta.kind;
 | 
			
		||||
			desc += ` / **Permission**: *${kind}*`;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const info = {
 | 
			
		||||
			operationId: endpoint.name,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,15 +11,15 @@ export default (
 | 
			
		|||
	noteId: Note['id']
 | 
			
		||||
) => new Promise<any>(async (resolve, reject) => {
 | 
			
		||||
	// Remove document
 | 
			
		||||
	const res = await NoteUnreads.delete({
 | 
			
		||||
	/*const res = */await NoteUnreads.delete({
 | 
			
		||||
		userId: userId,
 | 
			
		||||
		noteId: noteId
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	// v11 TODO: https://github.com/typeorm/typeorm/issues/2415
 | 
			
		||||
	if (res.affected == 0) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	//if (res.affected == 0) {
 | 
			
		||||
	//	return;
 | 
			
		||||
	//}
 | 
			
		||||
 | 
			
		||||
	const count1 = await NoteUnreads.count({
 | 
			
		||||
		userId: userId,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue