-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugin.js
More file actions
328 lines (305 loc) · 13.8 KB
/
plugin.js
File metadata and controls
328 lines (305 loc) · 13.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
class Plugin {
constructor(workspace) {
this.workspace = workspace;
this.catName = 'オートガード';
this._ngWords = [];
this._warnData = {};
}
async onload() {
this.registerBlocks();
console.log("AutoGuard Plugin loaded!");
}
async onunload() {
this.unregisterBlocks();
console.log("AutoGuard Plugin unloaded.");
}
registerBlocks() {
if (typeof Blockly === 'undefined') return;
const addAutoGuardData = () => {
if (Blockly.Python) {
if (!Blockly.Python.definitions_) Blockly.Python.definitions_ = {};
Blockly.Python.definitions_['import_ag_init'] = [
'import json, os',
'def save_ag_data():',
' try:',
' with open("autoguard_data.json", "w", encoding="utf-8") as f:',
' json.dump({"warn": bot._warn_data, "ng": bot._ng_words}, f, ensure_ascii=False, indent=4)',
' except Exception as e:',
' print(f"[AutoGuard ERROR] Failed to save data: {e}")',
'',
'if not hasattr(bot, "_warn_data"):',
' if os.path.exists("autoguard_data.json"):',
' try:',
' with open("autoguard_data.json", "r", encoding="utf-8") as f:',
' _loaded = json.load(f)',
' # キーが文字列になるため int に変換しつつ復元',
' bot._warn_data = {int(k): v for k, v in _loaded.get("warn", {}).items()}',
' bot._ng_words = _loaded.get("ng", [])',
' except Exception:',
' bot._warn_data = {}',
' bot._ng_words = []',
' else:',
' bot._warn_data = {}',
' bot._ng_words = []',
'_warn_data = bot._warn_data',
'_ng_words = bot._ng_words'
].join('\n');
}
};
const registerGenerator = (id, fn) => {
if (Blockly.Python) {
if (Blockly.Python.forBlock) Blockly.Python.forBlock[id] = fn;
Blockly.Python[id] = fn;
}
};
// 1. NGワード検出
Blockly.Blocks['ag_contains_ng_word'] = {
init: function () {
this.appendValueInput("TEXT").setCheck("String").appendField("📝 テキスト");
this.appendValueInput("NG_LIST").setCheck("Array").appendField("に NGワードリスト");
this.appendDummyInput().appendField("が含まれているか");
this.setOutput(true, "Boolean");
this.setColour(0);
this.setTooltip("テキストにNGワードリストの単語が含まれていればTrueを返します。");
}
};
registerGenerator('ag_contains_ng_word', (block) => {
addAutoGuardData();
const text = Blockly.Python.valueToCode(block, 'TEXT', 0) || '""';
const ngList = Blockly.Python.valueToCode(block, 'NG_LIST', 0) || '[]';
return [`any(w in ${text} for w in ${ngList})`, 0];
});
// 2. 招待リンク検出
Blockly.Blocks['ag_detect_invite'] = {
init: function () {
this.appendValueInput("TEXT").setCheck("String").appendField("🔗 テキスト");
this.appendDummyInput().appendField("に招待リンクが含まれているか");
this.setOutput(true, "Boolean");
this.setColour(0);
this.setTooltip("テキストにdiscord.gg/の招待リンクが含まれていればTrueを返します。");
}
};
registerGenerator('ag_detect_invite', (block) => {
addAutoGuardData();
if (Blockly.Python) Blockly.Python.definitions_['import_re'] = 'import re';
const text = Blockly.Python.valueToCode(block, 'TEXT', 0) || '""';
return [`bool(re.search(r"discord\\.gg/\\S+", ${text}))`, 0];
});
// 3. メッセージ削除
Blockly.Blocks['ag_delete_message'] = {
init: function () {
this.appendValueInput("MESSAGE").setCheck(null).appendField("🗑️ メッセージ");
this.appendDummyInput().appendField("を削除する");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(0);
this.setTooltip("指定したメッセージを削除します。");
}
};
registerGenerator('ag_delete_message', (block) => {
addAutoGuardData();
const msg = Blockly.Python.valueToCode(block, 'MESSAGE', 0) || 'None';
return `
if ${msg}:
await ${msg}.delete()
`;
});
const idValidator = function (newValue) {
return newValue.replace(/[^0-9]/g, '');
};
// 4. 警告数取得
Blockly.Blocks['ag_get_warn_count'] = {
init: function () {
this.appendDummyInput()
.appendField("⚠️ ユーザーID")
.appendField(new Blockly.FieldTextInput("0", idValidator), "USER_ID")
.appendField("の警告数を取得する");
this.setOutput(true, "Number");
this.setColour(0);
this.setTooltip("指定したユーザーの警告数を返します。");
}
};
registerGenerator('ag_get_warn_count', (block) => {
addAutoGuardData();
const userId = block.getFieldValue('USER_ID');
return [`_warn_data.get(int(${userId}), 0)`, 0];
});
// 5. 警告セット
Blockly.Blocks['ag_set_warn'] = {
init: function () {
this.appendDummyInput()
.appendField("⚠️ ユーザーID")
.appendField(new Blockly.FieldTextInput("0", idValidator), "USER_ID")
.appendField("の警告を")
.appendField(new Blockly.FieldNumber(0, 0), "COUNT")
.appendField("にセットする")
.appendField(new Blockly.FieldDropdown([["通知あり", "NOTIFY"], ["通知なし", "SILENT"]]), "NOTIFY");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(0);
this.setTooltip("指定したユーザーの警告数を直接セットします。通知ありの場合はDMで通知します。");
}
};
registerGenerator('ag_set_warn', (block) => {
addAutoGuardData();
const userId = block.getFieldValue('USER_ID');
const count = block.getFieldValue('COUNT');
const notify = block.getFieldValue('NOTIFY');
const notifyCode = notify === 'NOTIFY' ? `
_warn_user = guild.get_member(int(${userId}))
if _warn_user:
try:
await _warn_user.send(f"⚠️ あなたの警告数が {int(${count})} 回になりました。")
except:
pass` : '';
return `
_warn_data[int(${userId})] = int(${count})${notifyCode}
save_ag_data()
`;
});
// 6. 警告リセット
Blockly.Blocks['ag_reset_warn'] = {
init: function () {
this.appendDummyInput()
.appendField("🔄 ユーザーID")
.appendField(new Blockly.FieldTextInput("0", idValidator), "USER_ID")
.appendField("の警告をリセットする");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(0);
this.setTooltip("指定したユーザーの警告数を0にリセットします。");
}
};
registerGenerator('ag_reset_warn', (block) => {
addAutoGuardData();
const userId = block.getFieldValue('USER_ID');
return `_warn_data[int(${userId})] = 0\nsave_ag_data()\n`;
});
// 7. N回以上違反ユーザー取得
Blockly.Blocks['ag_get_users_warn_gte'] = {
init: function () {
this.appendDummyInput()
.appendField("📋")
.appendField(new Blockly.FieldNumber(1, 0), "COUNT")
.appendField("回以上違反したユーザーを取得する");
this.setOutput(true, "Array");
this.setColour(0);
this.setTooltip("指定した回数以上警告を受けたユーザーIDのリストを返します。");
}
};
registerGenerator('ag_get_users_warn_gte', (block) => {
addAutoGuardData();
const count = block.getFieldValue('COUNT');
return [`[uid for uid, c in _warn_data.items() if c >= int(${count})]`, 0];
});
// 8. N回違反ユーザー取得
Blockly.Blocks['ag_get_users_warn_eq'] = {
init: function () {
this.appendDummyInput()
.appendField("📋")
.appendField(new Blockly.FieldNumber(1, 0), "COUNT")
.appendField("回違反したユーザーを取得する");
this.setOutput(true, "Array");
this.setColour(0);
this.setTooltip("指定した回数ちょうど警告を受けたユーザーIDのリストを返します。");
}
};
registerGenerator('ag_get_users_warn_eq', (block) => {
addAutoGuardData();
const count = block.getFieldValue('COUNT');
return [`[uid for uid, c in _warn_data.items() if c == int(${count})]`, 0];
});
// 9. NGワードリストを取得
Blockly.Blocks['ag_get_ng_list'] = {
init: function () {
this.appendDummyInput().appendField("📋 NGワードリストを取得する");
this.setOutput(true, "Array");
this.setColour(0);
this.setTooltip("現在のNGワードリストを取得します。");
}
};
registerGenerator('ag_get_ng_list', () => {
addAutoGuardData();
return [`_ng_words[:]`, 0];
});
// 10. NGワードリストに追加
Blockly.Blocks['ag_add_ng_word'] = {
init: function () {
this.appendValueInput("WORD").setCheck("String").appendField("➕ NGワードリストに");
this.appendDummyInput().appendField("を追加する");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(0);
this.setTooltip("NGワードリストにワードを追加します。");
}
};
registerGenerator('ag_add_ng_word', (block) => {
addAutoGuardData();
const word = Blockly.Python.valueToCode(block, 'WORD', 0) || '""';
return `_ng_words.append(${word})\nsave_ag_data()\n`;
});
// 11. NGワードリストから削除
Blockly.Blocks['ag_remove_ng_word'] = {
init: function () {
this.appendValueInput("WORD").setCheck("String").appendField("➖ NGワードリストから");
this.appendDummyInput().appendField("を削除する");
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(0);
this.setTooltip("NGワードリストからワードを削除します。存在しない場合はコンソールにERRORを出力します。");
}
};
registerGenerator('ag_remove_ng_word', (block) => {
addAutoGuardData();
const word = Blockly.Python.valueToCode(block, 'WORD', 0) || '""';
return `
try:
_ng_words.remove(${word})
save_ag_data()
except ValueError:
print(f"[AutoGuard ERROR] NGワード '{${word}}' はリストに存在しません。")
`;
});
this.updateToolbox();
}
updateToolbox() {
const toolbox = document.getElementById('toolbox');
if (!toolbox) return;
let category = toolbox.querySelector(`category[name="${this.catName}"]`);
if (!category) {
category = document.createElement('category');
category.setAttribute('name', this.catName);
category.setAttribute('data-icon', '🛡️');
category.setAttribute('colour', '#F44336');
toolbox.appendChild(category);
}
category.innerHTML = `
<block type="ag_contains_ng_word"></block>
<block type="ag_detect_invite"></block>
<block type="ag_delete_message"></block>
<block type="ag_get_warn_count"></block>
<block type="ag_set_warn"></block>
<block type="ag_reset_warn"></block>
<block type="ag_get_users_warn_gte"></block>
<block type="ag_get_users_warn_eq"></block>
<block type="ag_get_ng_list"></block>
<block type="ag_add_ng_word"></block>
<block type="ag_remove_ng_word"></block>
`;
if (this.workspace && this.workspace.updateToolbox) {
this.workspace.updateToolbox(toolbox);
}
}
unregisterBlocks() {
const toolbox = document.getElementById('toolbox');
if (toolbox) {
const category = toolbox.querySelector(`category[name="${this.catName}"]`);
if (category) {
category.remove();
if (this.workspace && this.workspace.updateToolbox) {
this.workspace.updateToolbox(toolbox);
}
}
}
}
}