fix lint "no-param-reassign"
Some checks failed
ci/woodpecker/push/build Pipeline failed
ci/woodpecker/push/test Pipeline failed
ci/woodpecker/push/lint-backend Pipeline failed
ci/woodpecker/push/lint-client Pipeline failed

This commit is contained in:
Johann150 2022-08-10 16:36:54 +02:00
parent 4f9ba4b8a8
commit 7a80015225
Signed by: Johann150
GPG key ID: 9EE6577A2A06F8F1
28 changed files with 110 additions and 113 deletions

View file

@ -8,10 +8,10 @@ const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/;
const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/;
export function fromHtml(html: string, hashtagNames?: string[]): string {
const dom = parse5.parseFragment(
// some AP servers like Pixelfed use br tags as well as newlines
html = html.replace(/<br\s?\/?>\r?\n/gi, '\n');
const dom = parse5.parseFragment(html);
html.replace(/<br\s?\/?>\r?\n/gi, '\n')
);
let text = '';

View file

@ -4,8 +4,11 @@ export type Acct = {
};
export function parse(acct: string): Acct {
if (acct.startsWith('@')) acct = acct.substr(1);
const split = acct.split('@', 2);
const split = acct.split('@');
if (split[0].length == 0) {
// there was an initial at
split.shift();
}
return { username: split[0], host: split[1] || null };
}

View file

@ -2,11 +2,11 @@ import { URL } from 'node:url';
import { toASCII } from 'punycode';
import config from '@/config/index.js';
export function getFullApAccount(username: string, host: string | null) {
export function getFullApAccount(username: string, host: string | null): string {
return host ? `${username}@${toPuny(host)}` : `${username}@${toPuny(config.host)}`;
}
export function isSelfHost(host: string) {
export function isSelfHost(host: string | null): boolean {
if (host == null) return true;
return toPuny(config.host) === toPuny(host);
}

View file

@ -7,10 +7,8 @@ import * as crypto from 'node:crypto';
const TIME2000 = 946684800000;
let counter = crypto.randomBytes(2).readUInt16LE(0);
export function genId(date?: Date): string {
if (!date || (date > new Date())) date = new Date();
let t = date.getTime();
export function genId(date?: Date = new Date()): string {
let t = Math.min(date, new Date());
t -= TIME2000;
if (t < 0) t = 0;
if (isNaN(t)) throw new Error('Failed to create AID: Invalid Date');

View file

@ -54,10 +54,10 @@ export function convertLegacyReactions(reactions: Record<string, number>) {
return _reactions2;
}
export async function toDbReaction(reaction?: string | null, reacterHost?: string | null): Promise<string> {
export async function toDbReaction(reaction?: string | null, idnReacterHost?: string | null): Promise<string> {
if (reaction == null) return await getFallbackReaction();
reacterHost = toPunyNullable(reacterHost);
const reacterHost = toPunyNullable(idnReacterHost);
// 文字列タイプのリアクションを絵文字に変換
if (Object.keys(legacies).includes(reaction)) return legacies[reaction];
@ -124,8 +124,8 @@ export function decodeReaction(str: string): DecodedReaction {
};
}
export function convertLegacyReaction(reaction: string): string {
reaction = decodeReaction(reaction).reaction;
export function convertLegacyReaction(_reaction: string): string {
const reaction = decodeReaction(_reaction).reaction;
if (Object.keys(legacies).includes(reaction)) return legacies[reaction];
return reaction;
}

View file

@ -52,12 +52,10 @@ export const FollowingRepository = db.getRepository(Following).extend({
opts?: {
populateFollowee?: boolean;
populateFollower?: boolean;
}
} = {},
): Promise<Packed<'Following'>> {
const following = typeof src === 'object' ? src : await this.findOneByOrFail({ id: src });
if (opts == null) opts = {};
return await awaitAll({
id: following.id,
createdAt: following.createdAt.toISOString(),

View file

@ -65,9 +65,7 @@ export async function fetchNote(object: string | IObject): Promise<Note | null>
/**
* Noteを作成します
*/
export async function createNote(value: string | IObject, resolver?: Resolver, silent = false): Promise<Note | null> {
if (resolver == null) resolver = new Resolver();
export async function createNote(value: string | IObject, resolver?: Resolver = new Resolver(), silent = false): Promise<Note | null> {
const object: any = await resolver.resolve(value);
const entryUri = getApId(value);
@ -302,8 +300,8 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver):
}
}
export async function extractEmojis(tags: IObject | IObject[], host: string): Promise<Emoji[]> {
host = toPuny(host);
export async function extractEmojis(tags: IObject | IObject[], idnHost: string): Promise<Emoji[]> {
const host = toPuny(idnHost);
if (!tags) return [];

View file

@ -134,15 +134,13 @@ export async function fetchPerson(uri: string, resolver?: Resolver): Promise<Cac
/**
* Personを作成します
*/
export async function createPerson(uri: string, resolver?: Resolver): Promise<User> {
export async function createPerson(uri: string, resolver?: Resolver = new Resolver()): Promise<User> {
if (typeof uri !== 'string') throw new Error('uri is not string');
if (uri.startsWith(config.url)) {
throw new StatusError('cannot resolve local user', 400, 'cannot resolve local user');
}
if (resolver == null) resolver = new Resolver();
const object = await resolver.resolve(uri) as any;
const person = validateActor(object, uri);
@ -283,7 +281,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
* @param resolver Resolver
* @param hint Hint of Person object (Personの場合Remote resolveをせずに更新に利用します)
*/
export async function updatePerson(uri: string, resolver?: Resolver | null, hint?: IObject): Promise<void> {
export async function updatePerson(uri: string, resolver?: Resolver = new Resolver(), hint?: IObject): Promise<void> {
if (typeof uri !== 'string') throw new Error('uri is not string');
// URIがこのサーバーを指しているならスキップ
@ -299,8 +297,6 @@ export async function updatePerson(uri: string, resolver?: Resolver | null, hint
}
//#endregion
if (resolver == null) resolver = new Resolver();
const object = hint || await resolver.resolve(uri);
const person = validateActor(object, uri);
@ -405,8 +401,7 @@ export async function resolvePerson(uri: string, resolver?: Resolver): Promise<C
//#endregion
// リモートサーバーからフェッチしてきて登録
if (resolver == null) resolver = new Resolver();
return await createPerson(uri, resolver);
return await createPerson(uri, resolver ?? new Resolver());
}
const services: {
@ -419,10 +414,11 @@ const services: {
const $discord = (id: string, name: string) => {
if (typeof name !== 'string') {
name = 'unknown#0000';
}
return { id, username: 'unknown', discriminator: '0000' };
} else {
const [username, discriminator] = name.split('#');
return { id, username, discriminator };
}
};
function addService(target: { [x: string]: any }, source: IApPropertyValue) {

View file

@ -5,9 +5,7 @@ import Resolver from '../resolver.js';
import { IObject, IQuestion, isQuestion } from '../type.js';
import { apLogger } from '../logger.js';
export async function extractPollFromQuestion(source: string | IObject, resolver?: Resolver): Promise<IPoll> {
if (resolver == null) resolver = new Resolver();
export async function extractPollFromQuestion(source: string | IObject, resolver?: Resolver = new Resolver()): Promise<IPoll> {
const question = await resolver.resolve(source);
if (!isQuestion(question)) {

View file

@ -53,7 +53,5 @@ export const attachLdSignature = async (activity: any, user: { id: User['id']; h
const ldSignature = new LdSignature();
ldSignature.debug = false;
activity = await ldSignature.signRsaSignature2017(activity, keypair.privateKey, `${config.url}/users/${user.id}#main-key`);
return activity;
return await ldSignature.signRsaSignature2017(activity, keypair.privateKey, `${config.url}/users/${user.id}#main-key`);
};

View file

@ -2,7 +2,7 @@ import { URL } from 'node:url';
import chalk from 'chalk';
import { IsNull } from 'typeorm';
import config from '@/config/index.js';
import { toPuny } from '@/misc/convert-host.js';
import { isSelfHost, toPuny } from '@/misc/convert-host.js';
import { User, IRemoteUser } from '@/models/entities/user.js';
import { Users } from '@/models/index.js';
import webFinger from './webfinger.js';
@ -11,7 +11,7 @@ import { remoteLogger } from './logger.js';
const logger = remoteLogger.createSubLogger('resolve-user');
export async function resolveUser(username: string, host: string | null): Promise<User> {
export async function resolveUser(username: string, idnHost: string | null): Promise<User> {
const usernameLower = username.toLowerCase();
if (host == null) {
@ -25,9 +25,7 @@ export async function resolveUser(username: string, host: string | null): Promis
});
}
host = toPuny(host);
if (config.host === host) {
if (isSelfHost(idnHost)) {
logger.info(`return local user: ${usernameLower}`);
return await Users.findOneBy({ usernameLower, host: IsNull() }).then(u => {
if (u == null) {
@ -38,6 +36,8 @@ export async function resolveUser(username: string, host: string | null): Promis
});
}
// `idnHost` can not be null here because that would have branched off with `isSelfHost`.
const host = toPuny(idnHost!);
const user = await Users.findOneBy({ usernameLower, host }) as IRemoteUser | null;
const acctLower = `${usernameLower}@${host}`;

View file

@ -135,8 +135,9 @@ export async function readGroupMessagingMessage(
}
export async function deliverReadActivity(user: { id: User['id']; host: null; }, recipient: IRemoteUser, messages: MessagingMessage | MessagingMessage[]) {
messages = toArray(messages).filter(x => x.uri);
const contents = messages.map(x => renderReadActivity(user, x));
const contents = toArray(messages)
.filter(x => x.uri)
.map(x => renderReadActivity(user, x));
if (contents.length > 1) {
const collection = orderedCollection(null, contents.length, undefined, undefined, contents);

View file

@ -8,21 +8,22 @@ export class ApiError extends Error {
public httpStatusCode?: number;
public info?: any;
constructor(e?: E | null | undefined, info?: any | null | undefined) {
if (e == null) e = {
constructor(
e?: E | null | undefined = {
message: 'Internal error occurred. Please contact us if the error persists.',
code: 'INTERNAL_ERROR',
id: '5d37dbcb-891e-41ca-a3d6-e690c97775ac',
kind: 'server',
httpStatusCode: 500,
};
},
info?: any | null | undefined
) {
super(e.message);
this.message = e.message;
this.code = e.code;
this.id = e.id;
this.kind = e.kind || 'client';
this.httpStatusCode = e.httpStatusCode;
this.kind = e.kind ?? 'client';
this.httpStatusCode = e.httpStatusCode ?? 500;
this.info = info;
}
}

View file

@ -256,9 +256,12 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
/**
* Upload to ObjectStorage
*/
async function upload(key: string, stream: fs.ReadStream | Buffer, type: string, filename?: string) {
if (type === 'image/apng') type = 'image/png';
if (!FILE_TYPE_BROWSERSAFE.includes(type)) type = 'application/octet-stream';
async function upload(key: string, stream: fs.ReadStream | Buffer, _type: string, filename?: string) {
const type = (_type === 'image/apng')
? 'image/png'
: (FILE_TYPE_BROWSERSAFE.includes(_type))
? _type
: 'application/octet-stream';
const meta = await fetchMeta();

View file

@ -36,12 +36,6 @@ export async function uploadFromUrl({
name = null;
}
// If the comment is same as the name, skip comment
// (image.name is passed in when receiving attachment)
if (comment !== null && name === comment) {
comment = null;
}
// Create temp file
const [path, cleanup] = await createTemp();
@ -49,7 +43,20 @@ export async function uploadFromUrl({
// write content at URL to temp file
await downloadUrl(url, path);
const driveFile = await addFile({ user, path, name, comment, folderId, force, isLink, url, uri, sensitive });
const driveFile = await addFile({
user,
path,
name,
// If the comment is same as the name, skip comment
// (image.name is passed in when receiving attachment)
comment: name === comment ? null : comment,
folderId,
force,
isLink,
url,
uri,
sensitive,
});
logger.succ(`Got: ${driveFile.id}`);
return driveFile!;
} catch (e) {

View file

@ -47,10 +47,9 @@ export default class Logger {
return logger;
}
private log(level: Level, message: string, data?: Record<string, any> | null, important = false, subDomains: Domain[] = [], store = true): void {
private log(level: Level, message: string, data?: Record<string, any> | null, important = false, subDomains: Domain[] = [], _store = true): void {
if (envOption.quiet) return;
if (!this.store) store = false;
if (level === 'debug') store = false;
const store = _store && this.store && (level !== 'debug');
if (this.parentLogger) {
this.parentLogger.log(level, message, data, important, [this.domain].concat(subDomains), store);
@ -95,9 +94,8 @@ export default class Logger {
}
}
public error(x: string | Error, data?: Record<string, any> | null, important = false): void { // 実行を継続できない状況で使う
public error(x: string | Error, data?: Record<string, any> = {}, important = false): void { // 実行を継続できない状況で使う
if (x instanceof Error) {
data = data || {};
data.e = x;
this.log('error', x.toString(), data, important);
} else if (typeof x === 'object') {

View file

@ -33,14 +33,14 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
}
// TODO: cache
reaction = await toDbReaction(reaction, user.host);
const dbReaction = await toDbReaction(reaction, user.host);
const record: NoteReaction = {
id: genId(),
createdAt: new Date(),
noteId: note.id,
userId: user.id,
reaction,
reaction: dbReaction,
};
// Create reaction
@ -53,7 +53,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
userId: user.id,
});
if (exists.reaction !== reaction) {
if (exists.reaction !== dbReaction) {
// 別のリアクションがすでにされていたら置き換える
await deleteReaction(user, note);
await NoteReactions.insert(record);
@ -67,7 +67,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
}
// Increment reactions count
const sql = `jsonb_set("reactions", '{${reaction}}', (COALESCE("reactions"->>'${reaction}', '0')::int + 1)::text::jsonb)`;
const sql = `jsonb_set("reactions", '{${dbReaction}}', (COALESCE("reactions"->>'${dbReaction}', '0')::int + 1)::text::jsonb)`;
await Notes.createQueryBuilder().update()
.set({
reactions: () => sql,
@ -79,7 +79,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
perUserReactionsChart.update(user, note);
// カスタム絵文字リアクションだったら絵文字情報も送る
const decodedReaction = decodeReaction(reaction);
const decodedReaction = decodeReaction(dbReaction);
const emoji = await Emojis.findOne({
where: {
@ -103,7 +103,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
createNotification(note.userId, 'reaction', {
notifierId: user.id,
noteId: note.id,
reaction,
reaction: dbReaction,
});
}
@ -116,7 +116,7 @@ export default async (user: { id: User['id']; host: User['host']; }, note: Note,
createNotification(watcher.userId, 'reaction', {
notifierId: user.id,
noteId: note.id,
reaction,
reaction: dbReaction,
});
}
});

View file

@ -6,8 +6,8 @@ import { Cache } from '@/misc/cache.js';
const cache = new Cache<Instance>(1000 * 60 * 60);
export async function registerOrFetchInstanceDoc(host: string): Promise<Instance> {
host = toPuny(host);
export async function registerOrFetchInstanceDoc(idnHost: string): Promise<Instance> {
const host = toPuny(idnHost);
const cached = cache.get(host);
if (cached) return cached;

View file

@ -21,8 +21,8 @@ export async function updateUsertags(user: User, tags: string[]) {
}
}
export async function updateHashtag(user: { id: User['id']; host: User['host']; }, tag: string, isUserAttached = false, inc = true) {
tag = normalizeForSearch(tag);
export async function updateHashtag(user: { id: User['id']; host: User['host']; }, _tag: string, isUserAttached = false, inc = true) {
const tag = normalizeForSearch(_tag);
const index = await Hashtags.findOneBy({ name: tag });

View file

@ -400,18 +400,18 @@ function chooseFolder(folderToChoose: Misskey.entities.DriveFolder) {
}
}
function move(target?: Misskey.entities.DriveFolder) {
function move(target?: string | Misskey.entities.DriveFolder) {
if (!target) {
goRoot();
return;
} else if (typeof target === 'object') {
target = target.id;
}
const targetId = typeof target === 'string' ? target : target.id;
fetching.value = true;
os.api('drive/folders/show', {
folderId: target
folderId: targetId,
}).then(folderToMove => {
folder.value = folderToMove;
hierarchyFolders.value = [];

View file

@ -308,8 +308,7 @@ function paste(event: ClipboardEvent) {
}
}
function done(query?: any): boolean | void {
if (query == null) query = q.value;
function done(query?: any = q.value): boolean | void {
if (query == null || typeof query !== 'string') return;
const q2 = query.replace(/:/g, '');

View file

@ -332,14 +332,12 @@ export default defineComponent({
//
applyTransformHeight(height) {
if (height > window.innerHeight) height = window.innerHeight;
(this.$el as any).style.height = height + 'px';
(this.$el as any).style.height = Math.min(height, window.innerHeight) + 'px';
},
//
applyTransformWidth(width) {
if (width > window.innerWidth) width = window.innerWidth;
(this.$el as any).style.width = width + 'px';
(this.$el as any).style.width = Math.min(width, window.innerWidth) + 'px';
},
// Y

View file

@ -1,9 +1,8 @@
export default (v, digits = 0) => {
export default (v: null | number, digits = 0) => {
if (v == null) return '?';
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const sizes = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
if (v === 0) return '0';
const isMinus = v < 0;
if (isMinus) v = -v;
const i = Math.floor(Math.log(v) / Math.log(1024));
return (isMinus ? '-' : '') + (v / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, '') + sizes[i];
const i = Math.floor(Math.log(Math.abs(v)) / Math.log(1024));
return (v < 0 ? '-' : '') + (Math.abs(v) / Math.pow(1024, i)).toFixed(digits).replace(/\.0+$/, '') + sizes[i];
};

View file

@ -25,9 +25,7 @@ type ParsedPath = (string | {
function parsePath(path: string): ParsedPath {
const res = [] as ParsedPath;
path = path.substring(1);
for (const part of path.split('/')) {
for (const part of path.substring(1).split('/')) {
if (part.includes(':')) {
const prefix = part.substring(0, part.indexOf(':'));
const placeholder = part.substring(part.indexOf(':') + 1);
@ -81,9 +79,10 @@ export class Router extends EventEmitter<{
this.navigate(currentPath, null, true);
}
public resolve(path: string): { route: RouteDef; props: Map<string, string>; } | null {
public resolve(_path: string): { route: RouteDef; props: Map<string, string>; } | null {
let queryString: string | null = null;
let hash: string | null = null;
let path: string = _path;
if (path[0] === '/') path = path.substring(1);
if (path.includes('#')) {
hash = path.substring(path.indexOf('#') + 1);
@ -180,11 +179,11 @@ export class Router extends EventEmitter<{
}
const isSamePath = beforePath === path;
if (isSamePath && key == null) key = this.currentKey;
this.currentComponent = res.route.component;
this.currentProps = res.props;
this.currentRoute.value = res.route;
this.currentKey = this.currentRoute.value.globalCacheKey ?? key ?? Date.now().toString();
this.currentKey = this.currentRoute.value.globalCacheKey ?? key ?? (isSamePath ? this.currentKey : null) ?? Date.now().toString();
if (!initial) {
this.emit('change', {

View file

@ -209,8 +209,8 @@ function onMessage(message) {
function onRead(x) {
if (user) {
if (!Array.isArray(x)) x = [x];
for (const id of x) {
// ensure x is an array or turn it into one
for (const id of [x].flat()) {
if (pagingComponent.items.some(y => y.id === id)) {
const exist = pagingComponent.items.map(y => y.id).indexOf(id);
pagingComponent.items[exist] = {

View file

@ -1,6 +1,7 @@
export function focusPrev(el: Element | null, self = false, scroll = true) {
if (el == null) return;
if (!self) el = el.previousElementSibling;
export function focusPrev(_el: Element | null, self = false, scroll = true) {
if (_el == null) return;
const el = self ? _el : _el.previousElementSibling;
if (el) {
if (el.hasAttribute('tabindex')) {
(el as HTMLElement).focus({
@ -12,9 +13,10 @@ export function focusPrev(el: Element | null, self = false, scroll = true) {
}
}
export function focusNext(el: Element | null, self = false, scroll = true) {
if (el == null) return;
if (!self) el = el.nextElementSibling;
export function focusNext(_el: Element | null, self = false, scroll = true) {
if (_el == null) return;
const el = self ? _el : _el.nextElementSibling;
if (el) {
if (el.hasAttribute('tabindex')) {
(el as HTMLElement).focus({

View file

@ -17,7 +17,8 @@ type Action = {
allowRepeat: boolean;
};
const parseKeymap = (keymap: Keymap) => Object.entries(keymap).map(([patterns, callback]): Action => {
const parseKeymap = (keymap: Keymap) => Object.entries(keymap).map(([_patterns, callback]): Action => {
let patterns = _patterns;
const result = {
patterns: [],
callback,

View file

@ -33,7 +33,7 @@ export function uploadFile(
name?: string,
keepOriginal: boolean = defaultStore.state.keepOriginalUploading
): Promise<Misskey.entities.DriveFile> {
if (folder && typeof folder === 'object') folder = folder.id;
const folderId = typeof folder === 'string' ? folder : folder.id;
return new Promise((resolve, reject) => {
const id = Math.random().toString();
@ -73,7 +73,7 @@ export function uploadFile(
formData.append('force', 'true');
formData.append('file', resizedImage || file);
formData.append('name', ctx.name);
if (folder) formData.append('folderId', folder);
if (folderId) formData.append('folderId', folderId);
const xhr = new XMLHttpRequest();
xhr.open('POST', apiUrl + '/drive/files/create', true);