MiraiForum

    • 注册
    • 登录
    • 搜索
    • 热门
    • 最新
    • 未解决
    • 标签
    • 群组
    • 友情链接
    1. 主页
    2. 2446694
    3. 帖子
    2
    • 资料
    • 关注 1
    • 粉丝 0
    • 主题 11
    • 帖子 37
    • 最佳 0
    • 有争议的 0
    • 群组 0

    2446694 发布的帖子

    • 【mirai-core】当我使用使用聊天记录消息回复时,机器人生成的引用消息会自带一个@TA
      1. 我使用了new ForwardMessage作为消息回复。
      2. 当我在 ForwardMessage的Node中的一个MessageChain中使用了QuoteReply引用了一条消息后,这个Node消息前面自带一个 @TA
      3. 电脑版显示没有这样的问题,这种问题出现在了移动端

      关键代码

      //  [其他代码]
      for (QuoteReply quote : quoteList) {
          MessageSource source = quote.getSource();
          MessageChain originalMessage = chainService.selectMessageChain(source);
          if (originalMessage == null) {
              // 这里在Node中引入了quote引用,quote是QuoteReplay类型的
              nodeList.add(new ForwardMessage.Node(botId, (int) (System.currentTimeMillis() / 1000), "警告:未存储该消息的原数据", quote));
              break;
          }
          // [其他 nodeList.add]
      }
      // [其他代码]
      subject.sendMessage(new ForwardMessage(
              preview,
              String.format("%s的聊天记录", botName),
              String.format("[回复 @%s]", event.getSenderName()),
              String.format("回复 @%s", event.getSenderName()),
              String.format("查看%d条回复消息", nodeList.size()),
              nodeList
      ));
      

      效果图
      ef0208c2-25ef-4876-8da7-5ca5fb753c76-image.png

      希望修复,感激不尽!!!

      发布在 BUG反馈
      2
      2446694
    • RE: 如何去掉引用回复的 @TA?

      @abc408880155 对了,我用到是聊天记录的形式

       subject.sendMessage(new ForwardMessage(
                              preview,
                              String.format("%s的聊天记录", botName),
                              String.format("[回复 @%s]", event.getSenderName()),
                              String.format("回复 @%s", event.getSenderName()),
                              String.format("查看%d条回复消息", nodeList.size()),
                              nodeList
                      ));
      
      发布在 开发交流
      2
      2446694
    • RE: 如何去掉引用回复的 @TA?

      @abc408880155 我用的是安卓QQ8.9.50
      我裂了,不论我用何种方式声明QuoteReply,都会带一个@TA,强迫症看着很爽

      发布在 开发交流
      2
      2446694
    • RE: 如何去掉引用回复的 @TA?

      @2446694 组件是:mirai-core-2.15.0M1

      发布在 开发交流
      2
      2446694
    • RE: 如何去掉引用回复的 @TA?

      @abc408880155 我使用了new QuoteReply(new PlainText("未存储该元数据"));
      但还是会显示@TA,然后我发现,电脑上没有显示@TA,只有手机上显示了@TA,QQ版本是当前最新版

      发布在 开发交流
      2
      2446694
    • 如何去掉引用回复的 @TA?

      使用组件:mirai-core

      机器人发消息引用回复消息时,总是自带一个@TA,如何去掉这个@TA符号?

      如图所示:
      b0a71a25-84dc-4672-a32c-43a267d7dce4-96B8A87D1F3B393331DEBFC27B889902.jpg

      java源码

      for (QuoteReply quote : quoteList) {
          MessageSource source = quote.getSource();
          MessageChain originalMessage = chainService.selectMessageChain(source);
              if (originalMessage == null) {
                  // 客户端显示的quote是一个附带 @TA 的引用,即便我使用 new QuoteReply 也是会带 @TA
                  // 关键代码:我把引用 "quote" 传入到了作为了 MessageChain参数
                  nodeList.add(new ForwardMessage.Node(botId, (int) (System.currentTimeMillis() / 1000), "警告:未存储该消息的原数据", quote));
                  break;
              }
              if (source.getFromId() == sender.getId()) {
                  inputGPTMessageList.add(formatQuote(originalMessage, source, "user"));
              } else {
                  inputGPTMessageList.add(formatQuote(originalMessage, source, "assistant"));
              }
      }
      

      如何取掉这个@TA符号

      发布在 开发交流
      2
      2446694
    • RE: 机器人自己发送的消息,MessageEvent事件监听不到

      @cssxsh 牛啦,这是我的实现

          private void messagePostSendEventListener() {
              logger.info("MessagePostSendEventListener Running");
              GlobalEventChannel.INSTANCE.subscribeAlways(MessagePostSendEvent.class, event -> {
                  logger.info("MessagePostSendEvent...");
                  // 这里新构造了一个带source的chain,存储到数据库中
                  MessageChain chain = Objects.requireNonNull(event.getReceipt()).getSource().plus(event.getMessage());
                  if (!chainService.insertMessageChain(new MessageChainData(chain)))
                      logger.warn("存储失败: " + chain.contentToString());
              });
          }
      
      发布在 BUG反馈
      2
      2446694
    • 机器人自己发送的消息,MessageEvent事件监听不到

      使用组件:Mirai-core 2.15-M1

      前因

      我想要将数据存储到数据库中,以从别人的引用消息中获取原数据
      但是当别人引用除机器人以外其他消息是,数据库可以查询到
      当别人引用机器人发的消息时,数据库查询不到

      控制台输出,发现机器人并没有将自己发送的消息存储到数据库

      于是我尝试使用MessagePostSendEvent事件,将原数据添加到数据库中
      但MessagePostSendEvent并不附带MessageSource,所以无法获取ids等信息

      我想要

      希望修复这个bug,让MessageEvent可以监听到机器人自己发送的消息

      PS:我测试用其他设备发送消息,MessageEvent可以监听到,但就是监听不到Mirai自己发的消息

      发布在 BUG反馈
      2
      2446694
    • javaWeb如何实现短信登录?

      前段时间使用了 2.15 实现了扫码登录

      (date: 2023-4-21)
      但扫码登录目前支持 ANDROID_WATCH 和 MACOS

      于是我想实现一 下短信登录:

      // MyLoginSolver.java
      @Override
          public Object onSolveDeviceVerification(@NotNull Bot bot, @NotNull DeviceVerificationRequests requests, @NotNull Continuation<? super DeviceVerificationResult> $completion) {
              DeviceVerificationRequests.SmsRequest sms = requests.getSms();
              if (requests.getPreferSms() && sms != null) {
                  sms.requestSms((Continuation<? super Unit>) $completion);
                  return verification(bot.getId(), String.format("请处理 %s %s 的短信验证码", sms.getCountryCode(), sms.getPhoneNumber()));
              } else {
                  DeviceVerificationRequests.FallbackRequest fallback = requests.getFallback();
                  assert fallback != null;
                  return verification(bot.getId(), fallback.getUrl());
              }
          }
      

      但我实现以后还是滑动验证码登录,而不是短信登录,我应该怎么做?

      发布在 开发交流
      2
      2446694
    • 【mirai-core】希望把登录过程中和事件监听中产生的异常直接抛出来

      使用模块:mirai-core

      希望把登录过程中(Bot.login)和事件监听中(Listener)产生的异常直接抛出来
      如果异常在内部发生了异常直接在内部处理了,外部不好判断内部具体的错误原因。

      如果把异常抛出,可以方便在开发过程中处理是那种异常导致是什么类型,从而可以做出不同的处理。

      如果你不想改变之前的代码,希望可以新增一个可以处理异常的方法
      如:
      Bot.login 还是原来不抛异常的方法
      Bot.loginAndThrow 是可以抛出异常的方法
      监听事件异常也类似

      发布在 BUG反馈
      2
      2446694
    • RE: Spring Boot maven工程如何实现扫码登录?

      @2446694 在 Spring Boot maven工程如何实现扫码登录? 中说:

      @guizaipiao

      我使用的依赖是 mirai-core 这一个

      以下是你提到的配置

      QQSission

      package com.session;
      
      import net.mamoe.mirai.Bot;
      import net.mamoe.mirai.BotFactory;
      import net.mamoe.mirai.auth.BotAuthorization;
      import net.mamoe.mirai.contact.*;
      import net.mamoe.mirai.event.EventChannel;
      import net.mamoe.mirai.event.events.BotEvent;
      import net.mamoe.mirai.utils.BotConfiguration;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      import java.util.function.Consumer;
      
      
      /**
       * ContactOrBot	Contact 和 Bot 的公共接口	2.0
       * OtherClient	Bot 的其他客户端,如 “我的 iPad”,”我的电脑”	2.0
       * Bot	机器人对象	2.0
       * Contact	联系人对象,即所有的群,好友,陌生人,群成员等	2.0
       * Group	群对象	2.0
       * User	用户对象,即 “个人”. 包含好友,陌生人,群成员,临时会话用户	2.0
       * Friend	好友对象	2.0
       * Stranger	陌生人对象	2.0
       * Member	群成员对象,属于一个 Group.	2.0
       * NormalMember	普通群成员对象.	2.0
       * AnonymousMember	匿名群成员对象.	2.0
       */
      
      
      public class QqSession {
          private static final Logger logger = LoggerFactory.getLogger(QqSession.class);
          private final Bot bot;
          private final Consumer<Object> doRequest;
          private Consumer<Object> doResponse;
      
          public QqSession(Long qq, String password, Consumer<Object> doRequest) {
              // 使用自定义配置
              BotConfiguration botConfiguration = new QqBotConfiguration(qq);
              // 定义属性
              this.bot = BotFactory.INSTANCE.newBot(qq, password, botConfiguration);
              // 验证信息处理
              this.doRequest = doRequest;
          }
      
          public QqSession(Long qq, BotAuthorization credential, Consumer<Object> doRequest) {
              // 使用自定义配置
              BotConfiguration botConfiguration = new QqBotConfiguration(qq);
              // 二维码登录
              this.bot = BotFactory.INSTANCE.newBot(qq, credential, botConfiguration);
              // 验证信息处理
              this.doRequest = doRequest;
          }
      
          public Bot getBot() {
              return this.bot;
          }
      
          public boolean login() {
              this.bot.login();
              boolean isOnline = this.bot.isOnline();
              if (isOnline) logger.info(this.bot.getId() + " 登录成功");
              else logger.info(this.bot.getId() + " 登录失败");
              return isOnline;
          }
      
          public boolean isOnline() {
              return this.bot.isOnline();
          }
      
          public void close() {
              this.bot.close();
          }
      
          public Long getQq() {
              return this.bot.getId();
          }
      
          public ContactList<Friend> getFriends() {
              // 获取好友列表
              return this.bot.getFriends();
          }
      
          public ContactList<Group> getGroups() {
              // 获取群列表
              return this.bot.getGroups();
          }
      
          public Friend getFriend(Long id) {
              // 获取指定qq号好友
              return this.bot.getFriend(id);
          }
      
          public Group getGroup(Long id) {
              // 根据群号获取群
              return this.bot.getGroup(id);
          }
      
          public Stranger getStranger(Long id) {
              // 获取指定qq号陌生人
              return this.bot.getStranger(id);
          }
      
          public ContactList<OtherClient> getOtherClients() {
              // 联系其他客户端
              return this.bot.getOtherClients();
          }
      
          public EventChannel<BotEvent> getEventChannel() {
              return this.bot.getEventChannel();
          }
      
          public void sendRequest(Object request, Consumer<Object> doResponse) {
              this.doResponse = doResponse;
              // 发送验证请求
              this.doRequest.accept(request);
          }
      
      
          public void sendResponse(String response) {
              // 响应验证码
              doResponse.accept(response);
          }
      }
      
      

      QqSessionManager

      package com.session;
      
      import net.mamoe.mirai.auth.BotAuthorization;
      
      import java.util.HashMap;
      import java.util.Map;
      import java.util.function.Consumer;
      
      public class QqSessionManager {
          private static final Map<Long, QqSession> sessionMap = new HashMap<>();
      
          public static QqSession newQqSession(Long qq, Object credential, Consumer<Object> doRequest) {
              QqSession qqSession;
              if (credential instanceof BotAuthorization)
                  qqSession = new QqSession(qq, (BotAuthorization) credential, doRequest);
              else if (credential instanceof String)
                  qqSession = new QqSession(qq, (String) credential, doRequest);
              else throw new IllegalArgumentException("无效的credential");
              sessionMap.put(qq, qqSession);
              return qqSession;
          }
      
          public static QqSession getQqSession(Long qq) {
              return sessionMap.get(qq);
          }
      
          public static void removeQqSession(Long qq) {
              sessionMap.get(qq).close();
              sessionMap.remove(qq);
          }
      }
      
      

      Controller层实现

      @PostMapping("/login")
          public Result<Object> request(@RequestParam("qq") Long qq, @RequestParam(value = "pwd", required = false) String pwd) throws InterruptedException {
              Result<Object> result = new Result<>(); // 将url信息设置到result中
              QqSession[] qqSession = new QqSession[]{QqSessionManager.getQqSession(qq)};
              if (qqSession[0] == null || !qqSession[0].isOnline()) {
                  CountDownLatch latch = new CountDownLatch(1); // 定义一个CountDownLatch对象,用于等待result.setData
                  new Thread(() -> {
                      if (pwd == null) {
                          result.setCode(220);
                          qqSession[0] = QqSessionManager.newQqSession(qq, BotAuthorization.byQRCode(), object -> {
                              byte[] bytes = (byte[]) object;
                              String base64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(bytes);
                              result.setData(base64Image, "请扫码");  // 将图片设置到result中
                              latch.countDown();
                          });
                      } else {
                          result.setCode(210);
                          qqSession[0] = QqSessionManager.newQqSession(qq, pwd, object -> {
                              if (object instanceof byte[]) {
                                  byte[] bytes = (byte[]) object;
                                  String base64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(bytes);
                                  result.setData(base64Image, "请处理验证码");  // 将图片设置到result中
                              } else result.setData(object, "请处理url"); // 将url信息设置到result中
                              latch.countDown();
                          });
                      }
                      result.setCode(200).setData(qqSession[0].login(),"登录成功");
                      latch.countDown();
                  }).start();
                  latch.await(10000, TimeUnit.MILLISECONDS);  // 调用CountDownLatch对象的await方法等待url信息被设置
              } else {
                  result.setCode(200).setData(qqSession[0].isOnline(), "已经登录过了");
              }
              return result; // 返回result对象给前端
          }
      

      Result类

      package com.domain;
      
      import java.util.HashMap;
      import java.util.Map;
      
      public class Result<T> {
          static {
              Result.codeMap = new HashMap<>();
              Result.codeMap.put(100, "查询失败,没有找到相关数据");
              Result.codeMap.put(110, "添加失败,无法添加该数据");
              Result.codeMap.put(120, "删除失败,相关数据不存在");
              Result.codeMap.put(130, "修改失败,相关数据不存在");
      
              Result.codeMap.put(200, "登录失败");
              Result.codeMap.put(210, "验证码失效");
              Result.codeMap.put(220, "二维码失效");
              Result.codeMap.put(230, "短信验证失效");
              Result.codeMap.put(290, "登出失败");
      
              Result.codeMap.put(900, "请求数据有误");
              Result.codeMap.put(910, "系统繁忙,请稍后再试");
              Result.codeMap.put(990, "发生未知的错误,暂时无法处理");
          }
      
          private static Map<Integer, String> codeMap;
      
          private int code;
          private String msg;
          private T data;
      
          public Result() {
          }
      
          public Result(int code) {
              // 设置十位数上的值
              this.code = code;
              this.msg = codeMap.get(code);
          }
      
          public int getCode() {
              return code;
          }
      
          public Result<T> setCode(int code) {
              this.code = code;
              this.msg = codeMap.get(code);
              return this;
          }
      
          public String getMsg() {
              return msg;
          }
      
          public Result<T> setErrorMsg(String errorMsg) {
              // 如果代码为0,则表示异常或失败,设置错误信息
              if (this.code % 10 == 0) this.msg = errorMsg;
              return this;
          }
      
          public T getData() {
              return data;
          }
      
          public Result<T> setData(T data) {
              // 改变个位数上的值
              if (notNone(data) && this.code / 100 != 9) {
                  this.code = this.code / 10 * 10 + 1;
                  this.msg = "操作成功";
              }
              this.data = data;
              return this;
          }
      
          public Result<T> setData(T data, String msg) {
              // 改变个位数上的值
              if (notNone(data) && this.code / 100 != 9) {
                  this.code = this.code / 10 * 10 + 1;
                  this.msg = msg;
              }
              this.data = data;
              return this;
          }
      
          private boolean notNone(Object value) {
              // Character(char(\u0000)) 会被 instanceof Number == 0 处理
              return value instanceof Boolean ? (Boolean) value : value instanceof Number ? value != (Number) 0 : value instanceof String ? value != "" : value != null;
          }
      
          @Override
          public String toString() {
              return "Result{code=" + code + ", msg=" + msg + ", data=" + data + '}';
          }
      }
      
      
      发布在 开发交流
      2
      2446694
    • RE: Spring Boot maven工程如何实现扫码登录?

      @guizaipiao

      我使用的依赖是 mirai-core 这一个

      以下是你提到的配置

      QQSission

      package com.session;
      
      import net.mamoe.mirai.Bot;
      import net.mamoe.mirai.BotFactory;
      import net.mamoe.mirai.auth.BotAuthorization;
      import net.mamoe.mirai.contact.*;
      import net.mamoe.mirai.event.EventChannel;
      import net.mamoe.mirai.event.events.BotEvent;
      import net.mamoe.mirai.utils.BotConfiguration;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      import java.util.function.Consumer;
      
      
      /**
       * ContactOrBot	Contact 和 Bot 的公共接口	2.0
       * OtherClient	Bot 的其他客户端,如 “我的 iPad”,”我的电脑”	2.0
       * Bot	机器人对象	2.0
       * Contact	联系人对象,即所有的群,好友,陌生人,群成员等	2.0
       * Group	群对象	2.0
       * User	用户对象,即 “个人”. 包含好友,陌生人,群成员,临时会话用户	2.0
       * Friend	好友对象	2.0
       * Stranger	陌生人对象	2.0
       * Member	群成员对象,属于一个 Group.	2.0
       * NormalMember	普通群成员对象.	2.0
       * AnonymousMember	匿名群成员对象.	2.0
       */
      
      
      public class QqSession {
          private static final Logger logger = LoggerFactory.getLogger(QqSession.class);
          private final Bot bot;
          private final Consumer<Object> doRequest;
          private Consumer<Object> doResponse;
      
          public QqSession(Long qq, String password, Consumer<Object> doRequest) {
              // 使用自定义配置
              BotConfiguration botConfiguration = new QqBotConfiguration(qq);
              // 定义属性
              this.bot = BotFactory.INSTANCE.newBot(qq, password, botConfiguration);
              // 验证信息处理
              this.doRequest = doRequest;
          }
      
          public QqSession(Long qq, BotAuthorization credential, Consumer<Object> doRequest) {
              // 使用自定义配置
              BotConfiguration botConfiguration = new QqBotConfiguration(qq);
              // 二维码登录
              this.bot = BotFactory.INSTANCE.newBot(qq, credential, botConfiguration);
              // 验证信息处理
              this.doRequest = doRequest;
          }
      
          public Bot getBot() {
              return this.bot;
          }
      
          public boolean login() {
              this.bot.login();
              boolean isOnline = this.bot.isOnline();
              if (isOnline) logger.info(this.bot.getId() + " 登录成功");
              else logger.info(this.bot.getId() + " 登录失败");
              return isOnline;
          }
      
          public boolean isOnline() {
              return this.bot.isOnline();
          }
      
          public void close() {
              this.bot.close();
          }
      
          public Long getQq() {
              return this.bot.getId();
          }
      
          public ContactList<Friend> getFriends() {
              // 获取好友列表
              return this.bot.getFriends();
          }
      
          public ContactList<Group> getGroups() {
              // 获取群列表
              return this.bot.getGroups();
          }
      
          public Friend getFriend(Long id) {
              // 获取指定qq号好友
              return this.bot.getFriend(id);
          }
      
          public Group getGroup(Long id) {
              // 根据群号获取群
              return this.bot.getGroup(id);
          }
      
          public Stranger getStranger(Long id) {
              // 获取指定qq号陌生人
              return this.bot.getStranger(id);
          }
      
          public ContactList<OtherClient> getOtherClients() {
              // 联系其他客户端
              return this.bot.getOtherClients();
          }
      
          public EventChannel<BotEvent> getEventChannel() {
              return this.bot.getEventChannel();
          }
      
          public void sendRequest(Object request, Consumer<Object> doResponse) {
              this.doResponse = doResponse;
              // 发送验证请求
              this.doRequest.accept(request);
          }
      
      
          public void sendResponse(String response) {
              // 响应验证码
              doResponse.accept(response);
          }
      }
      
      

      QqSessionManager

      package com.session;
      
      import net.mamoe.mirai.auth.BotAuthorization;
      
      import java.util.HashMap;
      import java.util.Map;
      import java.util.function.Consumer;
      
      public class QqSessionManager {
          private static final Map<Long, QqSession> sessionMap = new HashMap<>();
      
          public static QqSession newQqSession(Long qq, Object credential, Consumer<Object> doRequest) {
              QqSession qqSession;
              if (credential instanceof BotAuthorization)
                  qqSession = new QqSession(qq, (BotAuthorization) credential, doRequest);
              else if (credential instanceof String)
                  qqSession = new QqSession(qq, (String) credential, doRequest);
              else throw new IllegalArgumentException("无效的credential");
              sessionMap.put(qq, qqSession);
              return qqSession;
          }
      
          public static QqSession getQqSession(Long qq) {
              return sessionMap.get(qq);
          }
      
          public static void removeQqSession(Long qq) {
              sessionMap.get(qq).close();
              sessionMap.remove(qq);
          }
      }
      
      
      发布在 开发交流
      2
      2446694
    • RE: Spring Boot maven工程如何实现扫码登录?

      @abc408880155 createQRCodeLoginListener来获取二维码。

      // 自定义LoginSolver
      public class QqLoginSolver extends LoginSolver {
          private Object verification(Long qq, Object request) {
              QqSession qqSession = QqSessionManager.getQqSession(qq);
              Object[] code = new Object[1];
              CountDownLatch latch = new CountDownLatch(1); // 定义一个CountDownLatch对象,用于等待code[0]
              qqSession.sendRequest(request, response -> {
                  code[0] = response;
                  latch.countDown();
              });
              try {
                  latch.await(300000, TimeUnit.MILLISECONDS);
              } catch (InterruptedException e) {
                  // 错误处理
              }
              return code[0];
          }
      
          @Nullable
          @Override
          public Object onSolvePicCaptcha(@NotNull Bot bot, @NotNull byte[] bytes, @NotNull Continuation<? super String> continuation) {
              return verification(bot.getId(), bytes);
          }
      
          @Nullable
          @Override
          public Object onSolveSliderCaptcha(@NotNull Bot bot, @NotNull String url, @NotNull Continuation<? super String> continuation) {
              return verification(bot.getId(), url);
          }
      
          @NotNull
          @Override
          public QRCodeLoginListener createQRCodeLoginListener(@NotNull Bot bot) {
              return new QRCodeLoginListener() {
      
                  @Override
                  public void onStateChanged(@NotNull Bot bot1, @NotNull State state) throws LoginFailedException {
                      if (state.name().equals("TIMEOUT")) throw new RuntimeException("二维码已失效");
                  }
      
                  @Override
                  public void onFetchQRCode(@NotNull Bot bot1, @NotNull byte[] bytes) {
                      QqSessionManager.getQqSession(bot1.getId()).sendRequest(bytes, null);
                  }
              };
          }
      }
      
      发布在 开发交流
      2
      2446694
    • RE: Spring Boot maven工程如何实现扫码登录?

      @abc408880155 确实可以用,不过我项获取二维码图片发送到前端验证

      发布在 开发交流
      2
      2446694
    • Spring Boot maven工程如何实现扫码登录?

      问题出现

      以下是在工程里的相关配置
      newBotConfiguration方法会生成自己定义的配置
      我在登录的时候提示需要二维码登录
      0536152e-6f62-40ed-8274-ac6cdcdbd031-image.png
      我找到了mirai-login-solver-sakura插件,但我不知道在SpringBoot中如何使用它?
      18287a49-4e78-4c9b-9622-3befaf98e235-image.png fe7ce264-7b35-477e-b4b3-aa7fb4b3db15-image.png

      需求

      • 如何在SpringBoot工程中使用mirai-login-solver-sakura(mirai console插件)
      • 如何实现二维码登录 或 短信验证码登录?
      发布在 开发交流
      2
      2446694
    • 1
    • 2
    • 2 / 2