chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:27:50 +08:00
commit cc8f841fc5
422 changed files with 70222 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
import path from 'path';
import fs from 'fs';
import inquirer from 'inquirer';
import { promisify } from 'util';
import chalk from 'chalk';
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
import Message from '@fiora/database/mongoose/models/message';
import History from '@fiora/database/mongoose/models/history';
export async function deleteMessages() {
const shouldDeleteAllMessages = await inquirer.prompt({
type: 'confirm',
name: 'result',
message: 'Confirm to delete all messages?',
});
if (!shouldDeleteAllMessages.result) {
return;
}
await initMongoDB();
const deleteResult = await Message.deleteMany({});
console.log('Delete result:', deleteResult);
const deleteHistoryResult = await History.deleteMany({});
console.log('Delete history result:', deleteHistoryResult);
const shouldDeleteAllFiles = await inquirer.prompt({
type: 'confirm',
name: 'result',
message: 'Confirm to delete all message files(Except OSS files)?',
});
if (!shouldDeleteAllFiles.result) {
return;
}
const files = await promisify(fs.readdir)(
path.resolve(__dirname, '../../server/public/'),
);
const iamgesAndFiles = files.filter(
(filename) =>
filename.startsWith('ImageMessage_') ||
filename.startsWith('FileMessage_'),
);
const unlinkAsync = promisify(fs.unlink);
await Promise.all(
iamgesAndFiles.map((file) =>
unlinkAsync(path.resolve(__dirname, '../../server/public/', file)),
),
);
console.log('Delete files:', chalk.green(iamgesAndFiles.length.toString()));
console.log(chalk.red(iamgesAndFiles.join('\n')));
console.log(chalk.green('Successfully deleted all messages'));
}
async function run() {
await deleteMessages();
process.exit(0);
}
export default run;
@@ -0,0 +1,53 @@
/**
* Delete users created today and their related data
*/
import chalk from 'chalk';
import inquirer from 'inquirer';
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
import User from '@fiora/database/mongoose/models/user';
import { deleteUser } from './deleteUser';
export async function deleteTodayRegisteredUsers() {
await initMongoDB();
const now = new Date();
const time = new Date(
`${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} 00:00:00`,
);
const users = await User.find({
createTime: {
$gte: time,
},
});
console.log(
`There are ${chalk.green(
users.length.toString(),
)} newly registered users today`,
);
if (users.length === 0) {
return;
}
const shouldDeleteUsers = await inquirer.prompt({
type: 'confirm',
name: 'result',
message: 'Confirm to delete these users?',
});
if (!shouldDeleteUsers.result) {
return;
}
await Promise.all(
users.map((user) => deleteUser(user._id.toString(), false)),
);
console.log(
chalk.green('Successfully deleted todays newly registered users'),
);
}
async function run() {
await deleteTodayRegisteredUsers();
process.exit(0);
}
export default run;
+117
View File
@@ -0,0 +1,117 @@
/* eslint-disable no-console */
import chalk from 'chalk';
import inquirer from 'inquirer';
import User from '@fiora/database/mongoose/models/user';
import Message from '@fiora/database/mongoose/models/message';
import Group, { GroupDocument } from '@fiora/database/mongoose/models/group';
import Friend from '@fiora/database/mongoose/models/friend';
import History from '@fiora/database/mongoose/models/history';
import initMongoDB, { mongoose } from '@fiora/database/mongoose/initMongoDB';
export async function deleteUser(userIdOrName: string, confirm = true) {
if (!userIdOrName) {
console.log(chalk.red('Wrong command, [userIdOrName] is missing.'));
return;
}
await initMongoDB();
try {
const user = await User.findOne(
mongoose.isValidObjectId(userIdOrName)
? { _id: userIdOrName }
: { username: userIdOrName },
);
if (user) {
console.log(
'Found user:',
chalk.blue(user._id.toString()),
chalk.green(user.username),
);
if (confirm) {
const shouldDeleteUser = await inquirer.prompt({
type: 'confirm',
name: 'result',
message: 'Confirm to delete user?',
});
if (!shouldDeleteUser.result) {
return;
}
}
const messages = await Message.find({ from: user._id });
const deleteHistoryResult = await History.deleteMany({
message: {
$in: messages.map((message) => message.id),
},
});
console.log('Delete history result:', deleteHistoryResult);
console.log(chalk.yellow('Delete messages created by this user'));
const deleteMessageResult = await Message.deleteMany({
from: user._id,
});
console.log('Delete result:', deleteMessageResult);
console.log(
chalk.yellow('Leave the group that the user has joined'),
);
const groups = await Group.find({
members: user._id,
});
// eslint-disable-next-line no-inner-declarations
async function leaveGroup(group: GroupDocument) {
if (!user) {
return;
}
console.log('Leave', group.name);
const index = group.members.indexOf(user?._id);
group.members.splice(index, 1);
if (group.creator?.toString() === user?._id.toString()) {
// @ts-ignore
group.creator = null;
}
await group.save();
}
await Promise.all(groups.map(leaveGroup));
console.log(
chalk.yellow(
'Delete the friend relationship related to this user',
),
);
const deleteFriendResult1 = await Friend.deleteMany({
from: user._id,
});
const deleteFriendResult2 = await Friend.deleteMany({
to: user._id,
});
console.log(
'Delete result:',
deleteFriendResult1,
deleteFriendResult2,
);
console.log(chalk.yellow('Delete this user'));
const deleteUserResult = await User.deleteMany({
_id: user._id,
});
console.log('Delete result:', deleteUserResult);
console.log(chalk.green('Successfully deleted user'));
} else {
console.log(chalk.red(`User [${userIdOrName}] does not exist`));
}
} catch (err) {
console.log(chalk.red('Failed to delete user!', err.message));
}
}
async function run() {
const userIdOrName = process.argv[3];
await deleteUser(userIdOrName);
process.exit(0);
}
export default run;
+57
View File
@@ -0,0 +1,57 @@
import chalk from 'chalk';
import cp from 'child_process';
import fs from 'fs';
import path from 'path';
import detect from 'detect-port';
import server from '@fiora/config/server';
import initRedis from '@fiora/database/redis/initRedis';
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
export async function doctor() {
console.log(chalk.yellow('===== Run Fiora Doctor ====='));
const nodeVersion = cp.execSync('node --version').toString();
console.log(
chalk.green(`node ${nodeVersion.slice(0, nodeVersion.length - 1)}`),
);
await initMongoDB();
console.log(chalk.green('MongoDB is OK'));
await (async () =>
new Promise((resolve) => {
const redis = initRedis();
redis.on('connect', resolve);
}))();
console.log(chalk.green('Redis is OK'));
const avaliablePort = await detect(server.port);
if (avaliablePort === server.port) {
console.log(chalk.green(`Port [${server.port}] is OK`));
} else {
console.log(chalk.red(`Port [${server.port}] was occupied`));
}
const indexFilePath = path.resolve(
__dirname,
'../../server/public/index.html',
);
const indexFile = fs.readFileSync(indexFilePath);
if (!indexFile) {
console.log(chalk.red('Homepage not exists'));
} else if (indexFile.toString().includes('默认首页')) {
console.log(
chalk.red(
'Homepage is default. Please build web client by [yarn build:web]',
),
);
} else {
console.log(chalk.green(`Homepage is OK`));
}
}
async function run() {
await doctor();
process.exit(0);
}
export default run;
+50
View File
@@ -0,0 +1,50 @@
import chalk from 'chalk';
import inquirer from 'inquirer';
import User from '@fiora/database/mongoose/models/user';
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
export async function fixUsersAvatar(
searchValue: string,
replaceValue: string,
) {
searchValue = searchValue || 'fioraavatar';
replaceValue = replaceValue || 'fiora/avatar';
await initMongoDB();
const users = await User.find({ avatar: { $regex: 'fioraavatar' } });
if (users.length) {
console.log(chalk.red('Oh No!'), "Some user's avatar is wrong");
users.forEach((user) => {
console.log(user._id, user.username, user.avatar);
});
const shouldFix = await inquirer.prompt({
type: 'confirm',
name: 'result',
message: 'Confirm to fix?',
});
if (shouldFix.result) {
await Promise.all(
users.map((user) => {
user.avatar = user.avatar.replace(
searchValue,
replaceValue,
);
return user.save();
}),
);
console.log(chalk.green('Congratulations! Fixed!'));
}
} else {
console.log(chalk.green('OK!'), "All user's avatar is corrent");
}
}
async function run() {
const searchValue = process.argv[3];
const replaceValue = process.argv[4];
await fixUsersAvatar(searchValue, replaceValue);
process.exit(0);
}
export default run;
+29
View File
@@ -0,0 +1,29 @@
import chalk from 'chalk';
import User from '@fiora/database/mongoose/models/user';
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
export async function getUserId(username: string) {
if (!username) {
console.log(chalk.red('Wrong command, [username] is missing.'));
return;
}
await initMongoDB();
const user = await User.findOne({ username });
if (!user) {
console.log(chalk.red(`User [${username}] does not exist`));
} else {
console.log(
`The userId of [${username}] is:`,
chalk.green(user._id.toString()),
);
}
}
async function run() {
const username = process.argv[3];
await getUserId(username);
process.exit(0);
}
export default run;
+80
View File
@@ -0,0 +1,80 @@
/**
* Register
*/
import bcrypt from 'bcryptjs';
import chalk from 'chalk';
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
import User, { UserDocument } from '../../database/mongoose/models/user';
import Group from '../../database/mongoose/models/group';
import { SALT_ROUNDS } from '../../utils/const';
import getRandomAvatar from '../../utils/getRandomAvatar';
export async function register(username: string, password: string) {
if (!username) {
console.log(chalk.red('Wrong command, [username] is missing.'));
return;
}
if (!password) {
console.log(chalk.red('Wrong command, [password] is missing.'));
return;
}
await initMongoDB();
const user = await User.findOne({ username });
if (user) {
console.log(chalk.red('The username already exists'));
return;
}
const defaultGroup = await Group.findOne({ isDefault: true });
if (!defaultGroup) {
console.log(chalk.red('Default group does not exist'));
return;
}
const salt = await bcrypt.genSalt(SALT_ROUNDS);
const hash = await bcrypt.hash(password, salt);
let newUser = null;
try {
newUser = await User.create({
username,
salt,
password: hash,
avatar: getRandomAvatar(),
} as UserDocument);
} catch (createError) {
if (createError.name === 'ValidationError') {
console.log(
chalk.red(
'Username contains unsupported characters or the length exceeds the limit',
),
);
return;
}
console.log(chalk.red('Error:'), createError);
return;
}
if (!defaultGroup.creator) {
defaultGroup.creator = newUser._id;
}
if (newUser) {
defaultGroup.members.push(newUser._id);
}
await defaultGroup.save();
console.log(chalk.green(`Successfully created user [${username}]`));
}
async function run() {
const username = process.argv[3];
const password = process.argv[4];
await register(username, password);
process.exit(0);
}
export default run;
@@ -0,0 +1,35 @@
import chalk from 'chalk';
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
import Group from '@fiora/database/mongoose/models/group';
export async function updateDefaultGroupName(newName: string) {
if (!newName) {
console.log(chalk.red('Wrong command, [newName] is missing.'));
return;
}
await initMongoDB();
const group = await Group.findOne({ isDefault: true });
if (!group) {
console.log(chalk.red('Default group does not exist'));
} else {
group.name = newName;
try {
await group.save();
console.log(chalk.green('Update default group name success!'));
} catch (err) {
console.log(
chalk.red('Update default group name fail!'),
err.message,
);
}
}
}
async function run() {
const newName = process.argv[3];
await updateDefaultGroupName(newName);
process.exit(0);
}
export default run;