Skip to content

Commit 05814a1

Browse files
committed
feat(Service): Auto Update
1 parent 30c8578 commit 05814a1

26 files changed

Lines changed: 697 additions & 53 deletions

File tree

‎bot/mirai/src/main/java/moe/dituon/petpet/bot/qq/mirai/MiraiPetpet.java‎

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
import moe.dituon.petpet.bot.qq.mirai.handler.MiraiSentMessageHandler;
77
import moe.dituon.petpet.service.BaseService;
88
import moe.dituon.petpet.service.EnvironmentChecker;
9+
import moe.dituon.petpet.service.TemplateUpdater;
910
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
1011
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescriptionBuilder;
1112
import net.mamoe.mirai.event.GlobalEventChannel;
1213
import net.mamoe.mirai.event.events.*;
1314
import net.mamoe.mirai.utils.MiraiLogger;
1415

1516
import java.awt.*;
17+
import java.io.File;
1618

1719
@SuppressWarnings("unused")
1820
public final class MiraiPetpet extends JavaPlugin {
@@ -39,20 +41,20 @@ public void onEnable() {
3941
.resolve(MiraiBotService.DEFAULT_CUSTOM_METADATA_PATH.getName())
4042
.toFile()
4143
);
42-
service.addTemplates(getDataFolder());
43-
service.addFonts(getDataFolder().toPath().resolve("./fonts"));
4444
service.setPermissionConfigPath(getConfigFolderPath().resolve("permissions"));
45-
var defaultFont = service.updateDefaultFont();
46-
service.updateScriptService();
47-
//TODO
48-
// if (config.getAutoUpdate()) new Thread(() -> {
49-
// DataUpdater updater = new DataUpdater(service, getDataFolder());
50-
// if (updater.autoUpdate()) {
51-
// getLogger().info("Petpet 模板更新完毕, 正在重载");
52-
// config.keyListString = "";
53-
// config.readData(MiraiPetpet.dataFolder);
54-
// }
55-
// }).start();
45+
var defaultFont = loadService();
46+
if (config.getUpdate().getEnabled()) new Thread(() -> {
47+
boolean success = new TemplateUpdater(config.getUpdate(), service).startUpdate();
48+
if (success) {
49+
log.info("Petpet 正在重载数据...");
50+
service.clear();
51+
var newDefaultFont = loadService();
52+
log.info(String.format("已加载 %s 模板; 随机表列包含 %s 模板;", service.getStaticModelMap().size(), service.getRandomIdList().size()));
53+
log.info(String.format("已注册 %s 脚本; 默认模板为 %s;", service.getScriptModelMap().size(), service.getDefaultTemplateId()));
54+
log.info(String.format("已加载 %s 字体; 默认字体为 %s;", GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames().length, newDefaultFont));
55+
56+
}
57+
}).start();
5658

5759
EnvironmentChecker.check();
5860
log.info("\u001B[95m\n\n" +
@@ -99,4 +101,14 @@ public void onEnable() {
99101
GlobalEventChannel.INSTANCE.subscribeAlways(NudgeEvent.class, nudgeHandler::handle);
100102
}
101103
}
104+
105+
/**
106+
* @return 默认字体 name
107+
*/
108+
private String loadService() {
109+
service.addTemplates(getDataFolder());
110+
service.addFonts(getDataFolder().toPath().resolve("./fonts"));
111+
service.updateScriptService();
112+
return service.updateDefaultFont();
113+
}
102114
}

‎bot/mirai/src/main/java/moe/dituon/petpet/bot/qq/mirai/MiraiPluginConfig.kt‎

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package moe.dituon.petpet.bot.qq.mirai
33
import moe.dituon.petpet.bot.qq.*
44
import moe.dituon.petpet.bot.utils.Cooler
55
import moe.dituon.petpet.core.FontManager
6+
import moe.dituon.petpet.service.TemplateUpdaterConfig
67
import net.mamoe.mirai.console.data.AutoSavePluginConfig
78
import net.mamoe.mirai.console.data.ValueDescription
89
import net.mamoe.mirai.console.data.value
@@ -59,12 +60,6 @@ object MiraiPluginConfig : AutoSavePluginConfig("PetPet") {
5960
@ValueDescription("是否使用 headless 模式")
6061
val headless: Boolean by value(true)
6162

62-
@ValueDescription("是否自动从仓库更新模板 (暂时无效)")
63-
val autoUpdate: Boolean by value(true)
64-
65-
@ValueDescription("用于自动更新的仓库地址 (暂时无效)")
66-
val repositoryUrls: List<String> by value(listOf(""))
67-
6863
// @ValueDescription("是否启用开发模式 (支持热重载)")
6964
// val devMode: Boolean by value(false)
7065

@@ -95,6 +90,9 @@ object MiraiPluginConfig : AutoSavePluginConfig("PetPet") {
9590
@ValueDescription("默认群聊管理权限")
9691
val defaultGroupEditPermission: String by value(DEFAULT_DEFAULT_GROUP_EDIT_PERMISSION)
9792

93+
@ValueDescription("自动更新配置, 详见文档")
94+
val update: TemplateUpdaterConfig by value(TemplateUpdaterConfig())
95+
9896
fun toQQBotConfig() = QQBotConfig(
9997
command = command,
10098
commandHead = commandHead,
@@ -116,9 +114,8 @@ object MiraiPluginConfig : AutoSavePluginConfig("PetPet") {
116114
groupCooldownTime = groupCoolDown,
117115
userCooldownTime = userCoolDown,
118116
inCoolDownMessage = inCoolDownMessage,
119-
autoUpdate = autoUpdate,
120-
repositoryUrls = repositoryUrls,
121117
headless = headless,
118+
update = update,
122119
gifQuality = gifQuality,
123120
)
124121
}

‎bot/onebot/src/main/kotlin/moe/dituon/petpet/bot/qq/onebot/Main.kt‎

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import moe.dituon.petpet.bot.qq.onebot.handler.OnebotGroupNudgeHandler
1616
import moe.dituon.petpet.bot.qq.onebot.handler.OnebotMessageHandler
1717
import moe.dituon.petpet.bot.qq.onebot.handler.OnebotSentMessageHandler
1818
import moe.dituon.petpet.service.EnvironmentChecker
19+
import moe.dituon.petpet.service.TemplateUpdater
1920
import net.mamoe.yamlkt.Yaml
2021
import org.slf4j.Logger
2122
import org.slf4j.LoggerFactory
@@ -58,14 +59,20 @@ suspend fun main() {
5859
}
5960
globalBotInstance = bot
6061
val service = OnebotBotService(bot, config)
61-
for (templatePath in config.templatePath) {
62-
service.addTemplates(systemPath.resolve(templatePath))
63-
}
64-
for (fontPath in config.fontPath) {
65-
service.addFonts(systemPath.resolve(fontPath).toPath())
62+
63+
var defaultFont: String ?= null
64+
fun loadService() {
65+
for (templatePath in config.templatePath) {
66+
service.addTemplates(systemPath.resolve(templatePath))
67+
}
68+
for (fontPath in config.fontPath) {
69+
service.addFonts(systemPath.resolve(fontPath).toPath())
70+
}
71+
defaultFont = service.updateDefaultFont()
72+
service.updateScriptService()
6673
}
67-
val defaultFont = service.updateDefaultFont()
68-
service.updateScriptService()
74+
loadService()
75+
6976
EnvironmentChecker.check()
7077
log.info(banner)
7178
log.info("Petpet Onebot 客户端启动成功:")
@@ -78,6 +85,24 @@ suspend fun main() {
7885
)
7986
bot.getLoginInfo().data ?: throw IllegalStateException("获取机器人信息失败")
8087

88+
if (config.update.enabled) {
89+
CoroutineScope(SupervisorJob() + Dispatchers.Default).launch {
90+
val success = TemplateUpdater(config.update, service).startUpdate()
91+
if (success) {
92+
log.info("Petpet 正在重载数据...")
93+
service.clear()
94+
loadService()
95+
log.info("已加载 ${service.staticModelMap.size} 模板; 随机表列包含 ${service.randomIdList.size} 模板;")
96+
log.info("已注册 ${service.scriptModelMap.size} 脚本; 默认模板为 ${service.defaultTemplateId};")
97+
log.info(
98+
"已加载 ${
99+
GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames.size
100+
} 字体; 默认字体为 ${defaultFont};"
101+
)
102+
}
103+
}
104+
}
105+
81106
val imageCacheHandler = OnebotSentMessageHandler(service)
82107
val eventScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
83108
if (config.respondGroup) {
@@ -123,3 +148,7 @@ suspend fun main() {
123148

124149
log.info("Petpet Onebot 客户端启动完毕, 发送 ${config.command} 以触发默认模板...")
125150
}
151+
152+
fun startService() {
153+
154+
}

‎bot/onebot/src/main/kotlin/moe/dituon/petpet/bot/qq/onebot/OnebotConfig.kt‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import kotlinx.serialization.Serializable
55
import moe.dituon.petpet.bot.qq.*
66
import moe.dituon.petpet.bot.utils.Cooler
77
import moe.dituon.petpet.core.FontManager
8+
import moe.dituon.petpet.service.TemplateUpdaterConfig
89
import net.mamoe.yamlkt.Comment
910

1011
@Serializable
@@ -126,6 +127,9 @@ data class OnebotConfig(
126127

127128
@Comment("传递给 Onebot 协议端的图像服务器地址")
128129
val httpServerUrl: String = OnebotBotService.DEFAULT_HTTP_SERVER_URL,
130+
131+
@Comment("自动更新配置, 详见文档")
132+
val update: TemplateUpdaterConfig = TemplateUpdaterConfig()
129133
) {
130134
fun toClientConfig() = BotConfig(
131135
url,
@@ -162,9 +166,8 @@ data class OnebotConfig(
162166
groupCooldownTime = groupCooldownTime,
163167
userCooldownTime = userCooldownTime,
164168
inCoolDownMessage = inCoolDownMessage,
165-
// autoUpdate = autoUpdate,
166-
// repositoryUrls = repositoryUrls,
167169
headless = headless,
170+
update = update,
168171
gifQuality = gifQuality,
169172
)
170173
}

‎bot/shared/src/main/java/moe/dituon/petpet/bot/BotService.java‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
package moe.dituon.petpet.bot;
22

33
import lombok.Getter;
4-
import lombok.Setter;
54
import moe.dituon.petpet.core.element.PetpetModel;
65
import moe.dituon.petpet.service.BaseService;
7-
import moe.dituon.petpet.service.ObservableBaseService;
6+
import moe.dituon.petpet.service.UpdatableBaseService;
87
import org.jetbrains.annotations.Nullable;
98

109
import java.util.ArrayList;
@@ -15,7 +14,7 @@
1514
/**
1615
* 对于通用社交媒体的抽象 Bot 服务
1716
*/
18-
public class BotService extends ObservableBaseService {
17+
public class BotService extends UpdatableBaseService {
1918
public static final String BOT_LOAD_EVENT_KEY = "bot_load";
2019
public static final String NO_TEMPLATE_MESSAGE = "暂未加载任何 Petpet 模板...";
2120

‎bot/shared/src/main/java/moe/dituon/petpet/bot/qq/QQBotConfig.kt‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import kotlinx.serialization.Serializable
55
import moe.dituon.petpet.bot.utils.Cooler
66
import moe.dituon.petpet.core.BaseRenderConfig
77
import moe.dituon.petpet.core.FontManager
8+
import moe.dituon.petpet.service.TemplateUpdaterConfig
89
import java.util.concurrent.TimeUnit
910

1011
val DEFAULT_COMMAND_PERMISSION_NAME = mapOf(
@@ -98,11 +99,10 @@ data class QQBotConfig(
9899
@SerialName("in_cooldown_message")
99100
val inCoolDownMessage: String = Cooler.DEFAULT_MESSAGE,
100101

101-
@SerialName("auto_update")
102-
val autoUpdate: Boolean = true,
103-
@SerialName("repository_urls")
104-
val repositoryUrls: List<String> = listOf(),
105102
val headless: Boolean = true,
103+
104+
val update: TemplateUpdaterConfig = TemplateUpdaterConfig(),
105+
106106
@SerialName("gif_quality")
107107
override val gifQuality: Int = 10,
108108
): BaseRenderConfig(

‎bot/shared/src/main/java/moe/dituon/petpet/bot/qq/QQBotService.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ public void updateScriptService() {
195195
}
196196
}
197197

198+
@Override
199+
public void clear() {
200+
templateExpectedSizeCache.clear();
201+
super.clear();
202+
}
203+
198204
// save permission config
199205
protected void onJvmExit() {
200206
if (!savePermission) return;

‎core/src/main/java/moe/dituon/petpet/core/FontManager.java‎

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.nio.file.Path;
1414
import java.util.List;
1515
import java.util.*;
16+
import java.util.stream.Collectors;
1617

1718
@Slf4j
1819
public class FontManager {
@@ -23,6 +24,7 @@ protected static class FontManagerInstance {
2324
public static FontManager getInstance() {
2425
return FontManagerInstance.INSTANCE;
2526
}
27+
2628
public static final String DEFAULT_WINDOWS_FONT = "Microsoft YaHei";
2729
public static final String DEFAULT_MACOS_FONT = "PingFang SC";
2830
public static final String DEFAULT_LINUX_FONT = "Noto Sans CJK SC";
@@ -46,12 +48,23 @@ public static FontManager getInstance() {
4648
// , LANG_EMOJI
4749
};
4850

51+
@Getter
52+
protected final Map<Font, File> localFontMap = new HashMap<>(32);
53+
/**
54+
* 未指定路径时默认用于下载更新的本地路径
55+
*/
56+
@Getter
57+
@Nullable
58+
protected File localFontDirectory = null;
59+
4960
@Getter
5061
protected final Map<Font, Set<SupportedLanguage>> fontSupportedLanguageMap = new HashMap<>(256);
5162
@Getter
5263
protected final Map<SupportedLanguage, Set<Font>> supportedLanguageFontMap;
5364
@Getter
5465
protected String defaultFontFamily = DEFAULT_FONT;
66+
@Getter
67+
protected Set<String> fontFamilies;
5568

5669
protected FontManager() {
5770
supportedLanguageFontMap = new HashMap<>(supportedLanguages.length);
@@ -64,6 +77,7 @@ protected FontManager() {
6477
}
6578

6679
setDefaultFontFamily(null);
80+
updateAvailableFontFamilyNames();
6781
}
6882

6983
public String setDefaultFontFamily(@Nullable String defaultFamily) {
@@ -89,6 +103,12 @@ public String setDefaultFontFamily(@Nullable String defaultFamily) {
89103
return defaultFontFamily;
90104
}
91105

106+
protected void updateAvailableFontFamilyNames() {
107+
fontFamilies = Arrays.stream(environment.getAvailableFontFamilyNames())
108+
.map(String::toLowerCase)
109+
.collect(Collectors.toSet());
110+
}
111+
92112

93113
public Font getFont(
94114
@Nullable String family,
@@ -98,7 +118,7 @@ public Font getFont(
98118
return StyleContext.getDefaultStyleContext().getFont(family == null ? defaultFontFamily : family, style, size);
99119
}
100120

101-
public void addFont(Font font) {
121+
protected void addFont(Font font) {
102122
var langSet = fontSupportedLanguageMap.computeIfAbsent(font, f -> new HashSet<>(supportedLanguages.length));
103123
for (SupportedLanguage language : supportedLanguages) {
104124
boolean allSupported = true;
@@ -113,19 +133,25 @@ public void addFont(Font font) {
113133
supportedLanguageFontMap.get(language).add(font);
114134
}
115135
}
136+
updateAvailableFontFamilyNames();
116137
}
117138

118139

119140
public boolean addFont(File fontFile) throws IOException, FontFormatException {
120141
Font customFont = Font.createFont(Font.TRUETYPE_FONT, fontFile);
121142
boolean success = environment.registerFont(customFont);
143+
122144
if (success) {
123145
addFont(customFont);
146+
localFontMap.put(customFont, fontFile);
124147
}
125148
return success;
126149
}
127150

128151
public void addFonts(Path fontDirectory) {
152+
if (localFontDirectory == null) {
153+
localFontDirectory = fontDirectory.toFile();
154+
}
129155
if (!Files.exists(fontDirectory) || !Files.isDirectory(fontDirectory)) return;
130156

131157
var files = fontDirectory.toFile().listFiles();
@@ -151,6 +177,14 @@ public void addFonts(Path fontDirectory) {
151177
}
152178
}
153179

180+
public boolean isFontAvailable(String fontName) {
181+
return fontFamilies.contains(fontName.toLowerCase());
182+
}
183+
184+
public boolean isFontAvailable(Set<String> fontNames) {
185+
return fontFamilies.containsAll(fontNames);
186+
}
187+
154188
public static class SupportedLanguage {
155189
protected char[] testPoints;
156190
public final String name;

0 commit comments

Comments
 (0)