Merge branch 'develop'
This commit is contained in:
commit
5cc1aab530
28 changed files with 184 additions and 113 deletions
|
@ -16,7 +16,7 @@
|
|||
</ol>
|
||||
<ol class="emojis" ref="suggests" v-if="emojis.length > 0">
|
||||
<li v-for="emoji in emojis" @click="complete(type, emoji.emoji)" @keydown="onKeydown" tabindex="-1">
|
||||
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-if="emoji.isCustomEmoji"><img :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-else-if="!useOsDefaultEmojis"><img :src="emoji.url" :alt="emoji.emoji"/></span>
|
||||
<span class="emoji" v-else>{{ emoji.emoji }}</span>
|
||||
<span class="name" v-html="emoji.name.replace(q, `<b>${q}</b>`)"></span>
|
||||
|
@ -31,6 +31,7 @@ import Vue from 'vue';
|
|||
import * as emojilib from 'emojilib';
|
||||
import contains from '../../../common/scripts/contains';
|
||||
import { twemojiBase } from '../../../../../misc/twemoji-base';
|
||||
import { getStaticImageUrl } from '../../../common/scripts/get-static-image-url';
|
||||
|
||||
type EmojiDef = {
|
||||
emoji: string;
|
||||
|
@ -78,6 +79,7 @@ export default Vue.extend({
|
|||
|
||||
data() {
|
||||
return {
|
||||
getStaticImageUrl,
|
||||
fetching: true,
|
||||
users: [],
|
||||
hashtags: [],
|
||||
|
|
|
@ -257,7 +257,7 @@ export default class Reversi {
|
|||
public get winner(): Color | null {
|
||||
return this.isEnded ?
|
||||
this.blackCount == this.whiteCount ? null :
|
||||
this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
|
||||
this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
|
||||
undefined as never;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ export class ASEvaluator {
|
|||
subtract: (a: number, b: number) => a - b,
|
||||
multiply: (a: number, b: number) => a * b,
|
||||
divide: (a: number, b: number) => a / b,
|
||||
remind: (a: number, b: number) => a % b,
|
||||
mod: (a: number, b: number) => a % b,
|
||||
strLen: (a: string) => a.length,
|
||||
strPick: (a: string, b: number) => a[b - 1],
|
||||
strReplace: (a: string, b: string, c: string) => a.split(b).join(c),
|
||||
|
|
|
@ -58,7 +58,7 @@ export const funcDefs: Record<string, { in: any[]; out: any; category: string; i
|
|||
subtract: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faMinus, },
|
||||
multiply: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faTimes, },
|
||||
divide: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||
remind: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||
mod: { in: ['number', 'number'], out: 'number', category: 'operation', icon: faDivide, },
|
||||
eq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faEquals, },
|
||||
notEq: { in: [0, 0], out: 'boolean', category: 'comparison', icon: faNotEqual, },
|
||||
gt: { in: ['number', 'number'], out: 'boolean', category: 'comparison', icon: faGreaterThan, },
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
export const twemojiBase = 'https://cdn.jsdelivr.net/npm/twemoji@11.3.0';
|
||||
// https://cdn.jsdelivr.net/npm/twemoji@11.3.0
|
||||
// https://cdnjs.cloudflare.com/ajax/libs/twemoji/11.3.0
|
||||
export const twemojiBase = 'https://cdn.jsdelivr.net/npm/twemoji@12.0.1';
|
||||
// https://cdn.jsdelivr.net/npm/twemoji@12.0.1
|
||||
// https://cdnjs.cloudflare.com/ajax/libs/twemoji/12.0.1
|
||||
// https://twemoji.maxcdn.com
|
||||
|
|
|
@ -8,7 +8,7 @@ export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSch
|
|||
|
||||
@EntityRepository(MessagingMessage)
|
||||
export class MessagingMessageRepository extends Repository<MessagingMessage> {
|
||||
public isValidText(text: string): boolean {
|
||||
public validateText(text: string): boolean {
|
||||
return text.trim().length <= 1000 && text.trim() != '';
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import $ from 'cafy';
|
||||
import { EntityRepository, Repository, In } from 'typeorm';
|
||||
import { User, ILocalUser, IRemoteUser } from '../entities/user';
|
||||
import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserGroupJoinings } from '..';
|
||||
|
@ -231,29 +232,13 @@ export class UserRepository extends Repository<User> {
|
|||
}
|
||||
|
||||
//#region Validators
|
||||
public validateUsername(username: string, remote = false): boolean {
|
||||
return typeof username == 'string' && (remote ? /^\w([\w-]*\w)?$/ : /^\w{1,20}$/).test(username);
|
||||
}
|
||||
|
||||
public validatePassword(password: string): boolean {
|
||||
return typeof password == 'string' && password != '';
|
||||
}
|
||||
|
||||
public isValidName(name?: string): boolean {
|
||||
return name === null || (typeof name == 'string' && name.length < 50 && name.trim() != '');
|
||||
}
|
||||
|
||||
public isValidDescription(description: string): boolean {
|
||||
return typeof description == 'string' && description.length < 500 && description.trim() != '';
|
||||
}
|
||||
|
||||
public isValidLocation(location: string): boolean {
|
||||
return typeof location == 'string' && location.length < 50 && location.trim() != '';
|
||||
}
|
||||
|
||||
public isValidBirthday(birthday: string): boolean {
|
||||
return typeof birthday == 'string' && /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.test(birthday);
|
||||
}
|
||||
public validateLocalUsername = $.str.match(/^\w{1,20}$/);
|
||||
public validateRemoteUsername = $.str.match(/^\w([\w-]*\w)?$/);
|
||||
public validatePassword = $.str.min(1);
|
||||
public validateName = $.str.min(1).max(50);
|
||||
public validateDescription = $.str.min(1).max(500);
|
||||
public validateLocation = $.str.min(1).max(50);
|
||||
public validateBirthday = $.str.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/);
|
||||
//#endregion
|
||||
}
|
||||
|
||||
|
|
|
@ -53,12 +53,14 @@ function validatePerson(x: any, uri: string) {
|
|||
return new Error('invalid person: inbox is not a string');
|
||||
}
|
||||
|
||||
if (!Users.validateUsername(x.preferredUsername, true)) {
|
||||
if (!Users.validateRemoteUsername.ok(x.preferredUsername)) {
|
||||
return new Error('invalid person: invalid username');
|
||||
}
|
||||
|
||||
if (!Users.isValidName(x.name == '' ? null : x.name)) {
|
||||
return new Error('invalid person: invalid name');
|
||||
if (x.name != null && x.name != '') {
|
||||
if (!Users.validateName.ok(x.name)) {
|
||||
return new Error('invalid person: invalid name');
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof x.id !== 'string') {
|
||||
|
|
|
@ -9,7 +9,7 @@ import config from '../../config';
|
|||
import { ILocalUser } from '../../models/entities/user';
|
||||
import { publishApLogStream } from '../../services/stream';
|
||||
import { apLogger } from './logger';
|
||||
import { UserKeypairs } from '../../models';
|
||||
import { UserKeypairs, Instances } from '../../models';
|
||||
import { fetchMeta } from '../../misc/fetch-meta';
|
||||
import { toPuny } from '../../misc/convert-host';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
@ -17,15 +17,30 @@ import { ensure } from '../../prelude/ensure';
|
|||
export const logger = apLogger.createSubLogger('deliver');
|
||||
|
||||
export default async (user: ILocalUser, url: string, object: any) => {
|
||||
logger.info(`--> ${url}`);
|
||||
|
||||
const timeout = 10 * 1000;
|
||||
|
||||
const { protocol, host, hostname, port, pathname, search } = new URL(url);
|
||||
|
||||
// ブロックしてたら中断
|
||||
const meta = await fetchMeta();
|
||||
if (meta.blockedHosts.includes(toPuny(host))) return;
|
||||
if (meta.blockedHosts.includes(toPuny(host))) {
|
||||
logger.info(`skip (blocked) ${url}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// closedなら中断
|
||||
const closedHosts = await Instances.find({
|
||||
where: {
|
||||
isMarkedAsClosed: true
|
||||
},
|
||||
cache: 60 * 1000
|
||||
});
|
||||
if (closedHosts.map(x => x.host).includes(toPuny(host))) {
|
||||
logger.info(`skip (closed) ${url}`);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info(`--> ${url}`);
|
||||
|
||||
const data = JSON.stringify(object);
|
||||
|
||||
|
|
|
@ -29,14 +29,14 @@ export const meta = {
|
|||
|
||||
params: {
|
||||
name: {
|
||||
validator: $.optional.nullable.str.pipe(Users.isValidName),
|
||||
validator: $.optional.nullable.use(Users.validateName),
|
||||
desc: {
|
||||
'ja-JP': '名前(ハンドルネームやニックネーム)'
|
||||
}
|
||||
},
|
||||
|
||||
description: {
|
||||
validator: $.optional.nullable.str.pipe(Users.isValidDescription),
|
||||
validator: $.optional.nullable.use(Users.validateDescription),
|
||||
desc: {
|
||||
'ja-JP': 'アカウントの説明や自己紹介'
|
||||
}
|
||||
|
@ -50,14 +50,14 @@ export const meta = {
|
|||
},
|
||||
|
||||
location: {
|
||||
validator: $.optional.nullable.str.pipe(Users.isValidLocation),
|
||||
validator: $.optional.nullable.use(Users.validateLocation),
|
||||
desc: {
|
||||
'ja-JP': '住んでいる地域、所在'
|
||||
}
|
||||
},
|
||||
|
||||
birthday: {
|
||||
validator: $.optional.nullable.str.pipe(Users.isValidBirthday),
|
||||
validator: $.optional.nullable.use(Users.validateBirthday),
|
||||
desc: {
|
||||
'ja-JP': '誕生日 (YYYY-MM-DD形式)'
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ export const meta = {
|
|||
},
|
||||
|
||||
text: {
|
||||
validator: $.optional.str.pipe(MessagingMessages.isValidText)
|
||||
validator: $.optional.str.pipe(MessagingMessages.validateText)
|
||||
},
|
||||
|
||||
fileId: {
|
||||
|
|
|
@ -9,7 +9,7 @@ export const meta = {
|
|||
|
||||
params: {
|
||||
username: {
|
||||
validator: $.str.pipe(Users.validateUsername)
|
||||
validator: $.use(Users.validateLocalUsername)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -66,7 +66,7 @@ export const meta = {
|
|||
};
|
||||
|
||||
export default define(meta, async (ps, me) => {
|
||||
const isUsername = Users.validateUsername(ps.query.replace('@', ''), !ps.localOnly);
|
||||
const isUsername = ps.localOnly ? Users.validateLocalUsername.ok(ps.query.replace('@', '')) : Users.validateRemoteUsername.ok(ps.query.replace('@', ''));
|
||||
|
||||
let users: User[] = [];
|
||||
|
||||
|
|
|
@ -58,13 +58,13 @@ export default async (ctx: Koa.BaseContext) => {
|
|||
}
|
||||
|
||||
// Validate username
|
||||
if (!Users.validateUsername(username)) {
|
||||
if (!Users.validateLocalUsername.ok(username)) {
|
||||
ctx.status = 400;
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate password
|
||||
if (!Users.validatePassword(password)) {
|
||||
if (!Users.validatePassword.ok(password)) {
|
||||
ctx.status = 400;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ export async function proxyMedia(ctx: Koa.BaseContext) {
|
|||
|
||||
const [type, ext] = await detectMine(path);
|
||||
|
||||
if (!type.startsWith('image/')) throw 403;
|
||||
|
||||
let image: IImage;
|
||||
|
||||
if ('static' in ctx.query && ['image/png', 'image/gif'].includes(type)) {
|
||||
|
|
|
@ -36,7 +36,7 @@ module.exports = async (ctx: Koa.BaseContext) => {
|
|||
|
||||
ctx.body = summary;
|
||||
} catch (e) {
|
||||
logger.error(`Failed to get preview of ${ctx.query.url}: ${e}`);
|
||||
logger.warn(`Failed to get preview of ${ctx.query.url}: ${e}`);
|
||||
ctx.status = 200;
|
||||
ctx.set('Cache-Control', 'max-age=86400, immutable');
|
||||
ctx.body = '{}';
|
||||
|
|
|
@ -149,18 +149,22 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
|
|||
if (generateWeb) {
|
||||
logger.info(`creating web image`);
|
||||
|
||||
if (['image/jpeg'].includes(type)) {
|
||||
webpublic = await convertToJpeg(path, 2048, 2048);
|
||||
} else if (['image/webp'].includes(type)) {
|
||||
webpublic = await convertToWebp(path, 2048, 2048);
|
||||
} else if (['image/png'].includes(type)) {
|
||||
webpublic = await convertToPng(path, 2048, 2048);
|
||||
} else if (['image/apng', 'image/vnd.mozilla.apng'].includes(type)) {
|
||||
webpublic = await convertToApng(path);
|
||||
} else if (['image/gif'].includes(type)) {
|
||||
webpublic = await convertToGif(path);
|
||||
} else {
|
||||
logger.info(`web image not created (not an image)`);
|
||||
try {
|
||||
if (['image/jpeg'].includes(type)) {
|
||||
webpublic = await convertToJpeg(path, 2048, 2048);
|
||||
} else if (['image/webp'].includes(type)) {
|
||||
webpublic = await convertToWebp(path, 2048, 2048);
|
||||
} else if (['image/png'].includes(type)) {
|
||||
webpublic = await convertToPng(path, 2048, 2048);
|
||||
} else if (['image/apng', 'image/vnd.mozilla.apng'].includes(type)) {
|
||||
webpublic = await convertToApng(path);
|
||||
} else if (['image/gif'].includes(type)) {
|
||||
webpublic = await convertToGif(path);
|
||||
} else {
|
||||
logger.info(`web image not created (not an image)`);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn(`web image not created (an error occured)`, e);
|
||||
}
|
||||
} else {
|
||||
logger.info(`web image not created (from remote)`);
|
||||
|
@ -170,18 +174,22 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
|
|||
// #region thumbnail
|
||||
let thumbnail: IImage | null = null;
|
||||
|
||||
if (['image/jpeg', 'image/webp'].includes(type)) {
|
||||
thumbnail = await convertToJpeg(path, 498, 280);
|
||||
} else if (['image/png'].includes(type)) {
|
||||
thumbnail = await convertToPng(path, 498, 280);
|
||||
} else if (['image/gif'].includes(type)) {
|
||||
thumbnail = await convertToGif(path);
|
||||
} else if (type.startsWith('video/')) {
|
||||
try {
|
||||
thumbnail = await GenerateVideoThumbnail(path);
|
||||
} catch (e) {
|
||||
logger.error(`GenerateVideoThumbnail failed: ${e}`);
|
||||
try {
|
||||
if (['image/jpeg', 'image/webp'].includes(type)) {
|
||||
thumbnail = await convertToJpeg(path, 498, 280);
|
||||
} else if (['image/png'].includes(type)) {
|
||||
thumbnail = await convertToPng(path, 498, 280);
|
||||
} else if (['image/gif'].includes(type)) {
|
||||
thumbnail = await convertToGif(path);
|
||||
} else if (type.startsWith('video/')) {
|
||||
try {
|
||||
thumbnail = await GenerateVideoThumbnail(path);
|
||||
} catch (e) {
|
||||
logger.error(`GenerateVideoThumbnail failed: ${e}`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn(`thumbnail not created (an error occured)`, e);
|
||||
}
|
||||
// #endregion thumbnail
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ export default class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
public warn(message: string, data?: Record<string, any> | null, important = false): void { // 実行を継続できるが改善すべき状況で使う
|
||||
public warn(message: string, data?: Record<string, any> | null, important = false): void { // 実行を継続できるが改善すべき状況で使う
|
||||
this.log('warning', message, data, important);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue