yz-yuki-plugin 1.0.2-rc.7 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -8,11 +8,13 @@ import { BiliQuery } from './bilibili.query.js';
|
|
|
8
8
|
|
|
9
9
|
class BiliTask {
|
|
10
10
|
taskName;
|
|
11
|
-
|
|
11
|
+
groupKey;
|
|
12
|
+
privateKey;
|
|
12
13
|
e;
|
|
13
14
|
constructor(e) {
|
|
14
15
|
this.taskName = "biliTask";
|
|
15
|
-
this.
|
|
16
|
+
this.groupKey = "Yz:yuki:bili:upPush:group:";
|
|
17
|
+
this.privateKey = "Yz:yuki:bili:upPush:private:";
|
|
16
18
|
}
|
|
17
19
|
async hendleEventDynamicData(uid, count = 0) {
|
|
18
20
|
const resp = await new BiliGetWebData().getBiliDynamicListDataByUid(uid);
|
|
@@ -50,6 +52,10 @@ class BiliTask {
|
|
|
50
52
|
}
|
|
51
53
|
async processBiliData(biliPushData, uidMap, dynamicList, lastLiveStatus) {
|
|
52
54
|
for (let chatType in biliPushData) {
|
|
55
|
+
if (!uidMap.has(chatType)) {
|
|
56
|
+
uidMap.set(chatType, new Map());
|
|
57
|
+
}
|
|
58
|
+
const chatTypeMap = uidMap.get(chatType);
|
|
53
59
|
for (let chatId in biliPushData[chatType]) {
|
|
54
60
|
const subUpsOfChat = biliPushData[chatType][chatId] || [];
|
|
55
61
|
for (let subInfoOfup of subUpsOfChat) {
|
|
@@ -75,46 +81,48 @@ class BiliTask {
|
|
|
75
81
|
logger.error(`获取 ${subInfoOfup.uid} 动态失败,resp 为空`);
|
|
76
82
|
return;
|
|
77
83
|
}
|
|
78
|
-
const chatIds = Array.from(new Set([...Object((
|
|
84
|
+
const chatIds = Array.from(new Set([...Object((chatTypeMap.get(subInfoOfup.uid) && chatTypeMap.get(subInfoOfup.uid).chatIds) || []), chatId]));
|
|
79
85
|
const bot_id = subInfoOfup.bot_id || [];
|
|
80
86
|
const { name, type } = subInfoOfup;
|
|
81
|
-
|
|
87
|
+
chatTypeMap.set(subInfoOfup.uid, { chatIds, bot_id, upName: name, type });
|
|
82
88
|
await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * (8000 - 2000 + 1) + 2000)));
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
async pushDynamicMessages(uidMap, dynamicList, now, interval, biliConfigData) {
|
|
88
|
-
for (let [
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
let
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
94
|
+
for (let [chatType, chatTypeMap] of uidMap) {
|
|
95
|
+
for (let [key, value] of chatTypeMap) {
|
|
96
|
+
const tempDynamicList = dynamicList[key] || [];
|
|
97
|
+
const willPushDynamicList = [];
|
|
98
|
+
const printedList = new Set();
|
|
99
|
+
for (let dynamicItem of tempDynamicList) {
|
|
100
|
+
let author = dynamicItem?.modules?.module_author || {};
|
|
101
|
+
if (!printedList.has(author?.mid)) {
|
|
102
|
+
logger.info(`正在检测B站动态 [ ${author?.name} : ${author?.mid} ]`);
|
|
103
|
+
printedList.add(author?.mid);
|
|
104
|
+
}
|
|
105
|
+
if (!author?.pub_ts)
|
|
106
|
+
continue;
|
|
107
|
+
if (Number(now - author.pub_ts) > interval) {
|
|
108
|
+
logger.debug(`超过间隔,跳过 [ ${author?.name} : ${author?.mid} ] ${author?.pub_time} 的动态`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (dynamicItem.type === "DYNAMIC_TYPE_FORWARD" && !biliConfigData.pushTransmit)
|
|
112
|
+
continue;
|
|
113
|
+
willPushDynamicList.push(dynamicItem);
|
|
103
114
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
continue;
|
|
116
|
-
await this.sendDynamic(chatId, bot_id, upName, pushDynamicData, biliConfigData, chatType);
|
|
117
|
-
await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * (6500 - 2000 + 1) + 2000)));
|
|
115
|
+
printedList.clear();
|
|
116
|
+
const pushMapInfo = value || {};
|
|
117
|
+
const { chatIds, bot_id, upName, type } = pushMapInfo;
|
|
118
|
+
for (let pushDynamicData of willPushDynamicList) {
|
|
119
|
+
if (chatIds && chatIds.length) {
|
|
120
|
+
for (let chatId of chatIds) {
|
|
121
|
+
if (type && type.length && !type.includes(pushDynamicData.type))
|
|
122
|
+
continue;
|
|
123
|
+
await this.sendDynamic(chatId, bot_id, upName, pushDynamicData, biliConfigData, chatType);
|
|
124
|
+
await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * (6500 - 2000 + 1) + 2000)));
|
|
125
|
+
}
|
|
118
126
|
}
|
|
119
127
|
}
|
|
120
128
|
}
|
|
@@ -122,7 +130,15 @@ class BiliTask {
|
|
|
122
130
|
}
|
|
123
131
|
async sendDynamic(chatId, bot_id, upName, pushDynamicData, biliConfigData, chatType) {
|
|
124
132
|
const id_str = pushDynamicData.id_str;
|
|
125
|
-
let sended
|
|
133
|
+
let sended, markKey;
|
|
134
|
+
if (chatType === "group") {
|
|
135
|
+
markKey = this.groupKey;
|
|
136
|
+
sended = await Redis.get(`${markKey}${chatId}:${id_str}`);
|
|
137
|
+
}
|
|
138
|
+
else if (chatType === "private") {
|
|
139
|
+
markKey = this.privateKey;
|
|
140
|
+
sended = await Redis.get(`${markKey}${chatId}:${id_str}`);
|
|
141
|
+
}
|
|
126
142
|
if (sended)
|
|
127
143
|
return;
|
|
128
144
|
if (!!biliConfigData.pushMsgMode) {
|
|
@@ -152,7 +168,7 @@ class BiliTask {
|
|
|
152
168
|
let imgs = await this.renderDynamicCard(uid, renderData, ScreenshotOptionsData);
|
|
153
169
|
if (!imgs)
|
|
154
170
|
return;
|
|
155
|
-
Redis.set(`${
|
|
171
|
+
Redis.set(`${markKey}${chatId}:${id_str}`, "1", { EX: 3600 * 10 });
|
|
156
172
|
(logger ?? Bot.logger)?.mark("优纪插件:B站动态执行推送");
|
|
157
173
|
for (let i = 0; i < imgs.length; i++) {
|
|
158
174
|
const image = imgs[i];
|
|
@@ -163,7 +179,7 @@ class BiliTask {
|
|
|
163
179
|
}
|
|
164
180
|
else {
|
|
165
181
|
const dynamicMsg = await BiliQuery.formatTextDynamicData(upName, pushDynamicData, false, biliConfigData);
|
|
166
|
-
Redis.set(`${
|
|
182
|
+
Redis.set(`${markKey}${chatId}:${id_str}`, "1", { EX: 3600 * 10 });
|
|
167
183
|
if (dynamicMsg == "continue") {
|
|
168
184
|
return "return";
|
|
169
185
|
}
|
|
@@ -247,7 +263,7 @@ class BiliTask {
|
|
|
247
263
|
});
|
|
248
264
|
}
|
|
249
265
|
else if (chatType === "private") {
|
|
250
|
-
await (Bot[bot_id] ?? Bot)?.
|
|
266
|
+
await (Bot[bot_id] ?? Bot)?.pickFriend(String(chatId)).sendMsg(message)
|
|
251
267
|
.catch((error) => {
|
|
252
268
|
(logger ?? Bot.logger)?.error(`用户[${chatId}]推送失败:${JSON.stringify(error)}`);
|
|
253
269
|
});
|
|
@@ -7,11 +7,13 @@ import { WeiboQuery } from './weibo.query.js';
|
|
|
7
7
|
|
|
8
8
|
class WeiboTask {
|
|
9
9
|
taskName;
|
|
10
|
-
|
|
10
|
+
groupKey;
|
|
11
|
+
privateKey;
|
|
11
12
|
e;
|
|
12
13
|
constructor(e) {
|
|
13
14
|
this.taskName = "weiboTask";
|
|
14
|
-
this.
|
|
15
|
+
this.groupKey = "Yz:yuki:weibo:upPush:group:";
|
|
16
|
+
this.privateKey = "Yz:yuki:weibo:upPush:private:";
|
|
15
17
|
}
|
|
16
18
|
async runTask() {
|
|
17
19
|
let weiboConfigData = await Config.getUserConfig("weibo", "config");
|
|
@@ -25,6 +27,10 @@ class WeiboTask {
|
|
|
25
27
|
}
|
|
26
28
|
async processWeiboData(weiboPushData, uidMap, dynamicList) {
|
|
27
29
|
for (let chatType in weiboPushData) {
|
|
30
|
+
if (!uidMap.has(chatType)) {
|
|
31
|
+
uidMap.set(chatType, new Map());
|
|
32
|
+
}
|
|
33
|
+
const chatTypeMap = uidMap.get(chatType);
|
|
28
34
|
for (let chatId in weiboPushData[chatType]) {
|
|
29
35
|
const subUpsOfChat = weiboPushData[chatType][chatId] || [];
|
|
30
36
|
for (let subInfoOfup of subUpsOfChat) {
|
|
@@ -33,47 +39,49 @@ class WeiboTask {
|
|
|
33
39
|
const dynamicData = resp || [];
|
|
34
40
|
dynamicList[subInfoOfup.uid] = dynamicData;
|
|
35
41
|
}
|
|
36
|
-
const chatIds = Array.from(new Set([...Object((
|
|
42
|
+
const chatIds = Array.from(new Set([...Object((chatTypeMap.get(subInfoOfup.uid) && chatTypeMap.get(subInfoOfup.uid).chatIds) || []), chatId]));
|
|
37
43
|
const bot_id = subInfoOfup.bot_id || [];
|
|
38
44
|
const { name, type } = subInfoOfup;
|
|
39
|
-
|
|
45
|
+
chatTypeMap.set(subInfoOfup.uid, { chatIds, bot_id, upName: name, type });
|
|
40
46
|
await this.randomDelay(1000, 4000);
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
51
|
async pushDynamicMessages(uidMap, dynamicList, now, interval, weiboConfigData) {
|
|
46
|
-
for (let [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
let
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
for (let [chatType, chatTypeMap] of uidMap) {
|
|
53
|
+
for (let [key, value] of chatTypeMap) {
|
|
54
|
+
const tempDynamicList = dynamicList[key] || [];
|
|
55
|
+
const willPushDynamicList = [];
|
|
56
|
+
const printedList = new Set();
|
|
57
|
+
for (let dynamicItem of tempDynamicList) {
|
|
58
|
+
let raw_post = dynamicItem || {};
|
|
59
|
+
let user = raw_post?.mblog?.user || {};
|
|
60
|
+
if (!printedList.has(user?.id)) {
|
|
61
|
+
logger.info(`正在检测微博动态 [ ${user?.screen_name} : ${user?.id} ]`);
|
|
62
|
+
printedList.add(user?.id);
|
|
63
|
+
}
|
|
64
|
+
if (!raw_post?.mblog?.created_at)
|
|
65
|
+
continue;
|
|
66
|
+
if (Number(now - (WeiboQuery.getDynamicCreatetDate(raw_post) / 1000)) > interval) {
|
|
67
|
+
logger.debug(`超过间隔,跳过 [ ${user?.screen_name} : ${user?.id} ] ${raw_post?.mblog?.created_at} 的动态`);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (dynamicItem.type === "DYNAMIC_TYPE_FORWARD" && !weiboConfigData.pushTransmit)
|
|
71
|
+
continue;
|
|
72
|
+
willPushDynamicList.push(dynamicItem);
|
|
62
73
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
continue;
|
|
75
|
-
await this.sendDynamic(chatId, bot_id, upName, pushDynamicData, weiboConfigData, chatType);
|
|
76
|
-
await this.randomDelay(2000, 10500);
|
|
74
|
+
printedList.clear();
|
|
75
|
+
const pushMapInfo = value || {};
|
|
76
|
+
const { chatIds, bot_id, upName, type } = pushMapInfo;
|
|
77
|
+
for (let pushDynamicData of willPushDynamicList) {
|
|
78
|
+
if (chatIds && chatIds.length) {
|
|
79
|
+
for (let chatId of chatIds) {
|
|
80
|
+
if (type && type.length && !type.includes(pushDynamicData.type))
|
|
81
|
+
continue;
|
|
82
|
+
await this.sendDynamic(chatId, bot_id, upName, pushDynamicData, weiboConfigData, chatType);
|
|
83
|
+
await this.randomDelay(2000, 10500);
|
|
84
|
+
}
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
87
|
}
|
|
@@ -81,7 +89,15 @@ class WeiboTask {
|
|
|
81
89
|
}
|
|
82
90
|
async sendDynamic(chatId, bot_id, upName, pushDynamicData, weiboConfigData, chatType) {
|
|
83
91
|
const id_str = WeiboQuery.getDynamicId(pushDynamicData);
|
|
84
|
-
let sended
|
|
92
|
+
let sended, markKey;
|
|
93
|
+
if (chatType === "group") {
|
|
94
|
+
markKey = this.groupKey;
|
|
95
|
+
sended = await Redis.get(`${markKey}${chatId}:${id_str}`);
|
|
96
|
+
}
|
|
97
|
+
else if (chatType === "private") {
|
|
98
|
+
markKey = this.privateKey;
|
|
99
|
+
sended = await Redis.get(`${markKey}${chatId}:${id_str}`);
|
|
100
|
+
}
|
|
85
101
|
if (sended)
|
|
86
102
|
return;
|
|
87
103
|
if (!!weiboConfigData.pushMsgMode) {
|
|
@@ -111,7 +127,7 @@ class WeiboTask {
|
|
|
111
127
|
let imgs = await this.renderDynamicCard(uid, renderData, ScreenshotOptionsData);
|
|
112
128
|
if (!imgs)
|
|
113
129
|
return;
|
|
114
|
-
Redis.set(`${
|
|
130
|
+
Redis.set(`${markKey}${chatId}:${id_str}`, "1", { EX: 3600 * 10 });
|
|
115
131
|
(logger ?? Bot.logger)?.mark("优纪插件:B站动态执行推送");
|
|
116
132
|
for (let i = 0; i < imgs.length; i++) {
|
|
117
133
|
const image = imgs[i];
|
|
@@ -122,7 +138,7 @@ class WeiboTask {
|
|
|
122
138
|
}
|
|
123
139
|
else {
|
|
124
140
|
const dynamicMsg = await WeiboQuery.formatTextDynamicData(upName, pushDynamicData, false, weiboConfigData);
|
|
125
|
-
Redis.set(`${
|
|
141
|
+
Redis.set(`${markKey}${chatId}:${id_str}`, "1", { EX: 3600 * 10 });
|
|
126
142
|
if (dynamicMsg == "continue" || dynamicMsg == false) {
|
|
127
143
|
return "return";
|
|
128
144
|
}
|
|
@@ -206,7 +222,7 @@ class WeiboTask {
|
|
|
206
222
|
});
|
|
207
223
|
}
|
|
208
224
|
else if (chatType === "private") {
|
|
209
|
-
await (Bot[bot_id] ?? Bot)?.
|
|
225
|
+
await (Bot[bot_id] ?? Bot)?.pickFriend(String(chatId)).sendMsg(message)
|
|
210
226
|
.catch((error) => {
|
|
211
227
|
(logger ?? Bot.logger)?.error(`用户[${chatId}]推送失败:${JSON.stringify(error)}`);
|
|
212
228
|
});
|
|
@@ -3,13 +3,14 @@ import { MainProps } from "../../components/dynamic/MainPage";
|
|
|
3
3
|
import { ScreenshotOptions } from './../../utils/puppeteer.render';
|
|
4
4
|
export declare class BiliTask {
|
|
5
5
|
taskName: string;
|
|
6
|
-
|
|
6
|
+
groupKey: string;
|
|
7
|
+
privateKey: string;
|
|
7
8
|
e?: EventType;
|
|
8
9
|
constructor(e?: EventType);
|
|
9
10
|
hendleEventDynamicData(uid: string | number, count?: number): Promise<any>;
|
|
10
11
|
runTask(): Promise<void>;
|
|
11
|
-
processBiliData(biliPushData: any, uidMap: Map<any, any
|
|
12
|
-
pushDynamicMessages(uidMap: Map<any, any
|
|
12
|
+
processBiliData(biliPushData: any, uidMap: Map<any, Map<string, any>>, dynamicList: any, lastLiveStatus: any): Promise<void>;
|
|
13
|
+
pushDynamicMessages(uidMap: Map<any, Map<string, any>>, dynamicList: any, now: number, interval: number, biliConfigData: any): Promise<void>;
|
|
13
14
|
sendDynamic(chatId: string | number, bot_id: string | number, upName: string, pushDynamicData: any, biliConfigData: any, chatType: string): Promise<string>;
|
|
14
15
|
buildRenderData(extentData: any, urlQrcodeData: string, boxGrid: boolean): MainProps;
|
|
15
16
|
renderDynamicCard(uid: string, renderData: MainProps, ScreenshotOptionsData: ScreenshotOptions): Promise<Buffer[] | null>;
|
|
@@ -3,12 +3,13 @@ import { MainProps } from "../../components/dynamic/MainPage";
|
|
|
3
3
|
import { ScreenshotOptions } from '../../utils/puppeteer.render';
|
|
4
4
|
export declare class WeiboTask {
|
|
5
5
|
taskName: string;
|
|
6
|
-
|
|
6
|
+
groupKey: string;
|
|
7
|
+
privateKey: string;
|
|
7
8
|
e?: EventType;
|
|
8
9
|
constructor(e?: any);
|
|
9
10
|
runTask(): Promise<void>;
|
|
10
|
-
processWeiboData(weiboPushData: any, uidMap: Map<any, any
|
|
11
|
-
pushDynamicMessages(uidMap: Map<any, any
|
|
11
|
+
processWeiboData(weiboPushData: any, uidMap: Map<any, Map<string, any>>, dynamicList: any): Promise<void>;
|
|
12
|
+
pushDynamicMessages(uidMap: Map<any, Map<string, any>>, dynamicList: any, now: number, interval: number, weiboConfigData: any): Promise<void>;
|
|
12
13
|
sendDynamic(chatId: string | number, bot_id: string | number, upName: string, pushDynamicData: any, weiboConfigData: any, chatType: string): Promise<string>;
|
|
13
14
|
buildRenderData(extentData: any, urlQrcodeData: string, boxGrid: boolean): MainProps;
|
|
14
15
|
renderDynamicCard(uid: string | number, renderData: MainProps, ScreenshotOptionsData: ScreenshotOptions): Promise<Buffer[] | null>;
|
package/package.json
CHANGED
package/public/output.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
/*! tailwindcss v3.4.
|
|
1
|
+
/*! tailwindcss v3.4.10 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.m-auto{margin:auto}.mb-3{margin-bottom:.75rem}.ml-7{margin-left:1.75rem}.mt-3{margin-top:.75rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-72{height:18rem}.max-h-96{max-height:24rem}.w-32{width:8rem}.w-72{width:18rem}.w-96{width:24rem}.p-1{padding:.25rem}.p-5{padding:1.25rem}.text-center{text-align:center}.text-lg{font-size:1.125rem;line-height:1.75rem}.italic{font-style:italic}.text-blue-500{--tw-text-opacity:1;color:rgb(59 130 246/var(--tw-text-opacity))}.text-red-600{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity))}
|