From 90656a3485bf1745b88e159c57b147f78b53888e Mon Sep 17 00:00:00 2001 From: Kloping <3474006766@qq.com> Date: Mon, 30 Sep 2024 14:29:37 +0800 Subject: [PATCH] =?UTF-8?q?v3.5=20=E6=9B=B4=E6=96=B0=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E8=84=9A=E6=9C=AC=E8=A7=A3=E5=86=B3=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 +- .../gdpl2112/mirai/p1/CallApiPlugin.java | 5 +- .../mirai/p1/services/DgSerializer.java | 293 ++++++++++++++++++ .../mirai/p1/services/ScriptService.java | 217 +++++++++++++ .../script/BaseMessageScriptContext.java | 89 ++++++ .../p1/services/script/BaseScriptUtils.java | 116 +++++++ .../p1/services/script/ScriptContext.java | 148 +++++++++ .../mirai/p1/services/script/ScriptUtils.java | 102 ++++++ src/main/resources/static/index.html | 2 +- 9 files changed, 970 insertions(+), 4 deletions(-) create mode 100644 src/main/java/io/github/gdpl2112/mirai/p1/services/DgSerializer.java create mode 100644 src/main/java/io/github/gdpl2112/mirai/p1/services/ScriptService.java create mode 100644 src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseMessageScriptContext.java create mode 100644 src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseScriptUtils.java create mode 100644 src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptContext.java create mode 100644 src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptUtils.java diff --git a/build.gradle.kts b/build.gradle.kts index da50398..37007a0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "io.github.gdpl2112" -version = "3.4" +version = "3.5" repositories { maven("https://repo1.maven.org/maven2/") diff --git a/src/main/java/io/github/gdpl2112/mirai/p1/CallApiPlugin.java b/src/main/java/io/github/gdpl2112/mirai/p1/CallApiPlugin.java index 6ee8a8a..4695674 100644 --- a/src/main/java/io/github/gdpl2112/mirai/p1/CallApiPlugin.java +++ b/src/main/java/io/github/gdpl2112/mirai/p1/CallApiPlugin.java @@ -1,5 +1,6 @@ package io.github.gdpl2112.mirai.p1; +import io.github.gdpl2112.mirai.p1.services.ScriptService; import io.github.kloping.initialize.FileInitializeValue; import kotlin.coroutines.CoroutineContext; import net.mamoe.mirai.console.MiraiConsoleImplementation; @@ -15,7 +16,6 @@ import org.jetbrains.annotations.NotNull; import java.io.File; -import java.util.HashMap; /** * @author github.kloping @@ -27,7 +27,7 @@ public class CallApiPlugin extends JavaPlugin { public static Conf conf = null; public CallApiPlugin() { - super(new JvmPluginDescriptionBuilder("io.github.Kloping.mirai.p1.CallApiPlugin", "3.4") + super(new JvmPluginDescriptionBuilder("io.github.Kloping.mirai.p1.CallApiPlugin", "3.5") .info("调用自定义API插件").build()); } @@ -40,6 +40,7 @@ public void onDisable() { public void onEnable() { super.onEnable(); loadConf(); + GlobalEventChannel.INSTANCE.registerListenerHost(new ScriptService()); GlobalEventChannel.INSTANCE.registerListenerHost(new SimpleListenerHost() { @Override public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) { diff --git a/src/main/java/io/github/gdpl2112/mirai/p1/services/DgSerializer.java b/src/main/java/io/github/gdpl2112/mirai/p1/services/DgSerializer.java new file mode 100644 index 0000000..23e5fc9 --- /dev/null +++ b/src/main/java/io/github/gdpl2112/mirai/p1/services/DgSerializer.java @@ -0,0 +1,293 @@ +package io.github.gdpl2112.mirai.p1.services; + +import com.alibaba.fastjson.JSON; +import io.github.kloping.arr.ArrSerializer; +import io.github.kloping.io.ReadUtils; +import io.github.kloping.url.UrlUtils; +import net.mamoe.mirai.Bot; +import net.mamoe.mirai.contact.Contact; +import net.mamoe.mirai.contact.Friend; +import net.mamoe.mirai.contact.Group; +import net.mamoe.mirai.message.data.*; +import net.mamoe.mirai.utils.ExternalResource; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * @author github.kloping + */ +public class DgSerializer { + private static final Pattern PATTER_FACE = Pattern.compile(""); + private static final Pattern PATTER_PIC = Pattern.compile("^]+?>"); + private static final Pattern PATTER_URL = Pattern.compile("^]+>"); + private static final Pattern PATTER_AT = Pattern.compile(""); + private static final Pattern PATTER_MUSIC = Pattern.compile(""); + private static final Pattern PATTER_VOICE = Pattern.compile(""); + private static final Pattern PATTER_MIRAI_FACE = Pattern.compile("\\[mirai:face:.*?]"); + private static final Pattern PATTER_MIRAI_IMAGE = Pattern.compile("\\[mirai:image:.*?]"); + + public static final Pattern[] PATTERNS = {PATTER_FACE, PATTER_PIC, PATTER_URL, PATTER_AT, PATTER_VOICE, PATTER_MUSIC, PATTER_MIRAI_FACE, PATTER_MIRAI_IMAGE}; + + private static final String BASE64 = "base64,"; + + public static final Map MARKET_FACE_MAP = new HashMap<>(); + + public static MessageChain stringDeserializeToMessageChain(String str, Bot bot, Contact contact) { + if (str == null || str.isEmpty() || bot == null) return null; + MessageChainBuilder builder = new MessageChainBuilder(); + goToFormat(str, builder, bot, contact); + MessageChain message = builder.build(); + return message; + } + + private static List goToFormat(String sb, MessageChainBuilder builder, Bot bot, Contact contact) { + List allElements = getAllElements(sb); + for (Object o : allElements) { + String str = o.toString(); + boolean k = (str.startsWith("<") || str.startsWith("[")) && !str.matches("\\[.+]请使用最新版手机QQ体验新功能"); + if (k) { + Message msg = null; + String ss = str.replaceAll("[<>\\[\\]]", ""); + int i1 = ss.indexOf(":"); + String s1 = ss.substring(0, i1); + String s2 = ss.substring(i1 + 1); + switch (s1.toLowerCase()) { + case "pic": + msg = createImage(contact, bot, s2); + break; + case "face": + msg = new Face(Integer.parseInt(s2)); + break; + case "at": + long tid = -1L; + if (s2.contains("?")) tid = contact.getId(); + else tid = Long.parseLong(s2); + msg = new At(tid); + break; + case "voice": + case "audio": + msg = createVoiceMessageInGroup(s2, bot.getId(), contact); + break; + case "music": + msg = createMusic(bot, s2); + break; + case "marketface": + msg = MARKET_FACE_MAP.get(Integer.parseInt(s2)); + break; + case "mirai": + String type = s2.substring(0, s2.indexOf(":")); + String c0 = s2.substring(s2.indexOf(":") + 1, s2.length()); + if (type.equals("face")) + msg = new Face(Integer.parseInt(c0)); + else if (type.equals("image")) + msg = createImage(contact, bot, c0); + break; + default: + msg = new PlainText(s2); + break; + } + if (msg != null) builder.append(msg); + } else { + builder.append(str); + } + } + return allElements; + } + + public static List getAllElements(String line) { + List list = new ArrayList<>(); + List olist = new ArrayList<>(); + algorithmFill(list, line); + for (String s : list) { + int i = line.indexOf(s); + if (i > 0) { + olist.add(line.substring(0, i)); + } + olist.add(s); + line = line.substring(i + s.length()); + } + if (!line.isEmpty()) olist.add(line); + return olist; + } + + public static void algorithmFill(List list, String line) { + if (list == null || line == null || line.isEmpty()) return; + Map nm = getNearestOne(line, PATTERNS); + if (nm.isEmpty()) { + list.add(line); + return; + } + int n = nm.keySet().iterator().next(); + String v = nm.get(n); + String[] ss = new String[2]; + ss[0] = line.substring(0, line.indexOf(v)); + ss[1] = line.substring(line.indexOf(v) + v.length(), line.length()); + if (!ss[0].isEmpty()) { + list.add(ss[0]); + line = line.substring(ss[0].length()); + } + line = ss[1]; + list.add(v); + algorithmFill(list, line); + return; + } + + public static Map getNearestOne(final String line, Pattern... patterns) { + try { + Map map = new LinkedHashMap<>(); + for (Pattern pattern : patterns) { + Matcher matcher = pattern.matcher(line); + if (matcher.find()) { + String l1 = matcher.group(); + int i1 = line.indexOf(l1); + map.put(i1, l1); + } + } + Map result1 = new LinkedHashMap<>(); + map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(x -> result1.put(x.getKey(), x.getValue())); + return result1; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private static Message createMusic(Bot contact, String vals) { + String[] ss = vals.split(","); + MusicKind kind = MusicKind.valueOf(ss[0]); + MusicShare share = new MusicShare(kind, ss[1], ss[2], ss[3], ss[4], ss[5]); + return share; + } + + public static Message createImage(Contact contact, Bot bot, String path) { + Message image = null; + try { + if (path.startsWith("http")) { + image = Contact.uploadImage(bot.getAsFriend(), new ByteArrayInputStream(ReadUtils.readAll(new URL(path).openStream()))); + } else if (path.startsWith("{")) { + image = Image.fromId(path); + } else if (path.contains(BASE64)) { + image = Contact.uploadImage(bot.getAsFriend(), new ByteArrayInputStream(getBase64Data(path))); + } else if (path.startsWith("[") && path.endsWith("]")) { + image = createForwardMessageByPic(contact, bot, (String[]) JSON.parseArray(path).toArray(new String[0])); + } else { + image = Contact.uploadImage(bot.getAsFriend(), new File(path)); + } + } catch (Exception e) { + System.err.println(path + "加载失败"); + e.printStackTrace(); + } + if (image != null) return image; + else return null; + } + + public static byte[] getBase64Data(String base64) { + int i = base64.indexOf(BASE64); + String base64Str = base64.substring(i + BASE64.length()); + byte[] bytes = Base64.getDecoder().decode(base64Str); + return bytes; + } + + public static Message createVoiceMessageInGroup(String url, long id, Contact contact) { + ExternalResource resource = null; + try { + byte[] bytes = UrlUtils.getBytesFromHttpUrl(url); + resource = ExternalResource.create(bytes); + if (contact instanceof Group) { + return ((Group) contact).uploadAudio(resource); + } else if (contact instanceof Friend) { + return ((Friend) contact).uploadAudio(resource); + } else return new PlainText(url); + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + if (resource != null) { + try { + resource.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static Message createForwardMessageByPic(Contact contact, Bot bot, String[] picUrl) { + ForwardMessageBuilder builder = new ForwardMessageBuilder(contact); + for (String s : picUrl) builder.add(bot.getId(), bot.getBot().getNick(), createImage(contact, bot, s)); + return builder.build(); + } + + public static final ArrSerializer ARR_SERIALIZER = new ArrSerializer(); + + static { + ARR_SERIALIZER.add(new ArrSerializer.Rule(Image.class) { + @Override + public String serializer(Image o) { + return String.format("", o.getImageId()); + } + }); + ARR_SERIALIZER.add(new ArrSerializer.Rule(At.class) { + @Override + public String serializer(At o) { + return String.format("", o.getTarget()); + } + }); + ARR_SERIALIZER.add(new ArrSerializer.Rule(Face.class) { + @Override + public String serializer(Face o) { + return String.format("", o.getId()); + } + }); + ARR_SERIALIZER.add(new ArrSerializer.Rule(PlainText.class) { + @Override + public String serializer(PlainText o) { + String touch = o.getContent(); + String regx = "<.*?>"; + Pattern pattern = Pattern.compile(regx); + Matcher matcher = pattern.matcher(touch); + while (matcher.find()) { + touch = touch.replace(matcher.group(), "\\" + matcher.group()); + } + return touch; + } + }); + ARR_SERIALIZER.add(new ArrSerializer.Rule<Audio>(Audio.class) { + @Override + public String serializer(Audio o) { + return String.format("<audio:%s>", o.getFilename()); + } + }); + ARR_SERIALIZER.add(new ArrSerializer.Rule<MusicShare>(MusicShare.class) { + @Override + public String serializer(MusicShare o) { + return String.format("<music:%s>", o.getMusicUrl()); + } + }); + ARR_SERIALIZER.add(new ArrSerializer.Rule<MarketFace>(MarketFace.class) { + @Override + public String serializer(MarketFace o) { + MARKET_FACE_MAP.put(o.getId(), o); + return String.format("<marketface:%s>", o.getId()); + } + }); +// ARR_SERIALIZER.add(new ArrSerializer.Rule<QuoteReply>(QuoteReply.class) { +// @Override +// public String serializer(QuoteReply o) { +// return String.format("<qr:%s>", AllMessage.latest(0, o.getSource().getInternalIds())); +// } +// }); + ARR_SERIALIZER.setMode(1); + } + + public static String messageChainSerializeToString(MessageChain chain) { + return ARR_SERIALIZER.serializer(chain); + } +} diff --git a/src/main/java/io/github/gdpl2112/mirai/p1/services/ScriptService.java b/src/main/java/io/github/gdpl2112/mirai/p1/services/ScriptService.java new file mode 100644 index 0000000..a36ced2 --- /dev/null +++ b/src/main/java/io/github/gdpl2112/mirai/p1/services/ScriptService.java @@ -0,0 +1,217 @@ +package io.github.gdpl2112.mirai.p1.services; + +import io.github.gdpl2112.mirai.p1.services.script.BaseMessageScriptContext; +import io.github.gdpl2112.mirai.p1.services.script.BaseScriptUtils; +import io.github.gdpl2112.mirai.p1.services.script.ScriptContext; +import io.github.kloping.common.Public; +import io.github.kloping.file.FileUtils; +import io.github.kloping.judge.Judge; +import io.github.kloping.url.UrlUtils; +import kotlin.coroutines.CoroutineContext; +import net.mamoe.mirai.Bot; +import net.mamoe.mirai.contact.Contact; +import net.mamoe.mirai.contact.User; +import net.mamoe.mirai.event.EventHandler; +import net.mamoe.mirai.event.SimpleListenerHost; +import net.mamoe.mirai.event.events.*; +import net.mamoe.mirai.message.data.ForwardMessageBuilder; +import net.mamoe.mirai.message.data.Image; +import net.mamoe.mirai.message.data.Message; +import net.mamoe.mirai.message.data.MessageChain; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +/** + * @author github.kloping + */ +public class ScriptService extends SimpleListenerHost { + public ScriptService() { + System.setProperty("nashorn.args", "--no-deprecation-warning"); + } + + @Override + public void handleException(@NotNull CoroutineContext context, @NotNull Throwable exception) { + exception.printStackTrace(); + } + + public static final ScriptEngineManager SCRIPT_ENGINE_MANAGER = new ScriptEngineManager(); + public static final String[] NOT_PRINTS = {"未开启", "NOT OPEN", "not open", "exit", "end", "stop"}; + + public static Map<String, ScriptException> exceptionMap = new HashMap<>(); + + private File jsFile = new File("./conf/callApi/script.js"); + + private String getScriptCode(long bid) { + return FileUtils.getStringFromFile(jsFile.getAbsolutePath()); + } + + @EventHandler + public void onMessage(@NotNull MessageEvent event) { + if (event instanceof MessagePreSendEvent) return; + if (event instanceof MessagePostSendEvent) return; + final String code = getScriptCode(event.getBot().getId()); + if (Judge.isEmpty(code.trim())) return; + Public.EXECUTOR_SERVICE.submit(() -> { + try { + ScriptEngine javaScript = SCRIPT_ENGINE_MANAGER.getEngineByName("JavaScript"); + javaScript.put("context", new BaseMessageScriptContext(event)); + javaScript.put("utils", new BaseScriptUtils(event.getBot().getId())); + String msg = toMsg(event.getMessage()); + javaScript.put("msg", msg); + javaScript.eval(code); + } catch (Throwable e) { + onException(event.getBot(), e); + } + }); + } + + private String toMsg(MessageChain chain) { + String msg = DgSerializer.messageChainSerializeToString(chain); + return msg; + } + + @EventHandler + public void onEvent(BotEvent event) { + if (event instanceof MessageEvent) return; + if (event instanceof MessagePreSendEvent) return; + if (event instanceof MessagePostSendEvent) return; + if (event instanceof BotOnlineEvent) return; + if (event instanceof BotOfflineEvent) return; + final String code = getScriptCode(event.getBot().getId()); + if (Judge.isEmpty(code.trim())) return; + Public.EXECUTOR_SERVICE.submit(() -> { + try { + ScriptEngine javaScript = SCRIPT_ENGINE_MANAGER.getEngineByName("JavaScript"); + javaScript.put("context", new BasebBotEventScriptContext(event)); + javaScript.put("event", event); + javaScript.put("utils", new BaseScriptUtils(event.getBot().getId())); + javaScript.put("msg", event.toString()); + javaScript.eval(code); + } catch (Throwable e) { + onException(event.getBot(), e); + } + }); + } + + public static void onException(Bot bot, Throwable e) { + if (e instanceof javax.script.ScriptException) { + String e1 = e.getMessage(); + for (String e0 : NOT_PRINTS) { + if (e1.contains(e0)) return; + } + } + e.printStackTrace(); + String err = io.github.kloping.MySpringTool.PartUtils.getExceptionLine(e); + err = e + err; + Long bid = bot.getId(); + ScriptException se = new ScriptException(err, System.currentTimeMillis(), bid); + exceptionMap.put(bid.toString(), se); + System.err.println(String.format("%s Bot 脚本 执行失败", bot.getId())); + } + + public static class BasebBotEventScriptContext implements ScriptContext { + private BotEvent event; + + public BasebBotEventScriptContext(BotEvent userEvent) { + this.event = userEvent; + } + + @Override + public MessageChain getRaw() { + return null; + } + + @Override + public void send(String str) { + + } + + @Override + public void send(Message message) { + + } + + @Override + public Bot getBot() { + return event.getBot(); + } + + @Override + public User getSender() { + return null; + } + + @Override + public Contact getSubject() { + return null; + } + + @Override + public ForwardMessageBuilder forwardBuilder() { + return new ForwardMessageBuilder(event.getBot().getAsFriend()); + } + + @Override + public Message deSerialize(String msg) { + return DgSerializer.stringDeserializeToMessageChain(msg, event.getBot(), event.getBot().getAsFriend()); + } + + @Override + public MessageChain getMessageChainById(int id) { + return null; + } + + @Override + public Image uploadImage(String url) { + try { + byte[] bytes = UrlUtils.getBytesFromHttpUrl(url); + Image image = Contact.uploadImage(event.getBot().getAsFriend(), new ByteArrayInputStream(bytes)); + return image; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String getType() { + return event.getClass().getSimpleName(); + } + } + + @Nullable + public static MessageChain getSingleMessages(int id, BotEvent event) { + return null; + } + + public static class ScriptException { + private String msg; + private Long time; + private Long qid; + + public ScriptException(String msg, Long time, Long qid) { + this.msg = msg; + this.time = time; + this.qid = qid; + } + + public String getMsg() { + return msg; + } + + public Long getTime() { + return time; + } + + public Long getQid() { + return qid; + } + } +} diff --git a/src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseMessageScriptContext.java b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseMessageScriptContext.java new file mode 100644 index 0000000..eb106b1 --- /dev/null +++ b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseMessageScriptContext.java @@ -0,0 +1,89 @@ +package io.github.gdpl2112.mirai.p1.services.script; + +import io.github.gdpl2112.mirai.p1.services.DgSerializer; +import io.github.kloping.url.UrlUtils; +import net.mamoe.mirai.Bot; +import net.mamoe.mirai.contact.Contact; +import net.mamoe.mirai.contact.User; +import net.mamoe.mirai.event.events.FriendMessageEvent; +import net.mamoe.mirai.event.events.GroupMessageEvent; +import net.mamoe.mirai.event.events.GroupMessageSyncEvent; +import net.mamoe.mirai.event.events.MessageEvent; +import net.mamoe.mirai.message.data.ForwardMessageBuilder; +import net.mamoe.mirai.message.data.Image; +import net.mamoe.mirai.message.data.Message; +import net.mamoe.mirai.message.data.MessageChain; + +import java.io.ByteArrayInputStream; + + +public class BaseMessageScriptContext implements ScriptContext { + private MessageEvent event; + + public BaseMessageScriptContext(MessageEvent event) { + this.event = event; + } + + @Override + public Bot getBot() { + return event.getBot(); + } + + @Override + public MessageChain getRaw() { + return event.getMessage(); + } + + @Override + public Message deSerialize(String msg) { + return DgSerializer.stringDeserializeToMessageChain(msg, event.getBot(), event.getSubject()); + } + + @Override + public void send(String str) { + Message msg = DgSerializer.stringDeserializeToMessageChain(str, event.getBot(), event.getSubject()); + event.getSubject().sendMessage(msg); + } + + @Override + public void send(Message message) { + event.getSubject().sendMessage(message); + } + + @Override + public ForwardMessageBuilder forwardBuilder() { + return new ForwardMessageBuilder(getSubject()); + } + + @Override + public MessageChain getMessageChainById(int id) { + return null; + } + + @Override + public User getSender() { + return event.getSender(); + } + + @Override + public Contact getSubject() { + return event.getSubject(); + } + + @Override + public Image uploadImage(String url) { + try { + byte[] bytes = UrlUtils.getBytesFromHttpUrl(url); + Image image = Contact.uploadImage(event.getBot().getAsFriend(), new ByteArrayInputStream(bytes)); + return image; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + @Override + public String getType() { + return event instanceof GroupMessageEvent || event instanceof GroupMessageSyncEvent ? "group" : event instanceof FriendMessageEvent ? "friend" : "Unknown"; + } +} diff --git a/src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseScriptUtils.java b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseScriptUtils.java new file mode 100644 index 0000000..80d1f6a --- /dev/null +++ b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/BaseScriptUtils.java @@ -0,0 +1,116 @@ +package io.github.gdpl2112.mirai.p1.services.script; + +import io.github.gdpl2112.mirai.p1.services.DgSerializer; +import io.github.kloping.map.MapUtils; +import io.github.kloping.url.UrlUtils; +import net.mamoe.mirai.message.data.MessageChain; +import org.jsoup.Jsoup; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.*; + +public class BaseScriptUtils implements ScriptUtils { + private long bid; + + public BaseScriptUtils(long bid) { + this.bid = bid; + } + + public static final Map<Long, Map<String, Object>> BID_2_VARIABLES = new HashMap<>(); + + @Override + public String requestGet(String url) { + return UrlUtils.getStringFromHttpUrl(url); + } + + @Override + public String requestPost(String url, String data) { + try { + return Jsoup.connect(url).ignoreContentType(true).ignoreHttpErrors(true).requestBody(data).post().body().wholeText(); + } catch (IOException e) { + return e.getLocalizedMessage(); + } + } + + @Override + public String serialize(MessageChain chain) { + return DgSerializer.messageChainSerializeToString(chain); + } + + @Override + public Object get(String name) { + return getValueOrDefault(BID_2_VARIABLES, bid, name, null); + } + + @Override + public Object set(String name, Object value) { + Object ov = getValueOrDefault(BID_2_VARIABLES, bid, name, null); + MapUtils.append(BID_2_VARIABLES, bid, name, value, HashMap.class); + return ov; + } + + @Override + public Integer clear() { + int i = 0; + Map<String, Object> sizeMap = BID_2_VARIABLES.get(bid); + if (sizeMap != null) { + i = sizeMap.size(); + sizeMap.clear(); + } + return i; + } + + @Override + public Object del(String name) { + Map<String, Object> sizeMap = BID_2_VARIABLES.get(bid); + if (sizeMap != null) { + Object oa = sizeMap.get(name); + sizeMap.remove(name); + return oa; + } + return null; + } + + @Override + public List<Map.Entry<String, Object>> list() { + if (BID_2_VARIABLES.containsKey(bid)) + return new LinkedList<>(BID_2_VARIABLES.get(bid).entrySet()); + return new ArrayList<>(); + } + + @Override + public <T> T newObject(String name, Object... args) { + try { + Class cla = Class.forName(name); + List<Class> list = new ArrayList<>(); + for (Object arg : args) { + list.add(arg.getClass()); + } + Constructor constructor = cla.getDeclaredConstructor(list.toArray(new Class[0])); + return (T) constructor.newInstance(args); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + + public static final <T, K1, K2> T getValueOrDefault(Map<K1, Map<K2, T>> map, K1 k1, K2 k2, T def) { + if (map.containsKey(k1)) { + Map<K2, T> m2 = map.get(k1); + if (m2.containsKey(k2)) { + return m2.get(k2); + } else { + m2.put(k2, def); + map.put(k1, m2); + return def; + } + } else { + Map<K2, T> m2 = new HashMap<>(); + m2.put(k2, def); + map.put(k1, m2); + return def; + } + } +} diff --git a/src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptContext.java b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptContext.java new file mode 100644 index 0000000..756230e --- /dev/null +++ b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptContext.java @@ -0,0 +1,148 @@ +package io.github.gdpl2112.mirai.p1.services.script; + +import io.github.gdpl2112.mirai.p1.services.DgSerializer; +import io.github.kloping.url.UrlUtils; +import net.mamoe.mirai.Bot; +import net.mamoe.mirai.contact.Contact; +import net.mamoe.mirai.contact.User; +import net.mamoe.mirai.message.data.*; + +import java.io.ByteArrayInputStream; + +/** + * script 交互对象 + * 预设脚本环境变量: context + * + * @author github.kloping + */ +public interface ScriptContext { + /** + * 获取bot + * + * @return + */ + Bot getBot(); + + /** + * 获取元数据 + * + * @return + */ + MessageChain getRaw(); + + /** + * 发送字符串 + * + * @param str + */ + void send(String str); + + /** + * 发送至所在环境 + * + * @param message + */ + void send(Message message); + + /** + * 获得一个 Builder + * + * @return + */ + default MessageChainBuilder builder() { + return new MessageChainBuilder(); + } + + /** + * 获得一个 转发行 + * + * @return + */ + ForwardMessageBuilder forwardBuilder(); + + /** + * 创建音乐分享消息 + * + * @param kind + * @param title + * @param summer + * @param jumUrl + * @param picUrl + * @param url + * @return + */ + default MusicShare createMusicShare(String kind, String title, String summer, String jumUrl, String picUrl, String url) { + return new MusicShare(MusicKind.valueOf(kind), title, summer, jumUrl, picUrl, url); + } + + /** + * 上传图片 + * + * @param url + * @return + */ + default Image uploadImage(String url) { + try { + byte[] bytes = UrlUtils.getBytesFromHttpUrl(url); + Image image = Contact.uploadImage(getBot().getAsFriend(), new ByteArrayInputStream(bytes)); + return image; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 构建 文本 + * + * @param text + * @return + */ + default PlainText newPlainText(String text) { + return new PlainText(text); + } + + default SuperFace toSuperFace(int id) { + return SuperFace.from(new Face(id)); + } + + /** + * 反向 str 解析为 Message + * + * @param msg + * @return + */ + default Message deSerialize(String msg) { + return DgSerializer.stringDeserializeToMessageChain(msg, getBot(), getBot().getAsFriend()); + } + + /** + * 从id获取MessageChain 可用于直接发送 <br> + * !! 仅能获取2小时以内的数据 + * + * @param id + * @return + */ + MessageChain getMessageChainById(int id); + + /** + * 发送者ID + * + * @return + */ + User getSender(); + + /** + * 发送环境id 一般为 群id + * + * @return + */ + Contact getSubject(); + + /** + * 所处环境 <a href="https://github.com/gdpl2112/dg-bot/blob/master/js-api.md"> 说明</a> + * + * @return + */ + String getType(); +} diff --git a/src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptUtils.java b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptUtils.java new file mode 100644 index 0000000..5c76275 --- /dev/null +++ b/src/main/java/io/github/gdpl2112/mirai/p1/services/script/ScriptUtils.java @@ -0,0 +1,102 @@ +package io.github.gdpl2112.mirai.p1.services.script; + +import net.mamoe.mirai.message.data.Image; +import net.mamoe.mirai.message.data.MessageChain; + +import java.util.List; +import java.util.Map; + +/** + * 脚本工具 + * 预设脚本变量为: + * utils + * + * @author github.kloping + */ +public interface ScriptUtils { + + /** + * get 请求 + * + * @param url + * @return + */ + String requestGet(String url); + + /** + * post 请求 + * + * @param url + * @return + */ + String requestPost(String url, String data); + + + /** + * 查询image url 通过image id + * + * @param imageId + * @return + */ + default String queryUrlFromId(String imageId) { + return Image.queryUrl(Image.fromId(imageId)); + } + + /** + * 正向解析mes为定制string + * + * @param chain + * @return + */ + String serialize(MessageChain chain); + + + /** + * 获取变量 + * + * @param name + * @return + */ + Object get(String name); + + /** + * 设置变量 + * + * @param name + * @param value + * @return + */ + Object set(String name, Object value); + + /** + * 清除当前账号的所有变量 + * + * @return + */ + Integer clear(); + + /** + * 删除指定变量 + * + * @param name + * @return + */ + Object del(String name); + + /** + * 列出当前bot所有变量 + * + * @return + */ + List<Map.Entry<String, Object>> list(); + + /** + * js 创建Java的对象 + * + * @param name 类全名 如: java.util.HashMap + * @param args 参数可选 + * @param <T> + * @return + */ + <T> T newObject(String name, Object... args); +} diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index b402ae5..6c13580 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -51,7 +51,7 @@ <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> - <p>自定义调用API<span class="sr-only">(current)</span></p> + <span class="nav-link">API管理</span> </li> <li class="nav-item"> <a class="nav-link" href="http://kloping.top/">kloping's web</a>