chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 压缩图片
|
||||
* @param image 要压缩的图片
|
||||
* @param mimeType mime类型
|
||||
* @param quality 质量
|
||||
*/
|
||||
export default function compressImage(
|
||||
image: HTMLImageElement,
|
||||
mimeType: string,
|
||||
quality = 1,
|
||||
): Promise<Blob | null> {
|
||||
return new Promise((resolve) => {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (ctx) {
|
||||
ctx.drawImage(image, 0, 0);
|
||||
canvas.toBlob(resolve, mimeType, quality);
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/** 封禁后提示文案 */
|
||||
export const SEAL_TEXT = '你已经被关进小黑屋中, 请反思后再试';
|
||||
|
||||
/** 封禁用户释放时间 */
|
||||
export const SEAL_USER_TIMEOUT = 1000 * 60 * 10; // 10分钟
|
||||
|
||||
/** 封禁ip释放时间 */
|
||||
export const SEAL_IP_TIMEOUT = 1000 * 60 * 60 * 6; // 6小时
|
||||
|
||||
/** 透明图 */
|
||||
export const TRANSPARENT_IMAGE =
|
||||
'data:image/png;base64,R0lGODlhFAAUAIAAAP///wAAACH5BAEAAAAALAAAAAAUABQAAAIRhI+py+0Po5y02ouz3rz7rxUAOw==';
|
||||
|
||||
/** 加密salt位数 */
|
||||
export const SALT_ROUNDS = 10;
|
||||
|
||||
export const MB = 1024 * 1024;
|
||||
|
||||
export const NAME_REGEXP = /^([0-9a-zA-Z]{1,2}|[\u4e00-\u9eff]|[\u3040-\u309Fー]|[\u30A0-\u30FF]){1,8}$/;
|
||||
@@ -0,0 +1,54 @@
|
||||
import WuZeiNiangImage from '@fiora/assets/images/wuzeiniang.gif';
|
||||
|
||||
// function convertRobot10Message(message) {
|
||||
// if (message.from._id === '5adad39555703565e7903f79') {
|
||||
// try {
|
||||
// const parseMessage = JSON.parse(message.content);
|
||||
// message.from.tag = parseMessage.source;
|
||||
// message.from.avatar = parseMessage.avatar;
|
||||
// message.from.username = parseMessage.username;
|
||||
// message.type = parseMessage.type;
|
||||
// message.content = parseMessage.content;
|
||||
// } catch (err) {
|
||||
// console.warn('解析robot10消息失败', err);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
function convertSystemMessage(message: any) {
|
||||
if (message.type === 'system') {
|
||||
message.from._id = 'system';
|
||||
message.from.originUsername = message.from.username;
|
||||
message.from.username = '乌贼娘殿下';
|
||||
message.from.avatar = WuZeiNiangImage;
|
||||
message.from.tag = 'system';
|
||||
|
||||
const content = JSON.parse(message.content);
|
||||
switch (content.command) {
|
||||
case 'roll': {
|
||||
message.content = `掷出了${content.value}点 (上限${content.top}点)`;
|
||||
break;
|
||||
}
|
||||
case 'rps': {
|
||||
message.content = `使出了 ${content.value}`;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
message.content = '不支持的指令';
|
||||
}
|
||||
}
|
||||
} else if (message.deleted) {
|
||||
message.type = 'system';
|
||||
message.from._id = 'system';
|
||||
message.from.originUsername = message.from.username;
|
||||
message.from.username = '乌贼娘殿下';
|
||||
message.from.avatar = WuZeiNiangImage;
|
||||
message.from.tag = 'system';
|
||||
message.content = `撤回了消息`;
|
||||
}
|
||||
}
|
||||
|
||||
export default function convertMessage(message: any) {
|
||||
convertSystemMessage(message);
|
||||
return message;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
export default {
|
||||
default: [
|
||||
'呵呵',
|
||||
'哈哈',
|
||||
'吐舌',
|
||||
'啊',
|
||||
'酷',
|
||||
'怒',
|
||||
'开心',
|
||||
'汗',
|
||||
'泪',
|
||||
'黑线',
|
||||
'鄙视',
|
||||
'不高兴',
|
||||
'真棒',
|
||||
'钱',
|
||||
'疑问',
|
||||
'阴险',
|
||||
'吐',
|
||||
'咦',
|
||||
'委屈',
|
||||
'花心',
|
||||
'呼',
|
||||
'笑眼',
|
||||
'冷',
|
||||
'太开心',
|
||||
'滑稽',
|
||||
'勉强',
|
||||
'狂汗',
|
||||
'乖',
|
||||
'睡觉',
|
||||
'惊哭',
|
||||
'升起',
|
||||
'惊讶',
|
||||
'喷',
|
||||
'爱心',
|
||||
'心碎',
|
||||
'玫瑰',
|
||||
'礼物',
|
||||
'星星月亮',
|
||||
'太阳',
|
||||
'音乐',
|
||||
'灯泡',
|
||||
'蛋糕',
|
||||
'彩虹',
|
||||
'钱币',
|
||||
'咖啡',
|
||||
'haha',
|
||||
'胜利',
|
||||
'大拇指',
|
||||
'弱',
|
||||
'ok',
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Combina two users id as frind id
|
||||
* The result has nothing to do with the order of the parameters
|
||||
* @param userId1 user id
|
||||
* @param userId2 user id
|
||||
*/
|
||||
export default function getFriendId(userId1: string, userId2: string) {
|
||||
if (userId1 < userId2) {
|
||||
return userId1 + userId2;
|
||||
}
|
||||
return userId2 + userId1;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
const AvatarCount = 15;
|
||||
const publicPath = process.env.PublicPath || '/';
|
||||
|
||||
/**
|
||||
* 获取随机头像
|
||||
*/
|
||||
export default function getRandomAvatar() {
|
||||
const number = Math.floor(Math.random() * AvatarCount);
|
||||
return `${publicPath}avatar/${number}.jpg`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认头像
|
||||
*/
|
||||
export function getDefaultAvatar() {
|
||||
return `${publicPath}avatar/0.jpg`;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import randomColor from 'randomcolor';
|
||||
|
||||
type ColorMode = 'dark' | 'bright' | 'light' | 'random';
|
||||
|
||||
/**
|
||||
* 获取随机颜色, 刷新页面不变
|
||||
* @param seed when passed will cause randomColor to return the same color each time
|
||||
*/
|
||||
export function getRandomColor(seed: string, luminosity: ColorMode = 'dark') {
|
||||
return randomColor({
|
||||
luminosity,
|
||||
seed,
|
||||
});
|
||||
}
|
||||
|
||||
type Cache = {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
const cache: Cache = {};
|
||||
|
||||
/**
|
||||
* 获取随机颜色, 刷新页面后重新随机
|
||||
* @param seed 随机种子
|
||||
* @param luminosity 亮度
|
||||
*/
|
||||
export function getPerRandomColor(
|
||||
seed: string,
|
||||
luminosity: ColorMode = 'dark',
|
||||
) {
|
||||
if (cache[seed]) {
|
||||
return cache[seed];
|
||||
}
|
||||
cache[seed] = randomColor({ luminosity });
|
||||
return cache[seed];
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { getLogger } from 'log4js';
|
||||
|
||||
const logger = getLogger();
|
||||
logger.level = process.env.NODE_ENV === 'development' ? 'trace' : 'info';
|
||||
|
||||
export default logger;
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "@fiora/utils",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@fiora/assets": "^1.0.0",
|
||||
"ali-oss": "^6.16.0",
|
||||
"axios": "^0.21.1",
|
||||
"log4js": "^6.3.0",
|
||||
"randomcolor": "^0.6.2",
|
||||
"socket.io": "^4.1.3",
|
||||
"xss": "^1.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/randomcolor": "^0.5.6"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export default function sleep(duration = 200) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, duration);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Socket } from 'socket.io';
|
||||
|
||||
export function getSocketIp(socket: Socket) {
|
||||
return (
|
||||
(socket.handshake.headers['x-real-ip'] as string) ||
|
||||
socket.request.connection.remoteAddress ||
|
||||
''
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import getFriendId from '../getFriendId';
|
||||
|
||||
describe('utils/getFriendId.ts', () => {
|
||||
it('should combina two users id as friend id', () => {
|
||||
const user1 = '111';
|
||||
const user2 = '222';
|
||||
expect(getFriendId(user1, user2)).toBe('111222');
|
||||
expect(getFriendId(user2, user1)).toBe('111222');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import { addParam } from '../url';
|
||||
|
||||
describe('utils/url.ts', () => {
|
||||
it('should add ?key=value into url', () => {
|
||||
const url = 'https://fiora.suisuijiang.com';
|
||||
const key = 'key';
|
||||
const value = 'value';
|
||||
const params = {
|
||||
[key]: value,
|
||||
};
|
||||
expect(addParam(url, params)).toBe(`${url}?${key}=${value}`);
|
||||
});
|
||||
|
||||
it('should add &key=value into url', () => {
|
||||
const url = 'https://fiora.suisuijiang.com?a=a';
|
||||
const key = 'key';
|
||||
const value = 'value';
|
||||
const params = {
|
||||
[key]: value,
|
||||
};
|
||||
expect(addParam(url, params)).toBe(`${url}&${key}=${value}`);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
export default {
|
||||
isToday(time1: Date, time2: Date) {
|
||||
return (
|
||||
time1.getFullYear() === time2.getFullYear() &&
|
||||
time1.getMonth() === time2.getMonth() &&
|
||||
time1.getDate() === time2.getDate()
|
||||
);
|
||||
},
|
||||
isYesterday(time1: Date, time2: Date) {
|
||||
const prevDate = new Date(time1);
|
||||
prevDate.setDate(time1.getDate() - 1);
|
||||
return (
|
||||
prevDate.getFullYear() === time2.getFullYear() &&
|
||||
prevDate.getMonth() === time2.getMonth() &&
|
||||
prevDate.getDate() === time2.getDate()
|
||||
);
|
||||
},
|
||||
getHourMinute(time: Date) {
|
||||
const hours = time.getHours();
|
||||
const minutes = time.getMinutes();
|
||||
return `${hours < 10 ? `0${hours}` : hours}:${
|
||||
minutes < 10 ? `0${minutes}` : minutes
|
||||
}`;
|
||||
},
|
||||
getMonthDate(time: Date) {
|
||||
return `${time.getMonth() + 1}/${time.getDate()}`;
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
const UA = window.navigator.userAgent;
|
||||
|
||||
export const isiOS = /iPhone/i.test(UA);
|
||||
|
||||
export const isAndroid = /android/i.test(UA);
|
||||
|
||||
export const isMobile = isiOS || isAndroid;
|
||||
@@ -0,0 +1,16 @@
|
||||
interface UrlParams {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function addParam(url: string, params: UrlParams) {
|
||||
let result = url;
|
||||
Object.keys(params).forEach((key) => {
|
||||
if (result.indexOf('?') === -1) {
|
||||
result += `?${key}=${params[key]}`;
|
||||
} else {
|
||||
result += `&${key}=${params[key]}`;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import xss from 'xss';
|
||||
|
||||
/**
|
||||
* xss防护
|
||||
* @param text 要处理的文字
|
||||
*/
|
||||
export default function processXss(text: string) {
|
||||
return xss(text);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user