package com.ruoyi.app.push; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.system.utils.JedisFactory; import org.springframework.stereotype.Component; import redis.clients.jedis.Jedis; import java.util.Locale; import java.util.Set; /** 仅处理原生用户通知;从明确场景选择随包音频,不根据状态或通知文案猜测声音。 */ @Component public class NativePushSoundResolver { private static final Set SCENES = Set.of("RIDER_ACCEPTED", "ORDER_DELIVERING", "ORDER_DELIVERED", "MERCHANT_ACCEPTED", "MERCHANT_READY", "PAYMENT_SUCCEEDED", "ORDER_CANCELLED"); private static final Set STOP_EVENTS = Set.of("FLASH_PICKUP_STOP_COMPLETED", "FLASH_DELIVERY_STOP_COMPLETED"); private final JedisFactory jedisFactory; public NativePushSoundResolver(JedisFactory jedisFactory) { this.jedisFactory = jedisFactory; } public NativePushSound forRecipient(RecipientApp app, Long userId, String payload) { String scene = scene(app, payload); if (scene == null) { return null; } String language = null; if (userId != null) { // 与 /changeLanguages 保持同一 DB 和原始字符串格式,不经过 JSON Redis 反序列化。 try (Jedis jedis = jedisFactory.create()) { language = jedis.get(userId.toString()); } catch (RuntimeException ignored) { // 缺失或暂时读不到语言不阻断通知,统一回退繁体中文。 } } return sound(scene, language); } public NativePushSound forTest(RecipientApp app, String language, String payload) { String scene = scene(app, payload); return scene == null ? null : sound(scene, language); } private static String scene(RecipientApp app, String payload) { if (app != RecipientApp.USER || payload == null) { return null; } try { JSONObject fields = JSON.parseObject(payload); if (fields == null) { return null; } String scene = fields.getString("eventScene"); if (scene != null && SCENES.contains(scene)) { return scene; } String event = fields.getString("eventType"); return event != null && STOP_EVENTS.contains(event) ? event : null; } catch (RuntimeException ignored) { return null; } } private static NativePushSound sound(String scene, String language) { return new NativePushSound(scene.toLowerCase(Locale.ROOT) + "_" + languageSuffix(language)); } private static String languageSuffix(String language) { if (language == null || language.isBlank()) { return "zh_hant"; } String tag = language.trim().replace('_', '-').toLowerCase(Locale.ROOT); if (tag.equals("zhhant") || tag.equals("tw") || tag.equals("zhtw") || tag.equals("zh-tw") || tag.equals("zh-hk") || tag.equals("zh-mo") || tag.equals("zh-hant") || tag.startsWith("zh-hant-")) { return "zh_hant"; } if (tag.equals("zhhans") || tag.equals("cn") || tag.equals("zhcn") || tag.equals("zh-cn") || tag.equals("zh-sg") || tag.equals("zh-hans") || tag.startsWith("zh-hans-")) { return "zh_hans"; } return switch (tag.split("-", 2)[0]) { case "en" -> "en"; case "th" -> "th"; case "id", "in" -> "id"; case "ms" -> "ms"; case "tl", "fil" -> "tl"; default -> "zh_hant"; }; } }