From 629ac88c69f7fb1262c0cc7d194abe6686c62a85 Mon Sep 17 00:00:00 2001 From: NetRiceCake Date: Thu, 11 Dec 2025 02:53:24 +0900 Subject: [PATCH] asdf --- README.md | 84 +++++---- ex.png | Bin 59112 -> 81246 bytes .../java/com/github/netricecake/Main.java | 76 +++------ .../github/netricecake/kakao/KakaoApi.java | 6 +- .../kakao/LocoSocketHandlerImpl.java | 124 ++++---------- .../github/netricecake/kakao/TalkClient.java | 159 ++++++++++++++---- .../github/netricecake/kakao/TalkHandler.java | 10 +- .../{ => kakao}/loco/LocoPacket.java | 16 +- .../{ => kakao}/loco/LocoSocket.java | 8 +- .../{ => kakao}/loco/LocoSocketHandler.java | 2 +- .../{ => kakao}/loco/codec/LocoCodec.java | 10 +- .../loco/codec/SecureLayerCodec.java | 6 +- .../loco/crypto/CryptoManager.java | 4 +- .../{loco => kakao}/packet/InboundPacket.java | 2 +- .../kakao/packet/inbound/etc/PingIn.java | 6 + .../packet/inbound/login/CheckInIn.java | 6 +- .../packet/inbound/login/GetConfIn.java | 6 +- .../packet/inbound/login/LoginListIn.java | 6 +- .../packet/inbound/member/DelMemIn.java | 8 +- .../packet/inbound/member/GetMemberIn.java | 8 +- .../kakao/packet/inbound/member/MemberIn.java | 45 +++++ .../packet/inbound/member/NewMemIn.java | 8 +- .../packet/inbound/member/SyncLinkPfIn.java | 43 +++++ .../packet/inbound/message/MessageIn.java | 11 +- .../packet/inbound/message/PostIn.java | 6 +- .../packet/inbound/message/ShipIn.java | 8 +- .../packet/inbound/message/WriteIn.java | 8 +- .../kakao/packet/inbound/room/ChatInfoIn.java | 36 ++++ .../packet/inbound/room/InfoLinkIn.java | 8 +- .../kakao/packet/outbound/etc/PingOut.java | 11 ++ .../packet/outbound/login/CheckInOut.java | 4 +- .../packet/outbound/login/GetConfOut.java | 4 +- .../packet/outbound/login/LoginListOut.java | 12 +- .../packet/outbound/member/GetMemberOut.java | 4 +- .../packet/outbound/member/KickMemberOut.java | 32 ++++ .../packet/outbound/member/MemberOut.java | 4 +- .../outbound/member/PardonMemberOut.java | 26 +++ .../packet/outbound/message/MessageOut.java | 4 +- .../packet/outbound/message/PostOut.java | 4 +- .../packet/outbound/message/ShipOut.java | 4 +- .../packet/outbound/message/WriteOut.java | 13 +- .../packet/outbound/room/ChatInfoOut.java | 4 +- .../packet/outbound/room/InfoLinkOut.java | 4 +- .../netricecake/kakao/structs/ChatRoom.java | 61 ++++++- .../kakao/structs/ChatRoomType.java | 11 ++ .../netricecake/kakao/structs/Member.java | 40 ++++- .../netricecake/kakao/structs/MemberType.java | 10 ++ .../netricecake/kakao/structs/Message.java | 33 +++- .../kakao/structs/MessageType.java | 14 ++ .../{loco => kakao}/util/BsonUtil.java | 2 +- .../{loco => kakao}/util/ByteUtil.java | 2 +- .../netricecake/kakao/util/ImageUtil.java | 63 +++++++ .../loco/packet/inbound/etc/PingIn.java | 6 - .../loco/packet/inbound/member/MemberIn.java | 26 --- .../packet/inbound/member/SyncLinkPfIn.java | 29 ---- .../loco/packet/inbound/room/ChatInfoIn.java | 32 ---- .../loco/packet/outbound/etc/PingOut.java | 11 -- 57 files changed, 747 insertions(+), 443 deletions(-) rename src/main/java/com/github/netricecake/{ => kakao}/loco/LocoPacket.java (63%) rename src/main/java/com/github/netricecake/{ => kakao}/loco/LocoSocket.java (95%) rename src/main/java/com/github/netricecake/{ => kakao}/loco/LocoSocketHandler.java (81%) rename src/main/java/com/github/netricecake/{ => kakao}/loco/codec/LocoCodec.java (93%) rename src/main/java/com/github/netricecake/{ => kakao}/loco/codec/SecureLayerCodec.java (91%) rename src/main/java/com/github/netricecake/{ => kakao}/loco/crypto/CryptoManager.java (97%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/InboundPacket.java (95%) create mode 100644 src/main/java/com/github/netricecake/kakao/packet/inbound/etc/PingIn.java rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/login/CheckInIn.java (87%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/login/GetConfIn.java (78%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/login/LoginListIn.java (90%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/member/DelMemIn.java (76%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/member/GetMemberIn.java (65%) create mode 100644 src/main/java/com/github/netricecake/kakao/packet/inbound/member/MemberIn.java rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/member/NewMemIn.java (76%) create mode 100644 src/main/java/com/github/netricecake/kakao/packet/inbound/member/SyncLinkPfIn.java rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/message/MessageIn.java (77%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/message/PostIn.java (68%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/message/ShipIn.java (74%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/message/WriteIn.java (56%) create mode 100644 src/main/java/com/github/netricecake/kakao/packet/inbound/room/ChatInfoIn.java rename src/main/java/com/github/netricecake/{loco => kakao}/packet/inbound/room/InfoLinkIn.java (61%) create mode 100644 src/main/java/com/github/netricecake/kakao/packet/outbound/etc/PingOut.java rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/login/CheckInOut.java (89%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/login/GetConfOut.java (83%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/login/LoginListOut.java (86%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/member/GetMemberOut.java (76%) create mode 100644 src/main/java/com/github/netricecake/kakao/packet/outbound/member/KickMemberOut.java rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/member/MemberOut.java (85%) create mode 100644 src/main/java/com/github/netricecake/kakao/packet/outbound/member/PardonMemberOut.java rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/message/MessageOut.java (53%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/message/PostOut.java (93%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/message/ShipOut.java (86%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/message/WriteOut.java (79%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/room/ChatInfoOut.java (76%) rename src/main/java/com/github/netricecake/{loco => kakao}/packet/outbound/room/InfoLinkOut.java (80%) create mode 100644 src/main/java/com/github/netricecake/kakao/structs/ChatRoomType.java create mode 100644 src/main/java/com/github/netricecake/kakao/structs/MemberType.java create mode 100644 src/main/java/com/github/netricecake/kakao/structs/MessageType.java rename src/main/java/com/github/netricecake/{loco => kakao}/util/BsonUtil.java (96%) rename src/main/java/com/github/netricecake/{loco => kakao}/util/ByteUtil.java (97%) create mode 100644 src/main/java/com/github/netricecake/kakao/util/ImageUtil.java delete mode 100644 src/main/java/com/github/netricecake/loco/packet/inbound/etc/PingIn.java delete mode 100644 src/main/java/com/github/netricecake/loco/packet/inbound/member/MemberIn.java delete mode 100644 src/main/java/com/github/netricecake/loco/packet/inbound/member/SyncLinkPfIn.java delete mode 100644 src/main/java/com/github/netricecake/loco/packet/inbound/room/ChatInfoIn.java delete mode 100644 src/main/java/com/github/netricecake/loco/packet/outbound/etc/PingOut.java diff --git a/README.md b/README.md index e6929b8..036fb56 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ 안드로이드 카카오톡 25.9.2 기반 비공식 카카오톡 클라이언트 (태블릿 서브 디바이스 로그인) -절대 본계정으로 돌려보지마세요. +되도록이면 부계정으로 돌리길 추천합니다. -**device uuid 무조건 바꾸시오.** +예제에 있는 uuid 그대로 쓰지 마세요. + +자바 21 이상에서 작동합니다. ## Example @@ -15,58 +17,50 @@ Main.java 파일 참고 TalkClient client = new TalkClient(email, password, deviceName, deviceUuid, new TalkHandler() { @Override public void onMessage(Message msg) { - if (msg.getType() != 1) return; // 1이 그냥 채팅, 그냥 채팅만 받기 - if (msg.getMessage().equals("!send")) { - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), "방 : " + msg.getChatRoom().getName() + "\n보낸사람 : " + msg.getAuthor().getName()); - } else if (msg.getMessage().equals("!reply")) { // 답장 - int replyType = 26; // 답장 타입 - JsonObject extraObject = new JsonObject(); - extraObject.addProperty("src_logId", msg.getLogId()); - extraObject.addProperty("src_userId", msg.getAuthor().getId()); - extraObject.addProperty("src_message", msg.getMessage()); - extraObject.addProperty("src_type", msg.getType()); - extraObject.addProperty("src_linkId", msg.getChatRoom().getLinkId()); - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), replyType, "reply test", extraObject.toString()); - } else if (msg.getMessage().equals("!mention")) { // 멘션 - JsonObject extraObject = new JsonObject(); - JsonArray mentionArray = new JsonArray(); - JsonObject mentionObject = new JsonObject(); - mentionObject.addProperty("user_id", msg.getAuthor().getId()); - JsonArray pos = new JsonArray(); - pos.add(1); - mentionObject.add("at", pos); - mentionObject.addProperty("len", msg.getAuthor().getName().length()); - mentionArray.add(mentionObject); - extraObject.add("mentions", mentionArray); - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), 1, "@" + msg.getAuthor().getName(), extraObject.toString()); - } else if (msg.getMessage().equals("!image")) { - byte[] imageBytes = ByteUtil.hexStringToByteArray("FFD8FFE000104A46494600010101006000600000FFDB0043000201010201010202020202020202030503030303030604040305070607070706070708090B0908080A0807070A0D0A0A0B0C0C0C0C07090E0F0D0C0E0B0C0C0CFFDB004301020202030303060303060C0807080C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC00011080080008003012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00FDFCA28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28AFC03F811F03FF69AFF0082C67FC14A3F6CED1749FDB3BE2F7C15D13E0A7C429F47D374ED16E2FA6B392D64BFD52DE08A38A0BFB5484451E9E80E03190C858E1812C01FBF9593E0DF1F685F1174D9AF7C3DAD693AED9DB5CCB6734FA75E47751453C4DB6489990901D1B8653C83C102BC67FE09BDFB24F8F3F62BFD9C8782BE227C6CF157C7BD793539EF63F12F882DDA1BB8A0758C25A8DF3CF232214760D24AED995870A1547E77FF00C19B1E263E0CFD95FE3CFC1ED76DB51D37E217C39F89735E78874FBA88A9B1FB4DA4168885B3CC827D2EF1597F8760FEF5007E8C7ECA7FF0514F869FB667C6BF8C9E00F03DEEA975E20F815AE2787FC50B7564D042972CF711FEE5C9FDE2896D2E109C0E6227054AB37BA57E247EC3CDA27EC63FF077F7ED09E028E4D7B4AD23E33F87AE353D22D6532C96FAB6AB73058EB77131E8BB15935708E7210EE8C1C922BF407FE0AE5FF057FF00871FF0497F80F36BDE24B9B6D67C6FAB42CBE19F09C370AB79ABCBC81238E4C76C8DF7E523031B577390A403DB7C25FB617C30F1E7ED23E21F841A378DB43D4FE25F84F4E4D5B57F0FDBCC5EEB4FB666440EF81B461A48832E772F9B1EE037AE7D26BF273FE0D93FD823C67E171F15BF6B2F8C9A19D23E2A7ED11AA4FA858DB4D6FE44961A55CCFF006D96454DD98D6EAE5D5846E32B1D9C0C0E1C8AFD63A0028AFC2BF097FC1CF7E23FD97FFE0A2DFB50D9FC78BCD635EF841E00F185E782FC2BE1EF0AF85EDA4BFB5B98AFEEA18666BA92485361B7B198C8B34CCEF24AA625091C807AB7FC46ADFB2C7FD083FB407FE08F48FF00E59D007EBF515F9E3FF0496FF83863C23FF0575FDAA7C71F0F7C1FF0CFC5FE18D1FC2DA1FF006F59EBBAB5CC2E6F6313C103453C11065B794B4F945134A1D6290E576E2BF43A800A28A2800A28A2800AFE69BF647FD90BF6ABFDA47FE0AD3FB707887F658F8D3A67C27D73C0DF176FDB59B5D5AFEE61D375C8EE755D6FC969A18EDEE61B83098240A93C2CA3ED0C415390DFD2CD7E40FC4DFF00834EAD3E26FEDDFE30F8B0FF00B4578C746F0978E7C77278EB54F0A695A335A5CB4EF7335C044BF4BC015E37B89C4737D9CBC6B2B01C92C403A6BA3FF056CFD96BE04DCDB6CF80DFB49F8D75BD502C1776F241A6B7876CD616DCCC8EBA5C3333C8C9B7018C7E51DC24127EEFE79FF83587C49F113E04FF00C150FF006B8F841F1BF43D534FF8D1E2FB3B2F1BF88249E5B79152782EA479CBB42CD1B19CEBB04A8D1128543107056BF77ABF193E18F8B2F3F676FF0083D0FE2259EBDA1EA090FC79F87B158786EE81511C9141A4E9D70F72727263F3342BD838E7CC038C026800FF0082EF7856FF00E087FC17E7FE09F3F16BC3BAE5ED8EBBE35D7EDFC07770A227971D845AADB47300482499E0D7AEA27F45518C139AF60FDB2FFE0D4CF807FB6A7C7BF1EFC4EF1078EFE3459F8BBC75732DF3797AD59DC5869B3BE0AF951CB68D2F92A4604466C042554A00BB7C7FFE0F2BF0ADFF00C3EF80DFB3BFC75F0F6B97BA378C7E167C42363A2B40885629AEEDFEDCB739607E78A5D1A0DA3041F31B3D057B27ED77FF00075D7ECE5FB197ED27E2FF0085DE23F097C69D575FF04EA0FA66A171A5E85622D1A64FBC233717B0C8CB9E8FE585618652CA43100F8EB505FDBA7FE0D98D734EBABAD5350FDA7BF65EB3F344D0C31DC13A1DAA2801A5678E69349009CA85925B538C13BD801FB43FB09FED8FE18FF8280FEC97E0BF8C1E0E86FEDB40F1A5A493436F7B1ECB8B59619E4B79E17C704C73C32A6E1C36DC8E08AFCD4D57FE0F41FD93F5DD2EE6C6FBE1C7C78BCB2BC89A0B8B79FC3FA3C914F1B02AC8EA7522194824107820D751FF00047BFF0082D0789BFE0A1BFB65CBE00F815FB3F68DE06FD92FC11A5BC53EA92D9A6997BA2CE6277863486DA46B35F326F945B4419821794C9C6DA00F953F62EFF829C7803FE08B5FF053DFF828BB7C68D27C6B16A3E2CF1F45AEE91A668DA5ADD5D5E5A36A7A9CC92E5E48E24578755B3954C8EA1964E0EEC29FBCBE047FC1D55FB16FC6AD274D7BFF00889AC7C3FD5752B8FB3AE95E28F0F5E4535B92D85796E2D927B44439CEE33E00FBDB6BC53FE0BCFF00F04E6F8A9F073F6C0F08FEDE3FB3669F0EA9F103E1D4313F8BBC3E96E649359B5B789E26BADAAC1E60D66C6D668D0893C95428432B1AE3BF66EFDB17FE0965FF000554F83961A7FC57F879F03BE127C43D641D47C43617FA6AF84E54BB46DD2491EB96EB6E24491C960A6E43B8387426803F57FE0EFEDD1F04BF689F159D07E1FF00C62F857E3AD7044D39D3BC3DE2CB0D4EEC46BF79FCA82567DA3B9C6057AA57F343FF000538FD82BFE09FEFFB6AFECB1F0DFF0067FD42DF55B3F8B7E2C8FC35E2A93E1FFC4B8F598F48827BBB3B686776B917FB6766BA7651BD14ADB38284B075FD5BFF008255FF00C1BF3E12FF008247FED4FE2DF1D7803E27F8EB5EF0AF89FC36BA20F0CEBA9039867FB443335E493C2228E56021D918FB3A945965CBB6EE003F40E8A28A0028A28A0028A28A002BF2ABFE0A5FFF0004E5FDA1FE2C7FC1C01FB317ED07F0A74AB67F02F8234FD2F47F146AE356B4B7974DB48F53BF7D4236825712C8B3585F4912F948E496607670D5FAAB45007C63FF0005DBFF00825BEA7FF056EFD8757E1CF87FC47A7F867C4FA16BF6FE26D1A7D415CD85CDCC305CDBF9170C8ACE91B477527CE8AC55954ED61907E9FF00D9F7C2BE26F02FC05F04689E35D723F13F8CB46D02C2C75ED6635DA9AB5FC56F1A5CDC81818124AAEF8C0FBDD0575F450014515F991FB5DFECC3FF00054BF1B7ED27E2FD4FE10FED1BF033C23F0CEEF5077F0E6937BA4466EECACFFE59A4C64D1EE98CA07DE6F39831C9010108A01FA6F5F2DFED53FF000450FD957F6D3F109D63E227C12F07EA5ADCB7525EDCEA9A6ACDA1DFEA13480067B9B8B192096E49C0FF005CCF83C8C126BE09F007ED07FF0005A1F853A1BE87A8FC0CF837F132E2CAE2551E21D56FF4AB79EFD3710AC12D756B38C26065736E8F83F30CF00D3FFE0B6DFF000515FD9C7C79A8E87F18BF607D4FC7339B78A6B46F8756BA97D960DD93F3DE5BFF006ADBCA703EE2B2329FBDD71401F6C7ECD1FF00040AFD917F640F8CBA4FC40F87FF000734FD27C5DA0B349A75F5DEB7AA6A82CE4231E624577732C4241FC2FB7729E54835F6157E40FF00C4477FB53FFD231FF680FF00BFDABFFF0028E8FF00888EFF006A7FFA463FED01FF007FB57FFE51D007EBF515F987FB27FF00C1777F685F8FBFB46F83BC17E2AFF827D7C75F879A0789B53874FBCF12DD9BF7B5D112460A6E66F3F4BB78C4499DCC4CAA7683B433614FE9E500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145007FFFD9"); // 테스트 jpg 이미지 hex - getTalkClient().sendJpg(msg.getChatRoom().getChatId(), imageBytes, "jpg", 128, 128); + if (msg.getType() != MessageType.TEXT) return; // 그냥 텍스트 채팅만 받기 + if (msg.getMessage().equals("!count")) { // 멤버 수 + msg.getChatRoom().sendMessage("멤버수 : " + msg.getChatRoom().getMemberCount()); + } + else if (msg.getMessage().equals("!type")) { // 보낸 사람 권한 + int type = msg.getAuthor().getMemberType(); + String t = ""; + if (type == MemberType.OWNER) t = "방장"; + if (type == MemberType.ADMIN) t = "부방장"; + if (type == MemberType.MEMBER) t = "일반 멤버"; + if (type == MemberType.BOT) t = "방장봇"; + msg.getChatRoom().sendMessage("당신의 멤버 타입 : " + t); + } + else if (msg.getMessage().equals("!kick")) { // 강퇴 (당연히 방장이나 부방장 권한 있을때만 작동합니다.) + msg.getAuthor().kick(); + } + else if (msg.getMessage().equals("!send")) { // 일반 메세지 + msg.getChatRoom().sendMessage("방 : " + msg.getChatRoom().getName() + "\n보낸사람 : " + msg.getAuthor().getNickName()); + } + else if (msg.getMessage().equals("!reply")) { // 답장 + msg.reply("reply test"); + } + else if (msg.getMessage().equals("!mention")) { // 멘션 + String extra = "{\"mentions\":[{\"user_id\":" + msg.getAuthor().getUserId() + ",\"at\":[1],\"len\":" + msg.getAuthor().getNickName(length() + "}]}"; + msg.getChatRoom().sendMessage("@" + msg.getAuthor().getNickName(), extra); + } + else if (msg.getMessage().equals("!jpg")) { // jpg 사진 전송, jpeg말고 다른 포멧은 테스트 안해봤습니다. + byte[] imageBytes = ByteUtil.hexStringToByteArray("FFD8FFE000104A46494600010101006000600000FFDB0043000201010201010202020202020202030503030303030604040305070607070706070708090B0908080A0807070A0D0A0A0B0C0C0C0C07090E0F0D0C0E0B0C0C0CFFDB004301020202030303060303060C0807080C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC00011080080008003012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00FDFCA28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28AFC03F811F03FF69AFF0082C67FC14A3F6CED1749FDB3BE2F7C15D13E0A7C429F47D374ED16E2FA6B392D64BFD52DE08A38A0BFB5484451E9E80E03190C858E1812C01FBF9593E0DF1F685F1174D9AF7C3DAD693AED9DB5CCB6734FA75E47751453C4DB6489990901D1B8653C83C102BC67FE09BDFB24F8F3F62BFD9C8782BE227C6CF157C7BD793539EF63F12F882DDA1BB8A0758C25A8DF3CF232214760D24AED995870A1547E77FF00C19B1E263E0CFD95FE3CFC1ED76DB51D37E217C39F89735E78874FBA88A9B1FB4DA4168885B3CC827D2EF1597F8760FEF5007E8C7ECA7FF0514F869FB667C6BF8C9E00F03DEEA975E20F815AE2787FC50B7564D042972CF711FEE5C9FDE2896D2E109C0E6227054AB37BA57E247EC3CDA27EC63FF077F7ED09E028E4D7B4AD23E33F87AE353D22D6532C96FAB6AB73058EB77131E8BB15935708E7210EE8C1C922BF407FE0AE5FF057FF00871FF0497F80F36BDE24B9B6D67C6FAB42CBE19F09C370AB79ABCBC81238E4C76C8DF7E523031B577390A403DB7C25FB617C30F1E7ED23E21F841A378DB43D4FE25F84F4E4D5B57F0FDBCC5EEB4FB666440EF81B461A48832E772F9B1EE037AE7D26BF273FE0D93FD823C67E171F15BF6B2F8C9A19D23E2A7ED11AA4FA858DB4D6FE44961A55CCFF006D96454DD98D6EAE5D5846E32B1D9C0C0E1C8AFD63A0028AFC2BF097FC1CF7E23FD97FFE0A2DFB50D9FC78BCD635EF841E00F185E782FC2BE1EF0AF85EDA4BFB5B98AFEEA18666BA92485361B7B198C8B34CCEF24AA625091C807AB7FC46ADFB2C7FD083FB407FE08F48FF00E59D007EBF515F9E3FF0496FF83863C23FF0575FDAA7C71F0F7C1FF0CFC5FE18D1FC2DA1FF006F59EBBAB5CC2E6F6313C103453C11065B794B4F945134A1D6290E576E2BF43A800A28A2800A28A2800AFE69BF647FD90BF6ABFDA47FE0AD3FB707887F658F8D3A67C27D73C0DF176FDB59B5D5AFEE61D375C8EE755D6FC969A18EDEE61B83098240A93C2CA3ED0C415390DFD2CD7E40FC4DFF00834EAD3E26FEDDFE30F8B0FF00B4578C746F0978E7C77278EB54F0A695A335A5CB4EF7335C044BF4BC015E37B89C4737D9CBC6B2B01C92C403A6BA3FF056CFD96BE04DCDB6CF80DFB49F8D75BD502C1776F241A6B7876CD616DCCC8EBA5C3333C8C9B7018C7E51DC24127EEFE79FF83587C49F113E04FF00C150FF006B8F841F1BF43D534FF8D1E2FB3B2F1BF88249E5B79152782EA479CBB42CD1B19CEBB04A8D1128543107056BF77ABF193E18F8B2F3F676FF0083D0FE2259EBDA1EA090FC79F87B158786EE81511C9141A4E9D70F72727263F3342BD838E7CC038C026800FF0082EF7856FF00E087FC17E7FE09F3F16BC3BAE5ED8EBBE35D7EDFC07770A227971D845AADB47300482499E0D7AEA27F45518C139AF60FDB2FFE0D4CF807FB6A7C7BF1EFC4EF1078EFE3459F8BBC75732DF3797AD59DC5869B3BE0AF951CB68D2F92A4604466C042554A00BB7C7FFE0F2BF0ADFF00C3EF80DFB3BFC75F0F6B97BA378C7E167C42363A2B40885629AEEDFEDCB739607E78A5D1A0DA3041F31B3D057B27ED77FF00075D7ECE5FB197ED27E2FF0085DE23F097C69D575FF04EA0FA66A171A5E85622D1A64FBC233717B0C8CB9E8FE585618652CA43100F8EB505FDBA7FE0D98D734EBABAD5350FDA7BF65EB3F344D0C31DC13A1DAA2801A5678E69349009CA85925B538C13BD801FB43FB09FED8FE18FF8280FEC97E0BF8C1E0E86FEDB40F1A5A493436F7B1ECB8B59619E4B79E17C704C73C32A6E1C36DC8E08AFCD4D57FE0F41FD93F5DD2EE6C6FBE1C7C78BCB2BC89A0B8B79FC3FA3C914F1B02AC8EA7522194824107820D751FF00047BFF0082D0789BFE0A1BFB65CBE00F815FB3F68DE06FD92FC11A5BC53EA92D9A6997BA2CE6277863486DA46B35F326F945B4419821794C9C6DA00F953F62EFF829C7803FE08B5FF053DFF828BB7C68D27C6B16A3E2CF1F45AEE91A668DA5ADD5D5E5A36A7A9CC92E5E48E24578755B3954C8EA1964E0EEC29FBCBE047FC1D55FB16FC6AD274D7BFF00889AC7C3FD5752B8FB3AE95E28F0F5E4535B92D85796E2D927B44439CEE33E00FBDB6BC53FE0BCFF00F04E6F8A9F073F6C0F08FEDE3FB3669F0EA9F103E1D4313F8BBC3E96E649359B5B789E26BADAAC1E60D66C6D668D0893C95428432B1AE3BF66EFDB17FE0965FF000554F83961A7FC57F879F03BE127C43D641D47C43617FA6AF84E54BB46DD2491EB96EB6E24491C960A6E43B8387426803F57FE0EFEDD1F04BF689F159D07E1FF00C62F857E3AD7044D39D3BC3DE2CB0D4EEC46BF79FCA82567DA3B9C6057AA57F343FF000538FD82BFE09FEFFB6AFECB1F0DFF0067FD42DF55B3F8B7E2C8FC35E2A93E1FFC4B8F598F48827BBB3B686776B917FB6766BA7651BD14ADB38284B075FD5BFF008255FF00C1BF3E12FF008247FED4FE2DF1D7803E27F8EB5EF0AF89FC36BA20F0CEBA9039867FB443335E493C2228E56021D918FB3A945965CBB6EE003F40E8A28A0028A28A0028A28A002BF2ABFE0A5FFF0004E5FDA1FE2C7FC1C01FB317ED07F0A74AB67F02F8234FD2F47F146AE356B4B7974DB48F53BF7D4236825712C8B3585F4912F948E496607670D5FAAB45007C63FF0005DBFF00825BEA7FF056EFD8757E1CF87FC47A7F867C4FA16BF6FE26D1A7D415CD85CDCC305CDBF9170C8ACE91B477527CE8AC55954ED61907E9FF00D9F7C2BE26F02FC05F04689E35D723F13F8CB46D02C2C75ED6635DA9AB5FC56F1A5CDC81818124AAEF8C0FBDD0575F450014515F991FB5DFECC3FF00054BF1B7ED27E2FD4FE10FED1BF033C23F0CEEF5077F0E6937BA4466EECACFFE59A4C64D1EE98CA07DE6F39831C9010108A01FA6F5F2DFED53FF000450FD957F6D3F109D63E227C12F07EA5ADCB7525EDCEA9A6ACDA1DFEA13480067B9B8B192096E49C0FF005CCF83C8C126BE09F007ED07FF0005A1F853A1BE87A8FC0CF837F132E2CAE2551E21D56FF4AB79EFD3710AC12D756B38C26065736E8F83F30CF00D3FFE0B6DFF000515FD9C7C79A8E87F18BF607D4FC7339B78A6B46F8756BA97D960DD93F3DE5BFF006ADBCA703EE2B2329FBDD71401F6C7ECD1FF00040AFD917F640F8CBA4FC40F87FF000734FD27C5DA0B349A75F5DEB7AA6A82CE4231E624577732C4241FC2FB7729E54835F6157E40FF00C4477FB53FFD231FF680FF00BFDABFFF0028E8FF00888EFF006A7FFA463FED01FF007FB57FFE51D007EBF515F987FB27FF00C1777F685F8FBFB46F83BC17E2AFF827D7C75F879A0789B53874FBCF12DD9BF7B5D112460A6E66F3F4BB78C4499DCC4CAA7683B433614FE9E500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145007FFFD9"); + msg.getChatRoom().sendJpg(imageBytes); } } @Override public void onNewMember(ChatRoom room, Member member) { - JsonObject extraObject = new JsonObject(); - JsonArray mentionArray = new JsonArray(); - JsonObject mentionObject = new JsonObject(); - mentionObject.addProperty("user_id", member.getId()); - JsonArray pos = new JsonArray(); - pos.add(1); - mentionObject.add("at", pos); - mentionObject.addProperty("len", member.getName().length()); - mentionArray.add(mentionObject); - extraObject.add("mentions", mentionArray); - getTalkClient().sendMessage(room.getChatId(), 1, "@" + member.getName() + "님 안녕하세요.", extraObject.toString()); + String extra = "{\"mentions\":[{\"user_id\":" + member.getUserId() + ",\"at\":[1],\"len\":" + member.getNickName().length() + "}]}"; + room.sendMessage("@" + member.getNickName() + "님 안녕하세요.", extra); } @Override - public void onDelMember(ChatRoom room, Member member) { - getTalkClient().sendMessage(room.getChatId(), member.getName() + "님이 나갔습니다."); + public void onDelMember(ChatRoom room, long userId, String nickName) { + room.sendMessage(nickName + "님이 나갔습니다."); } }); ``` - ## Build ``` @@ -78,8 +72,6 @@ jar 파일은 build/libs 디렉터리 안에 생성됩니다. ## Usage -자바21 이상 필요합니다. - 첫 로그인시에 기기등록이 필요합니다. 콘솔창에 방법 나오니 따라하세요. -로그인하면 로그인 정보(토큰 등)가 email_deviceName 폴더 안에 저장됩니다. 서버 연결이 안되면 삭제하고 시도하세요. +로그인하면 로그인 정보(토큰 등)가 email_deviceName 포멧의 이름을 가진 폴더 안에 저장됩니다. 서버 연결이 안되면 삭제하고 시도하세요. diff --git a/ex.png b/ex.png index dcf7177efae6f310a245846c4c8b8466596bcedb..2acb4de749e9922734dd02100c2ca13b37263385 100644 GIT binary patch literal 81246 zcmb@tbx<5%^gWoM!9#Gj;2zuw4#6$B6Wm=VxCIaH?(Xg`gFAz}yAM10e1E%JwYz_8 zZEe*^O?OZCd#`U_Ip>}*MR`dSM0~^#A3mT+ONl9e`0#P&!v~n=PjHYed0f&JkgtzU z%90`D3Sx@*BZkO4I4X2h_fQ?~g-v#U>vG@u)S6Wu)+1l!*k#%vvCX=4wStNcl&r;w(o*wMOJea)WKjg+xtoq{SNZvySMK&LYx_!pVY^Z`#ih}O zgK+rAXwwTb{=kz2Qo2CybBokq;7LJ4OUmH0XKEV0l3JDryCJFHoQSqIy&MY4W4qoB zDOn(Qj{EAWg{66RMa4Y7)T1;hhlPzzPD2ZxT>KY1vcT@FA2v3&g$)e@{8Cb+D2odV zGTIU8G$Nl23n~i49SgC)#ypplD)<+F7IDsoYyqXDN|D}K*;vGG>yQN={w}nrXXi?b zS1|t~_12h!-COb)z_miBpb*Hajk^;AA+BHwE0Y5q{P7bzw$89U!G|#tC%av6ln3Bw{042J?yt)a`o~H`p9xDY{z)y{D4me( z!y6X6E)U)AYLw|o<}D3NPhJa)qy1fsI2h&Z5+y;Gu!t)-yEvhJJu0m76YeQIJKKE% z-EaH)9hq1W4{W_8n~+nEy|%q*&7IYp^q}v>S&laqOqDivU<(~p)F`nepMB$ z+IVU`K5IvkjI>WG@vQ65pJ-ko>fm8pL$4AFd^%ojOeaD%^In1uRl4;^ZW6LI;LOq| zC$o(X885eXx<-%=cl|g|%{;j?^X5n;z!H6g4X6Q?Tb7NEFjwPo;oWR>A`JdP0p+*p zxl;!GXsRA!&r~`K9@6}Y{irtDT5wW=LPA;m?&9Z?+G`NZCRiQC$>lpV+Nj93zi*Iz z=(#oVr(ElYbc09#p=){iK<+X&psY6witwT;^$i=1_l5g&3T~lm-ws1+N1|=hgz>YD zz?1zwgSvGwdo)#)Q7PsboHXfO7eCI`YTc;2lkZxOT<70t(DA@;R7aUBAPK7K85`^| zu`@kGj{7|W_CzE7U{Gpl-cBL$Q}%Q~J5(PK*SX_zG88^`GmDn%!X1E;GQOLWMuSM4 zHMGQY3sO99GU5;qCM|)V(k$QmRVcIxlzt{juH5CpmKGNHHOx2j86lsX3}SKzeg0me zT>Gn&h6mfZil~LoJQ2Tu-*zuWEV;^q!nVXcIqU?mUD@PJ!1tbP*Nq;sfK5FK?9`Bf z5^E$r8bdeP6ZB8ATY$+%GB{Il^s(xfh|bf)mmg?zIfNb>7T>pEs0e1DzOR>xk*!pl zux9Ctd<|%)fIU7rMLZXiBnL_3ZPbXDAe;Cu!Y^D@Z)X66`)>^|))+ufhFWN|e8MLW zk$&M4W;J}}y|HShd57Z{ujCKXkNgya3Nd+aSbIdA-J4-5n>Kwfa>kT}sK}Yzz^>>$ zqN8bsqKJ7Vo+~NR1mV=`OGGZuvxTkoGpqS?O^yhoR}Pm*Yg=de1CqhqYuQ7Iv_Row zG^!^*0)QrZgnHu3;B2NLUri{MbRnP0K(;-?~ zZD4o;i!V85nqU<|wN6%8-$b5EWi2`O1gEMF2DyA3MFOG4cCI>k*nLe$m~IrA=1sIg zR$py=J7Gyc?mCUpNUZqS$JB`Myofb@FZGGs=1~?jC;7S8wt%}>!lN2-$9!Id{4Y{L zpUIj2jisLc{~<=~5*@K#M$OeaN=WL8rgVlOH(>6x`%8$4XBogI43APL?!ePc8NA!% z#O~ccYpP3x)mE_nM6G@9AGF=@mlOSn{X$XxJxozNx7*XFiB1L@N&@?3zB$8idx>P< ziJY5w`u?L**Ug;fPdGMaJ7B5iDKT&Kg}P={R^C}O`AQ2Gc%r<8EarDNYrWutq3lVz z&@aS*Mn*2xZ*@ytO2C%9=yr;EX;J|RsFJgZh3j4LT{_w4c9R7nb)|$>L{K^?7IZ72?ND)zb$;n;)l~^_1?`N<7gzD zt4Ah)B^MPlELkHZbum^IT&278JYvt>GLr{RT#pWqmk`$bMua&Ho1f{Ytv6-soniQZ zpNh0qBYw7g}3Tp6=b-GWByyx^SUp2NU%t6k=WOzBn z9iXR3N%_P040cct;===4s=$lu$W>x|B=kHQ1rM6|pJdfrUh@J#^Bcpgd*01CGgFiq zE(+Wu2AvChFKakqP8;kt`=a~(7;@TH5j;o5Gqn!__Zhqyv|PHt&>w@W+i?!aCus#} z<;$a)#7!)Fg(spG>$-o1UcNOH=?h=T-WpX8q#d#OGIX$QZQehaAK~Ec3onz#<=JieGGjO*wqNA9bnUT)2S@qF>Udo>TK5I!K!{ z&;dm${>^)hm1OTTX}DAC&BR;rLG*j;4LpBvTf=64^)+*7dwAXHKhaqG(9>!@e;6nT zzci9`FTxU|S{)i}BEB_;NteZ2*MDfI)5C>A57okDGzozZyz5?1R@z(A09wkLGaIg6#Mb*Rxf>O;7|9k0>?-t^K@Z1^PDq; zjV3U57$O5*0ZY));$5gaJa%W5=u25zyjygwS6=IKVPk%~0U@(I@DF;P7$W8*`H;lWKc0wgoAq4~mjXM(xd0x%ijgM^Hk9gY}@ zE%q3#pZBESVqCw+5V@@>bOXM;IDuw`nW?_zj*e6lMzzOICdzz4e|df+^;4zxyTwJwPs9PtRp!XH z&_h%E%{5*qR(GW=t?v@TD37hw6aq1f&>f&TYc;brQK}3w?p!~o>?~?F#S^R~P931K z!YV`G$Su9{smH$bWsTh*#6f*z=GLnhwj?|D)I7ZqmUr%M?8A{_Tm-uMx-P~}w2%ay z)kaz`?i_yopUZ#BS6bF{cjfwRQrnWURHf8;svM`+fGzBe*~m>b7q4f1FMXEkAK%c;NUG{0y$xu1R|JzrTAy zQbS~;brMN&QkPPO+9Eu*)jKEea=x%LPr{6^F~?tHh!_3lItNlVU$Se-7g%{Z34Z<+ zwtQ!|olcDi>Qk;?MPK!am;g60tu&DPvFj*9Ss+`U>BTQ~QZ(>RlGW@78e^ZWILz&> zZ;|~sDGjuIgq6C|Pn9R!)d*yP|AIgJu)Y5Y^LN!xWM9brAfJI!zhRUi^$z*R>!{mL z9Tbtpw=4|prseR)u&VA6oML66Mk+^CMg+*^^tKw+#X5#R{U}zh zc}qhvYi#y|KQefMKfMorqe+w@!Cp08qu$@aGGWbF2UnYDBCWP6C*Sep*75o7-$ivO zE8oiSH6~0kG*LSWl;3O5or7h`C()4CcQw=B6Az3w3G4Z@%3IfwSnZ*?dcf8*GnR!Zl%FP~8~`nJ@TxZ%oF*tV4nxXjfZMmiG(!3rWl`xtBay4p z9(@&CloVy|YorER+Ew1S`KU&IJyX{SmejP;h~9g5Nwlwq<3qsnm$|;F_0+rjrPD5! z$<~($ZXw=J`RKg-S?Tb~t1G~oa-bn(xv0h4B>h&-(z*+gin2q`Ym83tCzfC_O~t{P zUl|-VeG@w>le2E$ECY091~`42`xXV%g_jyr7Hc3mscc8qZP&S8YllsZkKKbwZ9J(A zB_$+nStlzfzXA5qQ6Cn!vGZ}flsHU9$jL^9oiE55ot`u6p&xWUd4HkCgiKzCvaRXP zNSL7oWk}}fka3uqVXF@%fyKlzL{}Ik)7+sioqLU6D`xLe>G|N4!PQ3^Kd7S2Bkf-v z2EDJNj~1*Dxz>2Z*@9>VUV9f$noThLa|bkT7e|(9Z>#?oip=bLs1{aS4Y8|6DIm-7 z-a~pxid*O2`obn8CP5#(uovCJ_1exNsG-519JZ4LGec2fO~e-x#evC_pvb?P+cipN z7W$B}t92zs3iy+vx0OWx>q(S!EUk;4LGh6{TW(i+jTiVx(9w zS{FvY%=puB{tM2=i{ZI7h}Lvn`NrYX&$cZdS5y?3DB9}UVI}+3I+=~khBfO?+|L1{ z3H(KNR$_p(=Ya3Nh6ruOAnYDay{7;@ z_Jx^Pb)5L2uKX_F%&?o_6+^h;i#9fkQ5;zp4lWO722WFS(+5

Q|*6z~*-D#>_+E@>Dh=NY>-|2Wu>``d>3KFZPB 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

  • +I@@sdCgr5t_fzlKcJnmyTIu_ zSr!bd)qa@?$VFh1Dk#+>_JFbRh@&m(2_n!?@iSWQ(Pu9YLx@aG9!EgYwAW@&PNPn? z3*~zY#R$363Uxz@^X1)t-2$FzDC+Q#zgm+j{ z8BV|uSu1i11*>XgGrIDan^iQJ5-83@ZFwxF#r5cQ`2Uf1*3Fk{QE>6VedQ4;_EY3& z?uwL!GZ9#|ZlwPN9gE|+mpkVJ4xlncHY}bfE?jZISY(U&6La`*R7kcb&&~a`X)v?v zcYQ9A)}d(ML@7ey?jwe`BC(i}<7+F8);=XOtW8#a3^#c~o@Ll3lp~-%J9sDPQz(M& zq;zxyRPV51{m3*8C!c9ga{EVE2Um<3eb>0TiV!9@giE$!=*?ac&7 zZN%JDj80k}4pK%2<5GCI0G;PA+ciZvAbA3r-PsuqH8Hd&j#Y=l;Mw>T|7ZdU%@lx5BsQkKoMa$aVu)@d`X zc}OTxch7vT0kzgH>Q`*I`P&zT>h{2V&3FaM_4$-q=SPDFGB)RIy(SaL8wWeI7p~2+ zeqJcJUw;+9!aMCl^t5>?M@s&b?@W#vLkaO*|DBA=4ei?Bn&uCcPhOB~{kBG11kpn+ zk)dbJo9NwTMc^P|1&F&)W{m)sf13^OeO3+lyOkZe)b+(-<8Cl7UzwC~xXi2Wul>5w zdM+^82LvI-1j9vHn^cT_BWAa7%(vHO4P8GfBwRXQ6Gy%#4PjY|W|;c>AyjW2r;Abh~$N=COoBiw4u;rVt!F@}6G$=)so3QPXpmq+@4A(Nl zSyb=gbwgWyHM)x@vMz}?<+JM7fd^zUV}QVa^Q}F9nhONCd(FKua&_ni+ic0399yH* z__uGJ(pHu6*N@^~Bc#Hk03ExI*La~sxKc@KhBuP<=W|WZ_RHUAZ_XEnA8eLs)vXtM ziS@}1$J^b`pT--SMt==J*F)ZpZ_y_uqMNy$x49jj_RzVcRJ9N3J@+X}evM@DLRrMg z3oef_+Q?Wx@uQgk7~^~A5(Cxh+fPpXD*F1eU;F-+yhizqgE#WJ25hR35NCx5B2tWV)!xuuuRlqV8*fZ(>%84{xG1&*-*m+aRqrC^zGq!~GE2a^j*M)y zeP~^BTxRK6q#|(WMLcP8BH2X~Ng-Rl|IvPp=#bEnzUz+L!cF#cZ3MYLMCeAq?lf-7 zQm&_WGw1{;I_u|lD17QWiEYC-J3rEvcx-V%&&-27OTYAa6DyskDWXBVVPzd!n`FDc z=q`0F)(^8aofc;9Y#pY*g1BcOI$3rCGbC+L!R4cYzF($YBB5?kM$nR)&|V7Qzb&eJ zG#@PziL#Kk3|rj<;ok}rK!AW!RQNwl@}oy2+L7Aq`br`E>Za7rv+5ekbINw(*~x0@ zloqf)j?O6;yf%>tQPQN9%yfZi;^fk_CYyts+NN~ZtitApXzI4rN(Kh+hqCoYA2z86 z1mfECZH$hoVY@Ea9XOzH{Oo)pj{>fu&=7}=Sz?yUSyG(4<$8r%Rcu_Do7YwfEq*(m zguZkQ%=F>A&#Ze>x)&?PgEyJw7rtIK1=^)&FOj7STsymmAZ@zmbfcKiEQ>_P$L)ML zke(jpgA)8A@>*{B`XIz`6=}|5pu74zsekY{P=73Bh&$s6wk69FIU!Da*6A494xisa zlLWiJZ5XZ?rdh7q?(JsFWIrd2ozZww9m%Tx01a}A3jh1oFdn$e3Jg12M z$v4akR$qJcetMAdeCRHxCQH~(^LcWbM2Q0ukNM06g2ddtn-0b?%HaxOon$Mge}424 z_-%O6rhwh;j?D=C^>b@JulwqM1?MzvYd`nSbN|&70iMcj)P6OyGGE|2;Ibd}RFbi! z8}&oLg=vQ5*m-Zp^qf08SDp zjXz9D{fJ%@bNS=#+VerT{)si9*;R;ANL^}DyD(Tz@4pP2fqVhHl0 z@DPyZc!;Z!m0BS9kJK_TmzVlne0r(;VA1IdYgwpL&vS%#<`RX`VqSLl5K@?;J%7eM z8w)sj;u{8+oPPk>53}-@#G^oug{jr@?AU*XzUTm)I){mXi+qYC3S2s=#ek`QZ>=v7 zw1H{{flAeU^}ooqFQALvn7~1@-cX3z2&%DU(=Qp$OVUvXU~A7lzJ$AFtm3TyvAmbT zAh_ZA#<{8VbGI#p#g?`HaPw-C4|U@^KqerAdtX{Ibefga0st?}$}$(XGzj$gB8SRZ z%ZTj?sV_C^Z49Y1!~wt=g~0YC=scmS;`HUxPY4$7C|+6^0J;Y_ahH<~)IS@{sRAGRT2}4Qesd1F0Ouc|puJa-j4|=q z2BQQh)HT+%g++r+0bAqwjHTT}2rL)W5zm|eMsDw@{{IqN$yz0)bM-yt-_>EDWRx%i zdMWHx5FJYc;MU_l+KweGzWkM-??S>!MXvXss`Fgq%R119eYlvb2;Y5Zh;EI z{fF{iXVSU^g9arsCSG>>zkX94OQ6PUQ{g95Se@j?H|3m$#_w*kR_|2gU}DnRBM8ab(^tS-{48mr5! zOrC(O9&qJnxU|iel>Q4Y3FMNRC??DP3(g!j_<~4-?9jzNE4E+L{RF_M$PE`9K3fiq z+VHaeU*3Jz3o2 zUHK=P2Lh=Ux0&QuZGCMT{tFiKI3Rh41|AD^84H6lD{%Z9$ z;cj-T3IhsC_??V|xT;!nNdd<4u0}@<*Xmrm;c=S%2hsDD{Di*{u|OPvW-4sz-#>hO z?Bg{4ARser1A9R#m~k(aSK+nI98s1!ocr5OfK4_ImF_+P+s29OQ}Bya{x*Ua7+L2Z}DnA zMk^!wtj#y1=XkAM0AHMcx7ci6b!zIL_%v`VCfdM;L#OV{-;G9!IU0d$n`+~5z>P{W$jTfoVkpfrUi-rAY-#K|7QumcTe z?y&)&*3*=y7y4g|z<5@Cm|Au2Y`+J!{j|OCSiSmsd~F z^hU<9{_V)KOI@_;3-7_F=%3Pa7GE!QH>ZCEh%Je}T>o0c;6W7^Xb`c3jGlZrth4FC zcoC^51_-I_{E69lftCwFQ#!W1f30F+xnqz2A`Emcbu1_RfjPA3#8iJ;^`&#mKL|S% ze><-H$90T(abo{tKZbxGR|MQK{ek|(+(Qws0eQ4)cLe7!RU3Ld*j^}hdjVmBqKGWN zlkw9AE-nCjocI|dt_Z$$(|&U^!;<_fSW(`4+dFTu>*0*y5Ha3IYP#aqhcUrF>(s2#=} z73Ro1%Ns28@J&XUg#wvSj6m9&2udKNUeYFRaUa~$fa8|yKW)j0@q&JfMtlpLI(EQZ zrin=EY4B@;2BZ&kRXCI!KBK8lQ;0AU!P#3VsT_-sFU_Iy(!<;4ZmZOBt4+t@#Tlw} z54{)X1B(2$Jy=$CL<1M`*r;3c8&_(UZo6+7Z8!n>6fyu@87Bo0hPb%>h2zX zPv9=7lp@t@tZcuC2Ij^fUe%P>QbY5GN8Lz`48d zM{js=zS=1Ft1)$Za$<sDtm0rf=@{*W7FR}6xPcP47M+i>xkER?C7He<1#`Q8{n57Dp=2X4~;{u zXN>gae%SF!&Z(-Ak)h>HVY~f$3K@1h9FW=BvjOmKSfx}f4q1%$c+0MqFrIaCfSQUD z>Zzuf2E|(eWH09wpWwX5YZ^Vl$?sFZ}li<-cGbD(h24CFmm z9SNtcG|qnw^Zps0)t{gNDt2o()N#0aBP8n$rf~s#xE{X$KqHZDk?setx4f>)fz7woh{qZ}{yYVZ$a0cl)G>bHy&s+Z}LuW;d%oWGV;j$1FB zlIx{AlAo88^?mF45@m@Hl8c=3DOmE%uP8G!z*J0zaJiJxmryXEaM#&*e#%SpY71mU z)jdXyQ)Ddw)c;S%Hx(NDRh%N?c&%OLQ#NnN0BG~kb@Fc|KNPc^Fu!gY)djuwMIt#o%XK7bHY=_!$x^3u6@R3SL%#DqoeXv`5n{%4v+HyZ0 zoOnKnk@(%aq3+xJEA7y=cBVtiWzWm=MW8ZW!VGW9h`N4JGI0{Sa{jPe6`HxpUt4V) zCpf)Qx#j$>xJA$oeek3qIz3#*pn={kv2s_M&vG4sE0$?BrlB(7oN%=4 zC$Cr>LKNI>12qbf5MQ5$_#BYKTWpQ}oz z4Jxth-DzUvJwqO$qD&VSexlNZ(!5Ad_$Avt&s$MmKF9uaL0CSB0gA@K*ochMy6Hro zs9dY1V$jUy?t5hT-CpHoJFCy`aVBp1Qtyml1g}X7Wz(?6IJcLQB75`9>&4zTxZNx2JAAlsns>d=9owSQb*Gh?YXGI1~? zTONmh$~1srStsy6swV2%1OZ#CNb#|v<((%mDR?$TteYY`X+GMivXSnV4rgkad` zDxDBkZAZJaI?5r9iI8ZV^QS&V0*9-g1q!?&*>PF0UX?7nR(0`ePG=^G8}@viY|?4d z3aE-I_4dFJC>5eJ1wL6ty#qPE6O&g{1>3mheQi&($j`UG^>}nQJJ%>-xj5|t)7XRK z{&a1sHtGQG%TSF)=@Yt4xb=-CCtK?!Era(xI7>-a{X@z7-Pn1jpJ%5)r8DI+KN}6w zaDiBDLtz#Zwt9*2MkL!r_O*pMH!CVCj$~F%!7D|{|AzMB=G5^8H{^6s$cII)Z=2z5 z+@9KyHCw#lE+e9CZ%QY8*6dnYVrgl9@;*YUEZ`yTZ)aPppIsfoZ6_MpVbT8e`HadJ zbfk<^9MA5>7kGEQ8SddrThym;up=xQ^^1?e?|=$DOxccyHbndejk|lXg;-j8}>f1dcZ41 z%sI}UDZ=#hv6Ec-WG3EB-zPjsZ`tFz^?L3{b08-I`c7Z*2d8nuz}s#Jozv)?{&|OP z{U5y@A+pA8bk^tX_y?s6VVN_YQ(-MYK1mtXUj1!@8?s>A6Hzf33}ktJ6p24F0{c{= z8S#L`LKC0KfunLSB7&6I1ZV~%cxJ0d;ElBYkv{@(cm=8T$Rtq>2ef!B+V3*jS}URZ zqseHfm{Yw@S|Y4TcC?C2ZVoShmv5SUA}*vE4=aj4X22Os|i;pQOr>VmY<)u>v`#)lU~5VFb8fHQx!tECf}I8p0U68{!tJXxs^q8PI&E$!MU-(k@{mI ze%%bcvw-nKJ-@QhN_ABeG69w4fQECYHTb{){wiJ;DGIk9C@{H5SIfAUhs?Wpi*qeVN| zs+=rNU2wk2n6A9s`^T5s`Y*KTMcuI1qMh<@g_>p z{Y%pXOmUR|46u3W1#GSf1vnkq{CjT;5Y%-gr_rde!5)u4&BEs{&@uGf2vzxR>r|<& z9{V+$E-5Zsp0gkpu+nl0M#n|71P9DUOEkOdWenYUUSe+k!l+c>u~eml(@ZO(-^y5- z4g5zljZI(R`=d0^H7qDbPS($!S65m?rPNmLVV=vl6LrLyzDtzi2dG(%Pi$BSm-bsy zt13*V+ctaj#LWb}G1@wUSw>P*RxS<#7pk>Ts!CIf9DUB{mkJNCFd<)B)Kd+*2>9Fq z7JK~-s&QoK^Wg)>p{~bn8h7FsdDb5w(NWHr-_0v7KPgAtd?22)$%7b%AcZ?lH^Lla z;=s7Dw^{l>zA|?QSR_F?n^)Mkj4lXV<*z|p0+Z`{usu5THoF13)7 zw^YE}iReX^6ZYG8Yp@1PpE1A?`L)1k{t7lRXBSiy!$|9RRf>-dOFK4+4$}d!D~I69>X9?p>E;8uboT%kcS<^ov^o<$K?axpY4_Ng3mP(Mwl5p8yv7R z;b6vKh`4;An%bd0vm*#FC()&a^tL~-=&jy!T-DZXwqGChu8b(OJj<}vLGB2MAD@ZS zI#r;dhFQd<5ZPG_jG#|b95eUdXXa9S%0WOd&cWHDR#0U^gL>a!%#NdNQfp-;evXy@ z{t%FEwiY)@E6`4y9PGE>%|M5509o;NFMQG>vGu{o*x&2W%EtkZnNji5;nR7dfu_cT zH%|>0n|-^xnh+|s;}a|GXXI~g#weHEo*m;-_5I5Aoj7<%K&T;ldq#MpU zSgHZEuOE?*CgQ@v%n|<%0n~(%MkkPH?;89z*2x~SfU4!atd3V42E80(^=;x zmu>w|IS4o7r#t-9O~&(Aj1;$x&F+k~o#qn>Lp|0y-d6vsEA^K4dkCNX5rMjJ6}pGN z%uUYb7tq8c?}dN}!p%us+kBG<>FHrdURp7r_&Zo}((u+fXc*D6sX6Q3xueQ{bqCaPi(%1Zi<}teyxu># zFtrop9_?(s$^VIJAP72*Iv(yqheXgGCWFlSeL;S|g@)Zsz6FtIQ`4Bo#w!B}0}Ch+ zQB!y89_n>waXw1cir!umnY^L7rn@AD$d3%YkqjIzcDI3iOHRP8Wc~p}3f8U>3|#N+ zou3_Qyr%*-GwP^GkPDZM%%PZ3*tscSP(E-88*klvRygiJ%Q5Y%;`b)0F9jp8iO!WT z!oJ4BG6~qtT9%-SWzS4Gh4Vf|@E&{gzP^}*C34n{@rfz0=t7mk5QjAgqGo>wA60>r zB=GPA1+})EAk?y$9NK!!Kj+09CPNp@zQ3ghYHT1@iJVB$$=MhKg61q;;1`RdOjvhN zkS-GBNW>u#5-!kCQ4tjbe@IA>y=0QYgbcm`gYf78v@xmv_yOHHCAOdePaXCP7N~H* zibX*EL`6k~@y{M0{gQzDr~q}QU%SjDpFhlgcg=18r)k5@MN~q9tAQY=n}P)W{UldX z9+K{?Aptz|V8AH;V^O101jG^7S@>?$i~t_B+pp|!j0iA;-R?92@_C`9-`3ylOLL8>4_yNs}~5coi6%y4_0c(5Tsm;@CRRQoE1{Nx7X zFX=ZMLB;|PKE4;S6D)%s9VYZY0Vjw6d|HwUi*5{f+vslKD#UFh_;W(A^qT-NiZ#{p zrm}9xb-!Artpt5Hx=mw|2{0dMXz=?K--{(PMt5K36NCU#tnK&95G8f>kjukaK||#I z2eY?6?V_{=l%tniFKt}NxLuVc z)m$7Dmv0O(l}mVg3wwHbP1^z!6-JN~Xg-+0(r{2zd|Iskh+Gksf6EAlg@^qTv>6nqWkv#&3pZ4*I_ zQ6Dj=76i-&YWe4@9I8e|Wo4{rGGS!h+41RVT+V9sZ=*J4y3Ke_yCW_Mzwhzx1B9cP zXxZcA;xcn{X-r8k`BWUdq95l&K-TYkXUJK#S0ANqsHhI=V;>cGVXRkL2s0j!%#?L> zqP~BBZT9wCo&_+J&K#K^O8WX3@=dI&axj*5c2aL%i__x-jP5!ye&Rs-UB$e$yDK=o z-xZ9KW+g4z5Pt9}J?D)+>*T@$FtDsc0Y)Y!==+C)In%e`n5FvmT}`y^FeK%(rAgh4 zF#5%_W!B&nyEZ}_8yj;Qo8I;AQ0PLcSAO32SB5Js9ttK%3>Q88av7tcD=T`tcM7)? ziOnZXgY$_?Qr5B$8mPAsnN`dvqeACVD*nLY(`A6(mO|lj$#+|ow}wnie3DD%LOPr+ zhg=Vn^sv{shbbM8I$&a%aH1dQQ3S}Lx^;>0GQjjhuCuGEUdM>s(KCCw^OB%bVm*bO7|2B1o!oQc-aj7G2{qPOZMGp=H}-1 zcacThgo9N|s;WVXqK`Pq-uv?OIF3c@&S8EU4(5qreGxBnJtUDC-cikrlBI;0rSyw1 z9WAum{iw1()gXwp=1(oyaV*Ra+nZb7Da1*V{Art zdMxF<(`8nqWsy~e(1_JGtpLP+d%h#ppCR6(I&=O%Gcqvdpc@^x2a<^C5fe=K4GS!Y z(!H;=I?&I;yhEw6zCl&kEb{31K3?*9UKC80S5-|k76y*C>2aq~aG`e3*OeVMoHQM> zd;Iyb*L3pArz*7U@MgrVEwI(=+UWV|afC*wMUoQhD-G%d&X(n;S1AQbhM^&dY%YKn z47jUs=%n>}C22c>YjSq?oPV*Pq{O+7<}UJMZDl3atiG?Xr>7^B*XsGsaQ9}6=!rG< zBY`^ZJ!tpGO)dv&Egxzj;jeI&rw74*9mNba4yPYyuPhB+!oJ>PSgu*vZ4~OMWrMmr55uL5x zb&#wMH!H5ds3wPaQG24IB+p{5#e)-%RVPf?>x%EOw{8?jb}V^cFW-#E_`I6aZ^uK0 zPxA@jb3GFmTWQxZjNHT)XS>F=`P1Ym${$w^_cyMoppp+X(E|MD=`ARU%i=YU_1s!e zh9)cHN9kE59v+@1byupS9s$Rjn@1m^`=e@w0(CVteo7$m599BL?Md$Yz_Bxu7Fj(i zLVS67i8Lx7Q4tsT>7k@9Qr6WVw7~PB$vLeAQT?p?X4yuV3OpVmo($i<3K=R{uD2t% z1tuduV2TS(|E3FnY-|ildcE4?-1K1$LDc@8j2!%1dCr}?PvXom5>ySBGummEc25tt z3gm-T>?Q*^dsn&aRAJYU)fn=p)6kLHOezA&weXLhYa+8WuzmqW6SYFArRlT5&eb4~ z=09HvdIH1Dnb(?iiF){Du*4F$2&HCSj#gTUadC0Yt*v_+che&c*uwxT$CHXC@i)PM zM4V2!2Q{Z5v0d{lHqzWy{0#{ju2;O$M5u#WvmZ-QleeAyBRUuRx^C@)rhKCVMg~b`*`4!>eoM`$$42#O+*PMS#@=I-^$h> zPP;KG-Or3lwChI*18{pdB0>?{GM*oH-7lv#97gzeJ0RD9KU^E)9DO<8DBw!?;N^=x zvJ`&AAB}ujqmpGDM@L5^+c#{ZQMhX9j8xvl1Hc@`c%3vN*f+L)QVjrq9~>NX3Roxw zW2;rPc#oTE;i;GDgy+g8cG;~S&Q>ww;NflDoNX#p5MLeXRzi9s@w3ayMv$gBNBCfY zk%*>^;T(!Lac=-ek$pd@TMtO(D^Y5=UP^3GwJQ)-66DBe4wx{2tFSw%LZc8R#>qb= zg&~i{(O&=Rr0!Cx*}syYs%+DgLZ@{hcFeu6&Ui$1Tk)U+iRjC@7au~2X=vahqoAaT zRGSWW<;ka{?$Xv}y&jb%X*ML_+f8+{-%WE9s3#)X{~K#jH-8~8rE->lYQ0*pN)qy@ zI-j-x$L!ICQs&5rB|AbsH^v~ci_2kt5B1)r_z;k#!f&3)svCho4#EsE%q%Jz;Jyid zcmQo}Z9!d~wOvfehRxMWg4X;IQlE?#|5#BaT{X@Cryqa!;szy*+eD7c2!3jDznDba zux2bR5IY2PW~yLC*kg85(qhrPu51sMEc^IAOG&N+nF_I2L@hSznKz@MyA0 zN=nMnSzs$$Yt)PUaFH(x_gb}WqdSm6e(kl|iM`=B;KisAK`p$7^ASPg5H)B6AS!U* zij^|DqoL}0pB~SIG5)Se=gWMR$=LCsoR_C(=3-*sFE`@Xi#Vv=_5sQlScVpJ*pWPT zD^Wl=pkv<&cQak?v;C^MAPKNv;p?SM>-yqilwE+&neMSeNQc9+@2UB7PQk^6yUuz( zfT^qj#%i|AWv22-Mk&w22=HhXapl3(R0FOh(khs0Njg6-LlG&kl8Je&?L(}yhMK02 z24%jhm4h>M)RHGq=auM#{2p^Rpib`&%Qy9(FZIV)R?wk-4G&9dXlN`s0SC3{boUJ;(DVJO+Z6+&Y&``t1B1A%EXtqr^YQuleUd~A#VSX^mGzzoAm?Iu zvpW2N9Vaucfw6aSb;@w;>LWj3}t8t8eV*XSjAL zk^~ya@J0jSS#a6m-ob(6UF6v1Jg+0>ap4FXHkJtryv1wB={$u3nNY-7!IK7R(*TUP z`L+=6@CerBAn2=akN`N8({ZWs0hto&5srv&`2E=75=JKiZ$^GZoN8AXK&zMQp$(U@ z%1=rtC`3ESd3bneR-2-cflkFc(4S6DY?mAdSx)aC`5-Olr&B75lt%i8jCD2y@Or+F zE_ABf6}Z#%N0esEZ8db`jp|fj>+Y;&oGrs&{-`pauars(Mz$z$+6T87SxL|V>fSSd z0;}!;GqyO*jM{r$RJ6fkz$1deFp46#UzS9$h1*|D_2uNKZktQ@L=6DRZSY6zLR%ne zEBTV6lPu7HP5 zCWYzmrp*UU(UOsPS%CGoKWwu>@29sKrDYM#;Hp)Su9}Q8%4$>X`y@ci(!0e zpETjedXwiZ`gv}bciSXDh=h?*Yp}|wtUqoxHZ%w!l26^i+9>1CqpM`t=PNV{&{h3L z!DtK+GHx_4Q($-3hM#O@qfZVP7Fi@aF^Q=Oh|`4VNzzkyN>E(7@jCW0lUIXU-hp?E zzQ@RZ3ylg7s}etOGam3vcD7X!nPr5LRZZETOo+_r<^Rkd#VHxD_0>>K)60rqO}P;+-}4-|H-z*ZcZPbHDDg)_MzxA zcfN`PHrCfypn9ThMn*>a)3wedV!^O=qrs{QH;5jyW(9>Qfz|^v3=li7msF2*-CZ80 zF}_`1U;HAW89~@dRWQ8{ygxQdTp)rl#DCGYnZ>rRJgMW0%&HAzfLc(#ChI#JAVyCT zbSuNIGeVp>q$WV6qND3aI{N*CPOzTl4b=cV>V)#p?z!Rb?=&Ngiu__MgIy80Oi&gH z>_-vPakiOk@6?&AbFB1RCyr!IdtBuwdw{4UYGB}_S%!oJHEEzT4rdPJ5eGLDQDu_r z4D$R0QTP@<-?Bl8umnW@hp(98oKp12-rk}s073qsv=TNJ8r;e^LsU#$+9MeW%dpPv z4_Hbw*n`-mqL_a~DA9yN-%-8_6wh_rISWAr@*pMB{ZJn8)?iGW-FMqBZMY%;N&$oy|c*2?2lGhsu{ZlL(muMSGWhLH+zHgRrKnKG)*$0yV z4QaNCbV6bIO1NMJPy6yPPD3?_99{{YzT5sS}xjinqWL-4Ws+adx?IvdQeYn1+YhHfd6$RkrKu zK9rQ{ATfi`xf5H07Zw5=y3m_E5(i1uR2+U{`}HQ>Xx;bk)E1Q4^u#7@Lw$^Yr1BJk z=sKc}Xe@@CO9MCYzLK8z&Gw?tgl^H!2zmt|tlsNuv{f>TCgR%Aw#fKx6&3Vjfd!&U zPg489w_lccqqIXj6o*w{s^J!`^!s{fZMt@Vq=T zXi>nJQFK8A&U#7Kl>`53G7Mcvo;V31R(@RJDv=`s<_TA02m+I3^7d zl4k5g()QQRr@H$y|^#?g&4@T)Dd! zuk|nhMs+vh+0gs8{Ok?UW1sW4I~UT#RE;5aQey?@(9_*(ZA=b%7c4C0_OJVYvxpHu zu>JofvG~8WoEz`|(#ds(!?kv8&L|N^7=-915<;}-#Hgbsfh#I{{4L-d*|0&d-n6Jy;r&STK8Ie0PgaqnahHh zr^%(lNyE}Q+K#EVZ^`!fxQ5VUwT@1*hXYh%{%hrJ>&)xt_8QTGWWZT+l3`rBv|)v! zUj#|KW}vtE9BQJNak=8$&(%m1Af4krXQY|Lmr)T;{%7>hS6BhG=+Cl6pNZm%noc*Q zCgOJ;^cEB?u{K1fr)Cdug=490%XDuIJsxIc`#FWlH|lz@Gmu1pTl?7O(?VR!?Rj<& zCBLn%81}HID09vvMJnNqSix6FB&%kOPq?fy`K1Sgev3axK`+k>_rCbg(d%e(2hz?p z&weVXRL5Ud&|~MksooZluTGN_Q)ejye;7Z~5baUaD$r`$GxJLmAd$4}GRe|i#ct#u zOspVaoe9t{f$-A@^UL^NQT@iMGHEFgDlGSufs!OPW{}_(jsgYvbhJ`*?S#V%sPoT@ zF9`Boo$&=ml^gaeV24y-s6`GmQCDL6RPwzYbUUy-FtN%}2UDA8nyrlzpCH18RypKoi2Xe)?brrnv0? zeZ9UZmej!^$+K4<=3i^y4?I>0-q*98<_wzJCQ??Vjif<)Th-%_0m7QyMC7}5+ZC~` zv|Qblx5bFtxA`|f^P6UVr9#4e+c9lpG7j>hdB8slmpXQT^tVCXXm7hu;L)tUpv*|i*9QFY7y7QP=hbO$}N9>hTa?K`u*iLswp zN=CeEIdy7}8uu#0O-;p3W(hx!9xeQp-eh1A#9;beRd&a_rN~uC)aQ>HHm2T-E4kC? z)<#Ax`<7I<`04$#1J`**0 zsjnwrzv1lGv+mag{*vm27f0Usr6jFSGj!d(I^+hE+r$yfA;dWwVE(0`82Sp0{}rLO zB&Q-XNs?yJm5k*a{-u?7wvf$?lRJ9dUod=E$&9>u?*iO$wbSv-rrq8f@#>jCDaZ&; z0iZRsUdJQ(U^4n!(wtOTx7_WxrGUgP!!P&rqWlJb*I(_J3M*&_m<<)bDR8a05s3A3z?( z&%6#d)uK+)*02H$eHTJsR9*xsGyvvY>o_BQGgr5^R8dc5?C$#2k$o=)`#U7hh((RD}Gv6!5$>69f+U6ccYCiOcx+)qxZFtgK5s ztgyQu=igJ7Pb;=soyzwm?4TI1Oq&lZtIpo&>j=BArv10XA8$w2d1@^|iD37)4b4Uf{>ouwa& z63*`HctoQX@HU{u{Kz2{Au+zXqY-^4rvq3aVv+D5QNRD)QJx=K|2Sk$b14K$mL9D# zLCC{&xHjYz1KRy|<)m+=rTFlO$nw{N^>aj9b<8_BzM z_(od9-|nDQs@%4aMGHG2Gq6py3|0tbo7D@#s=lqH+**&oknX4;X5fx;fZ&9~L-Rux zJM&&km8@ROaE z_ZNU#^Yst#nB5SHQ?0u(y@N(Zr*X0)goS;!>V?t~{{>gE=h4isdo!Qkp`aoC6T|^c z8UeAEj_V-FZT_aBLibO+!}cJWZ-9-_>d`Dt;RgrslYX*DU+tEtKlf!Nvw4+pQ7Z*< zj$z?(p{33m`)17&A&xX>{f7A6Ug|`Ej4i?;+R9MBL1WdnMlGP;MVua)L&)0P#k5gN1sESN@A~y0Gn0a+>J&V+3z-&Jr02Cp^rM3JY zaRICa7OC?P=2Akki8+sD4zDGItE4>C^3uDRW|Y`zZ>h95x!Tzqb^AWCM>uXoxlW8y zcg6cUuPTw^TOdrd`Z!8>Wzi=rM66qtoyeyRmjAQ`qE1~sZ6!(pq&5(psaCP%oa(o72dM z`}{$81x_#dj)yRwrfK0qW8$UD{^`YMF+pPheMk;-aC+f79_NJ-3EhVSvC`n;`{7AS z->^vo4=4~MdV$PE?cZr0L37PZ++u#3j9S#%q;3K*1^aZbh4RQrK}^PBG;t%`%twOn zlQg<&w8Z8^grx0L^)C;)aVH@1hWI)<;cs^V8eZWAk5L{q?_+pEl)AlFR@88V?rQ&6 z3TIKozdQ;MKh|)~P6% z<$~WCD9}H5%ffjYW1^S()W^-n9VMw;UJl}RMH#^jD&ldt_FzD*bjnmtE$!{W&bh@h zOk-DoA&s3{MO|_253h?iuKd~$(?q*74Gk}+ZVP@2>ow$M8?wuRIHlPlMI%0O0?V0! zha-T~@JH6%v4QcLKx;lVBfFpPhhYprY*0kX3kq_^s)(100txP~1A?J}+>5ML!5&^N zCn+l}q&4hnf3g;^G&oeb+!$^5c1;2J1|Yv6XBcFk_G;iG-^|5jG13&p?h@mFl{c7c zX;JUE13O5mQ+uI26&ynAO+iL#M2OVz8BXS ze~-CENdSsAEVE&88A!TST3MM4gS0PbN;^2{fn8l)4UCLZxMCaU`SyaWn9L`);ZA?? zHygcBj{opX#6Y^YkFpmIp22B>$#w8cYE6}8$P6+JHRDnVD(I_ zVzmUZ7B)qm*|>*OXSMwq>nNc2>$`56T8z4iXp6Gnm$i@&E=tK^oZ~v&^FW&C8JHe0 z_*=JAJP@6Wk9GY<+dXBa_&iZ8{e{QXF9Iqo8sW(eEe(x}d)lh(le5OGOi6w^kjg*@C2=kKAGZW&g&rFit-Nh)M3p|CY#*D` z2N@tu0UIP5SXj_YeIHE6c#gqYK@!iWl8QyT=-SYElG4R(OJ85c+UFM?XxE8pxiPVu zmpBacDvrJFkP+qKv_HxkIU*HbhZ~$OIC;5x^!shTI3uTh`QDR*;7aGZ(UmNgmNzMG zeSNvlK1UaP_}J_LPQT2*d58uScdfzx*_QjmTATie_YF$~vh>4tYBPbF0Cu;b3)Hbh6&*<)3$kmU(mUk-ED;*s~g@V3QBVh5~Pke zT`Rs9&KWO8%F?7%(=r;$+<0x)W`yXsIf5#sFRSAk;uq80-_hj?A?OobS}XOOznev* zzX7{gX=cz=ic}5Asu)RVg@|Mfsc|!t;wWRr?XUPa&4f?ywT*Pe>+>q0y~aa2flLuF zn)1*56A8?z+fzj&5%7d1zo`c!eg!V3_zF^Co7YbwTG+8vPk>R8IOnAQdWP%&z!M^m X8U_X*#o*G&fR7IRkw%r8ZN$F-WyD$b literal 59112 zcmbTdbx<7Pw=GH_XmEFTcXtK|?(V@Ig6o9fFhFp3cemgWEI0&r2|l>%ot)pPS9Q;O zRqxjQ1G-wK`}$yQep$`1}`!MWWW&s7YA0P*i(DXJw zUH8eto^QXnH1W7U{ltYl07c1Y4>06F*a`bRAK#W|EJ2G%{fj9=&?TuO2hzwPOJX_9h<~feA1NW5r*9Ip876EG)5Q3h*xkhPl4StU^;f*SWzmRnp2lvc@Zx9~~7H7ZW8WR>-DC6mkFQ!d7fc)k7O! zG{GgvNS4xqFDtL$rj^AP9lU=W($Phi2N0a#Ia@9{J{>3#wI}0Lj)9m4Et&%`(!buq zY1e%JvU!!ZsnZqYu{vd;zr}TKxpap|U(H)%QvzZ+C(YYmzdeOKjBj<<*}VdIqcbGH zjoCt&_+xMmigSO?iqbWGIpM@b#owwmY!Q60K2NxGoJ{w^Id_fi+~ibQx{JnEq}X|9 zCcZ&4>m*2Y#O@iF;JYF?wwm4SOWvRhrpYJelk4}gN8-9r_LPp4B zB5Ceh7qMtIBHM<(I>6qbDmQ{JWh*PKzNoc<0Usa_a)P07s>pGDw`v1OY_1$zwP3sc z{=w0l)atl7m1DpEBK6WOKk{lezyc&1k)y_$ zHek9PV-?4n;O;>DXsjv6+i}Tr@$7{OX!1;Ju(A59RS5>)(`=;WULaERd9Rq@{-emU(NzlIlw;36Xp7`I(*h@|} z1uXn5GQ%$$rBHCy4OO<*leUDi`3MFbRR=vpeiA&=unV4AInpIILoqDOO> z(-Z`WaI>dXZA!!sGjXHiL#x@)Az=-aDu%~UNKgm$E-eRr7G!dF#*7e*|5$J~z-WFv zF8-(a-!%n&H%qKr{@tsB<16vV@idIgNL+d zbPq~Iz`CpjZI#aG-=5rYaSJ1ngU#;A({9I6Msrk__7E*88AO1PPMyv3QJ+U8U)_~f z+Zy$^G%ddG^LI)0Z!>>Sk>oBLD}HmM{46Ztvfs0&&1L(Eg$T(046Sx=txwrt;1M!$ zJFsFj&gI?_M3ZyN!e!lvsiwKGS`Cy1M!h=z*U54EdZ-q_AaJDfJB%Vs_M!5Bk1W@g zT<}X3m%9Oheb$LVinv4Lk`wUgKwr1jn`xjVYxGPDo`4HhUQ$6$G-WkWJTJof9R`$3 zMxz_G_e1Q8WN=#eP8q9aXG0G>7)BG#)|3U3HF>oYsgnK9|?-CP#~`JYbmj zzlI!-F1fV04y_hPswV-#_$j*o4eDoQ{)8$LMVq4}J3rtA*mzlVpbTLc<-nlq$H#1! zoIDfV)W22B)6c!$aySylHPohvbb~-Wm6yfoqy}{l+a;ry7hdS}R8{7|z>aPcoWJnd z`HHcXM|CpPp2DC-fT>6U2~5G8(`UYwrqs;K=NBoQfS%v}&kkT9_Dl`SuBvL^HSTX9 z>co@>{s1qYV%lUKcuY#LD~&j_Y|-$3Zha*JGU0sv)gDo_caNS+XLDLp6@n9;fnTGA z%v{EWz4yxqfRglhhTZOCku_AKGHZ2LpmtW!h_Krg{AbEI*~5b~!@h!;*EHT;%sQ+H z$qhWxoA1vA7Q5cMD34rrf^$fVg9H)%U;~lxI3y)fTx8IqX_L5Shb<{nORnt_Py{ML zoSoCs^X;_)@}j&_maL?eB8`i3b>A-uY>Y0fL&s}Qc+iEFBbZ`imEKt2$13Bu01vGH zU=MZ6K?23eLlV+u#L{9nsN03Rqa_m%t<3J-0NltrLT1arPFoyi++Awz%Bnwj<}AR# zA{f)YTgk%wvU#T-W@3Z9f%|NG;C<5`Qcmkenr=08xzzq0vxKXJapN&&M{RTi%zmf8 z`xf_Q$1$;tW3~1pj;`TivrvorZl->r=bZ3n60!FBqco=+`SBN?b5T-WHl;&D_BTr- zF)>A&Vj?q;bcuaU!hqIL)6!0MTxsJUZAch_y-bO*=c_i?86<20ptK|t*Bq+^epVe} z6YdqmovN=P<>c_*v+;CXGhJ$tm*-32^tbpfL6w&h;V#M(o^~RWh0B5VGm_@j`Cw_Y18;+gI<WpXPs`Y$`C)D z;+kjoke?owfEc?N=+;oA`uX)5&XU8l>AWMOr|9(D{=s_0pU>)aeAv9Z)}Ep5P$ujK zaXt2;HI!-h)k6S8(4O3o^25WvrQUVIWEr!iD>;cZ;9Ek&Hny1R`1W92BTe17w=f7e zuuZah=(av!nAR8rqj&Jt&@JiF`{gNXDD4zYujN5tlUVXeSTa3Pv7*?4G;T#H`mt;p z=twf$J$RzVDjb9S?hDAp`iIIdkAL}YPp%sh{mb=`@kz33ZN?}DI#uW2x4PIeY-}h0 zo{rU+jfbYr986~tvvz`ZGhz;yqCYH~H24~6nL05V5uChRK%Jt>$vJ`4YFjr!gV$XP|;SzS_}XS3Mc^;XH9 zqpbC*wC^GM@faaEGqWgzt@obmVht-c<{9-v&^ZzAZ{7^{=0aRtK{JMQ0I=;M?Dzui z+MDn|3U-lWdPfD_bw|S*Gbj2-(Tj<*{RF%t(uOoUG*%HctLnj|q;$ zA3iYo><3@J>8_g%d_j>g4};J?ETZos1p&MEVnew!kTM^ztq>B+NnV zYtV@MGqc##v1mivU18nJnQF@Fj0j|QfOQdcX-l7N{dMu|(H*O%wUP&2j}NhJ@k+rG z5z|g1RzdW*W3P3BEkiYP3qK)vxN~`!AdVesJ8wuyQ-jakI(63`OEKfvx)ysT2dzdY zSOOD&6gHALOwGh0wfVA669AR9HMNvNpRlAUV71xq=+OPK`EvyOJuwu0S|1)kqbW@ zXKcvo(J01=0+rIZC-r%tWS_frNeC$KCLRXl=i*ZbfaX}}DuwlWyN^ihKDqOk z?3OE^W;-<^A9)HI1%X50*d7h38yVo3GIPl@Ry&E+Fw3z!4IIWIJjI-Un&ErNV!=Bh zcUR7M2?`?TS=`aVaK;l2;!gu2NIDW*w$b}UQp(9;K^Qb5ZgEOT{MLFYiOSv;FGPo~ z7v=VcBeMU>Uv?^D z0DmfX{yZ_Z*BxX3+1&M|e<`zudgmzuBZBf*XU-`+<=95}rNb1)?0@2mI3#g4<@gvN z{_EoHQVEPM7$PF1^B{A@cn;bw>y!w3kieXuG9}uP|_iMo&P1_Dt-P|1evh60~h!S}xtA<() zW3l_v7gLTRh~6yubbTY2;!+sAq74D?{JgTHI9{#(2wRTuIx^8g>Vb65l{WovM^9?| z2S<$BZlfVctJ=GwF&UFp@Sx(@Zcq+JyK^IRj@`tgeC~mXBxzyV;WOwk1pprgH$!cg_{?i z5Axbf8zQF0-;sRuHX{NE0?dGKmlYhlEatB}JlMaIFFoVMM>+1seBWOV$cvDgAZ1&? zITsTK#}~pzR^gGTy7P!u{YjHhFFY)|&0lrkIN8k>cFQUgJ7KhKJHD>ov-mfVmtd8? z8594hLG}5RpcB$)-K{uKfbH;^kYh8JRQFSq{4&vfciOtfB_gmaWAfsMWy`?}XF%PN za7*g}K7}J767rV)9)u^rvMEAYu#|1VkY1QK@X}_t*FjKfbfStv_$I0yvq)ljmyNM$ zxq$B2S7Ek!>Q}(W>J?I(2(yq)2y%obF<+>$65gCy`HT$4!*E28UySZiDrPE;M#xIN zW_sTtF~?I`6lodP)R_?I}T04|3U?*;j`_O)mAcxl887uxiT?=g4J{tX`Z@@W1J&D&d)Vf3Dy5s=gC8L6mK$|L;)NLSF2Q_$x?S!xK6QT{)H(-$cbPJ2woVc_QimB2&buo-ba z%}^6on!Dfy@azYPRW?RHa18T@>2T16EkVER3a^unu1c9rSHXBndNBdO6Es~aec`45 z7?`|#83A;+yT0BPE8UNI)IR?}6mwa!YW@B^F0}J8y@&7SDf*>b711k)eZ6O77ua;{ z54ixJL&8{Y$5?=ck) zpZym-lPJ=e(*sSCc7aL%Zb!ww@3)nTuVE@28=%58eoJm1t?gjCg|j6jDixG=hT9{A z7b?`u7}A*YfJ;T8c&`nkabHu>Ia*`{WL^TM!lUUXa6C;krEjj^V91HH?`&YH{& zNp}H6fQY!U8PHQ2lwmmZq*aVDN52erDpCp#!}XD)#av|mDaYC6gaW(B@5CmZ0YCB(n}P34>yb>^P0u#@wZF74+*5+)|O z8DC}!tqOxO>-=7%QxnAhV1d$xsu)x;??UX=S;Eg5#2n;x-%vZ0<$oyFhFoOyL354^g?|i4?8RBPi3*^RvA-*ogA_K{5y019kCmbwR{Bv0-N!TE8RqZ=n$1+)c4_FoQ=O961x}IczadWBSuhC6_sApWy;n!Kcd?BtQ z2J68Fcq2a3g}y#E-`a{psZDk}!9ixea|E-Yf_l-;1MSb&sL{7l%V$-pj$Rod7n6kB zg<8XQ`>|6t4mJ8Mx9dHC^DbphZzB&kz5DTL|KusX zXBe>dT);I(4eHt_mxrpCZ^aybikIM(zju_P#lIscnWM({Lxx*i4F1FcEmaUSVu!Bn z7epTz8JIiq+8FQ>XAI#>X6i8``g53fe|J)K7(J(3t)-k86dQ2)A;peY1s9}7^ru^5 zLQ)=CC`5CwSN?}MDL^DWTw_3!)kv98;V&pP=wOM`z})%Z7}BNcmH}<@sNk;MO}Bq} z>97TPRI~>a$3z>;Vyk?sRZF#%Z6x~`wc`D-lWBcNAaMfZ@=94jWpla#Ca157;z{@r zxI5HE0%+49oy;H#7TQhj4A-iq!Djzz5lhgcH6w^%&i$j5QwOdg3(p~o04+-XxaCPI zv)ROZeNZ5m2YoD1cCY$JNgpb%v!Kh}JO01P>0y7Ocw4ETz%u{Dnpw|9G3hG_Y@fT5yrrN4Y z7X3?Af-ol^HlP~K%^NoR>?_PkwEm@uV`(l`qeADbR@rz7|Ha!@Ib(O61fPFjS&Fko z8%JwTAA^ut#0v&%swsT>ijd@?GufH4a%8If5S zay0JS%U9iBNrcb2n=sufogW9!yTYuo-AY z>mMuT4g09(>jX9c6HQHdcmHFXj~gC(R{7E#P*%%Cri6Fne)QhKCD;F5hxt>N6L2ut z80f#_s~feb{EkiE{R(s9R|?612F@DgZJNWo=YP<5s>Bt0fbJFC0Smkzk7OuiZ-w1v0^Sv^IoO4 z>zAoRMIvHjsp*pl@C=lh2+4#d@Za#^<7i=Yzd4Rw{tq4EwDcc3#Bih#2pph|wTxgD)y5XH9^?@5No3~mb z>t)yvA`qN>Fp2zwcfoc5i|f(&?ay_oc%+4|Gf^p1Bt$8Y!A}(5Izf!RtY|mY!U%f0 z`cbMd&9>teJdfhJxS0Fw!;WO@( zbnRj}+CODtNLst1wY~$o>}o>9EhmTKoTtWG+tH@Vm(gIdpdnV%k`VhQSc^hSYo6$# z%z@jSmPn_mY@pS&IUwjbA7OhjgGOl8Ub~r?a;0Gs(+BvA9g_8y92O_3mJBye(I|GY z`>$_neAg;@)}GpRaRH0ZJNG3$Dw5>4URP7Ecpiy$R;RnL4Qj2#!9G9?rov91Eo%SyGSZV&~>RKH9t`FM?!+Sag@35k|2cdZ=Z*};XCjo&{~ zzF$yUiDW4{6L*}1M|%{mOwoh-WgU3o6wQas3~ctvuFhAyVd4j$tD!O8h(yn934eOO zD^Vx4PwO3YRMIe@-$t0vaj3;5LkRT?TgLB@oRBC6 zk`(cK%ek5=-1%=1DBArt2w@5oxVno1Di1Eyw!1*(zH6N5dYmYLNHDNyglOH}u)}7j zjTD60Bf7I`{NB!4lIdJ~%kMH!I&M932dO;?lVp{w7e=NOMK|H*z+8o!r9+c&3m?Y( z$tD*0OctkJME1XA+XEw+cAntou1VOW)kY@4mWs+1q$Cj#eeTj%cxZ1D>pt|{+)ymP zRPZ`;gzXs1lX#r-OC?c135>;~1&$xaiTy@@u)=t?_5BS&B3(~}+lbJdjXXr&8|KYjehex5;9*l-bMV8k21P>@VJMv@qNceVE?)9B5Q-9wJbc z*m5r{5+n-6T@FPKo;`Vb^dA^l5_?wckGuPjH~43OM3uh9&%ePBGV0-{%Cec^SHhXs zLjuw2Ts;^ZOG8=d*eu$z-;A_CgVK21GMNrtd;%#U8r;6B5wD-53PI#USL%v`5cD1T z_=F63UzrjPfg@jk@>$K~k|8+mYT5HJbjpxRFDc5OdT43yq#Q{F^cI!}?j5t}vQp&G zE*+~j_7ENN6Gh0yQLLj>;5r*OEjbTQ%%2-~^9FQD1acmcu2ndS*c9=PKT=YZ^=06q z3h?m|DSmOtsbSA@a(-4g*+4s%RU+@#;r#u3l7fb3z73+>#xf|UMpvC?IT>MI2~|L2 zeA{vPkrOZHsmy9iK)`Rr%0Poi5$hW@5H$Cfl1C)_bj{ep%F=5r7SSp;Y7z-T!uZzY zV6cWlWZ~xjy~2Qos0R^63F7}B#mE2Et_p<%sw;0{o2K2*Zuvz*uEqSfu#6Uh>Z)0U zQE+)P3;Pmo{L|Q~BF4f_Y{sp4&K>gl`eECN|3=0lD1z?OW$fZDHzr5J#h3W!2DvjT z47yEIl^eEJO3K6gmd^&28=E`p3CP29daYTTI`kx?e`0XiVq4T^LFfX}nKRt=$*+7x z_~*DeuNz0lN1?@Ggq2ZBbtt4gjuE56Dr~$-81tY|v6cGrKa|<{VvK6~WoABQ=&um* z7}j9#et{$-BC4ey3p`brmIE3_j@Fr&jbJpTspe0_2P85T2DYb1#(v9uSTnY*K#i%Lt0@bdFhzo`qO3M+@+X~sCzhI_p|A$cgVAQSR_pBs*) zYSiJqbyO;I1oQKl2&p4iEGo<|Ci5SCX1{toOQ^d0-F-@%8iX>60#I5?Z`Sj6e$?>C;I{V#^bk0+H5j|0H# zeh|Z!BW!r0$UI8b+ry_8;xfy_VjY(W7O}#*vTqqBf){p0z8b1HswBqPD4PdNMZV%1 z*o2uGWo*vB{+^0wssSQD*S0)6Wf=b!csO=HdwjypA$xZk@y&d^DZI?$kdcSni5U#U z)CgkR4RQ4TMckqfs1tZeE?chj{8}TUQfQ44*v3K5nsqLOs5PEwrgr|VKO(cn`sApG7{(MsFOHc^&7}?mma3sr36n*|E<9HC^K`S1m*mybh))*>&g{$ zY!tDu7Pap{DQ(+d?%kW8w*^%T7k+Yh{`F#0gLOZ4?z#RYHn+il1NtlHoGKS~hPvho z2`X^~X4w(DkOV z%&6B}$V5`-Pcl(`jL#>0E-oWP|C(cdds>IydGZA)A1le*vEws*)0nsM;=f=-8vbi_ zxuO8vc2*JYzp~Z&YIqJkz4oVdvHnDyq~o6N!cl|ENvp7VT}eMG5xF#Y`_<3&Y&r^D7W9WI2g-*YMdb-Antjeu>%1{E_k7~xGN`a8#ARdW3~*!Q ze?gHJe>{UJ;-Bb9fCRO}90z#H`J<9^#Q3R~ijrv|woI=L|Lo+RtbyO@d}`A|nWY=v zakDTyFI!4g|_RjeOE*SQB{qpirGl=r$QJnaS ztf2^Vo!_%a-WdzEf`IQwQ%in%VIJq5!-J*S-wUfrs+&`|!qD~_Cvq?JjJV9%_~RB9 zco7f*juVbHq?Nh7kY=UBSclXILjfe8&_^>{)IkYPc}A~|2dXpS@(4t0l>KHjF)O9e zaO)J|PvLguwPhuv;F7vBsMG<(@RR&JJ|fY#A9%(A=>=HIz0s0xMkMXkjQ1ih`1fnC zCNB<}z)42N-b$V=mzFt66Q@8|mR8|=VwhMl4CiPf6clN-vT8w4Y2U&bq_^oa=V}mr zajInP_Y3i)O{Q?MS2K*9R-NnV=G5sOr|r9*s)L-zsfOn{^|zKllJduPes%S-x00;) zwkJW>t_w<0W){os=&8$h(kGs%F=>4}L8>t1{ZTqnno64Fd^(gbt3MAO1}%4|2{Udc z5%mZfe-lfOiKxKT+q;tE>zRG+XRBRrU>hgG|Nm998YXgC{ zcLPHPR#j|l>?D4fGh7JpcP&k}XGh^lYpA*wcx%maad{ua@Zl$>N=gLc((7qzw%a-` zEAF{o6mWS4oBNd*!Tn(fOf%D4MuN%#9?$@Z(g zcFgE7|dADHL4anjq(53CCz>aCqGc;N+T}#t!HgDdk2(qyWU3 z3!&Sx(mm{J!orqT)SnDYDB_ELT*c~W8fAyy{_^n3O2 z40sYKMJ5~F8>4ld9HnZ%KWM$4V|bs;$_yMiam(H6J}KqcegW>TRyfm-D16u)M~9?E z(!nhbP~CNFIJa^aGIw(bi0!>jzS>?4D|X){GATfcBX3W;U*$oNdqx4 z{FB<*?(9ty4~mQqTiGEE7&Y_LdH`v5N<1Q%H#A^ zG5Gm*C#1W*Ela%sbH=BW5#Ek)`ElJ0(zgis?r_kVQ4x1l@*zVZfB(X)L4)K+K|zHw zH!NqCaSgseNNA6Ncwe3bDA$|gz{E{JYB)Fa*miJkx;MCWawnN)Dj_p-isXJ{YR7WQ zt*!+H>C>b8ur}%Q1kB560@qP?`S;`bN@yPVik)d8I`6)6veP=n zAIuPdp`kK-@Y6nL5zqw*n*uPrG#Nlrfro+uUs0O~RaR!B43DZM?OL?$q|Sd-wC&B< zvpX72w(VlTgiQPqc6fV)fs&>J&EoInZR+#m*opH+p@H@EG*eB*=SqId~Wub;W|$XC;-0gAy$ZXh|y zh>y!P849DGGnLM?%1V9lDZ@c*JzFs*uUVT$A|D9RT=`it=@uOG1)0!f%}H|KE0Jfp z@b9`3)7kHYXNgf)I>Gd;p)8h`{zht}n+sL2;%PcN5(6m$;8F8h+GA#?TCZm_ zQW@O26OA5Oa<142Jp4tE?3kvQf$?x`H^0v(F182weSRTSh)g7P-{Pib`@qS&aiP*A zqiiJVt#HQru%uoLCy}}F-#c_yOaZjC;P%S77x{uFC<2S3q^a#T`vm_pG6ev?$c<<{ zdTB-8HYF2N=rHh!>}4lJQ<>mTYAw-Lz6Y7xx>3&_JQiJ8*KH^cuwc77HJ#^3z0CRJ z1j-RZ5}3^zZ0+|jS*>2nXj9HmL{hVVwsTF8kS?#3nb@&fQn$dxd3r6GEwnTc7Y0=5 zo*=`Li~LM24@rmJQ6b60u4D03#D_Lb$U8&DC6<}`cEL@MX}pW4V+@7jcv^Pb;PNVy z^$N#+Q+4jvA31Pnq}!XJ#UxNz9Yr)L5`C8kPS^weBo|SL0?*kYXepD&?RDf@%%^&VI=9M5n<-Kqt?GKd_nZ0w5v_GT@ zoe^;G(w^=ltkAhtLab5STp9nnsAA?8ni&voAmO;@=ffBc^v7vMW1y^c!0IsZ37b%v z`fKP+qA{Emwcs6r4LdR-NkuYIna2wWmwc*uO=@WclJ;0lO>QOwnsekgx#kq}_fk4N zg00a9qUR(zhg8{^A?O8u4I~lj>RdMEj!;U{TH`fKKl4#N+WmP0K)g5#gpWd{|o+AR%hx9o@JG@(}al`UTR zo~{nWxVxFkc8Vik?urA3_Shl)#!nd?8+CW2xUso%kreZ_7W>|~XB;JAtBo$5qLX{^jtByhW+Ey9{qsj6p>E^&M#F7>7dpn{$0=1am_Tn0_Vz0bAP6f_kH)A zMk)xdfMrwwl;dr6-r;&{c7~**6qVS+49X2#cSf%0wNAynLzY07g#GZGaombKLUlRj zgi-L~U+F<5ZDmHXQ-*_OKC#|x<8NG*Xp?J(NvGWEvl?=vik5{`OSCtcW8_p8xEJ}b zeL(9r)3d*QJ*`^Ole4~Cs#NbwYRb_aFjQ>**W5ik7EjtAEDuQx^zO{E-}Ikyu?ch{ z3a%>SmagZG&A*0x+J6?^eE3P%=~z>E$4op`2fi<~CCn(P_xsHlw*0$KA&p?y*9L*A>>u?u{&33Gd;iMP>?>K z;9x+JMvRSI9>~zT__ID3l$76?dr;o6IIh4`5~YVZ^5S*-c;AG*hJ-n zGbIz30|nnE}HE(<2N9KX=#6c*ZRkOn^Rgcwfo2{A6o z;jh=Ge}5|8foiq@`^6(p%*6-*9|-+o!ClmDx-W3iC8_Jqqsa%~`qwn^)_t4BDel$u zX4@g~cAibInUO!IHh47rZqNbzPe`oVmDwB*yv8d$F}}^ znP?J3xK||);EUs`SswH+#y?4rPQr{=(VfrzqUM2Th1T&~)b#mm%db|~&QKO%28$Xy z0&0b@vx)bpy$8C;PsB!ED7je)8yEGqGP!4iUoAvg@8pkmq^xtFx`x$PO6KF-q-H@BlZSkXy(`(^)Jk=XuoGd0F~HQWt$m}I@33vlMRya5s5X1qz{~#{^3a>Vh!Pk#zX}$)M%onF6R4o*@$;g z!Pf2oT)k~Cxz%-60c$o4?BHI)*;I+eKp)<;B;Oqi4#Q6%P(b2kXl_^_bels@lkWP7 zWi_CxVxLmMOe(!=x#*b5?gD{O(2uJ_RumV(ctBgp%&Uqo&;@>g5<1sM&ieiiEe(SZ zIZXKrQl;*0G$Gj<2ePzUzaUGJun&CU88C;zGH&qH=7abpW|t$AgI`VFY5BS<2@C~b zQH~$|LlOUM*~3rh`4ed^Y~l>jyR3aEY@G1c?7IbA!V{v$ik2WZ)~=A9OsAsrbZgE7 zU`}s*y0Vf65#Q94fV1;c+B~FmM00)@;2}k`28qR0(q-Y_1z6%-IFk5lqq6x!8*~Q+ zgqwCy?XBv#o3gE@2(<&)qqe)*1n$e%Z8Cu(edMEV&50WbWl@AnKg zvB*vPylZE?SI_qc-E?o^@OUpd1-o#wf7SpB1~7$jmDVpmObsTzZrPviFPz7=&YCZR z56sr)>Ntv&-cJK3vewzU8CxHa&7g$JZ(co2d)_Q@*hKpL{Jc)q8{S{u@m(amBWb2( zxNGoQL316Bbc>L<#+Rb{QoFR?TIf;Og1th;dhwGWhwo$24viTNtL2jCSu2A6sou!L zune4n#h`+&&@rl{9cn1L2nZaHQ{^oTF52fGnVh2F5ovgCB0y2~cax`&66KC733XO> zZ0vUgj_$a)o#y*N@{mU`?B5b9Cf!KhUvWT-(5O_}<7}KWg8nB0>xQqH8*n$lwUd8V z18RJhn~ukAR@WklJIzE&1K8s|f)`G-T*)T)Qv{|6ba*`aUId+n_MdiNsF+U8wjbyS zx&=6c+0q4ajJ$^FagxU^UTQjmixYJJg(X{Y2D6eY!bL!lLEU8+4Hu4ahs^Go(XP+e z2dl2%)fTk!SzY*6RWY>{vnn#$=ml=>ZGgRluf=&S`~ojZB3dRos=%@oPp_L6LfC0; zRh)~w{8rx3G53}$z~u*-`|H%U@fcRS7Lt%1t(yTF#dSZC)^XioTZP->+V}f`zMz(D z@9#fofJCaqwVA^-b#L`G-jQ-R`HxKKZOkhTkov1|4mv(}?nv^oWUEH2{PCC_{ys^g zxhG)&-oC7|2Bnkm_}IqICa*j{XlO-{umZwj%%+ks)|MQfAfcWy9851ZTQvE$xw-T7 z@OLCc!}GYP*AQ{@Gb~OF1{1cOJSVUDcxt77q{!X~2J@v>?dycaey9&Tnd?fs&x&sB zML*<5f8-o(3!k*QK8qK|t*?ohRprEHt9KY{DE+SF=Dd~4C1vcUP{vV%TLM{6t)EL{ z{-stk2k8l_@P_;oB)Dm^*VUQOsM4rT8u%GV>K9JTSVT<@ry!4MpkbDnY;x` zjmU2+r!{=jOHK02|#RRZV$!aO<8pC{?QIkcm1o0OHw_QAJR|;F~=b` zpaOEQey@FHMMB}<`lRZt>aF4}{#mhVDyqJ-B1C6HuvbEcO949mGbbWI4Wf|D=)zMH z(NNyx)g8X!A-*@68Qv}pWa;3i;P+Ebf9&36?q)YY?Ymbd>s@ueO%Jhe+Swwa3jU!bUeB!c7zzxuz{$D2%0L-=*l9B0kHf@;jA{MbM~LBtQep-s zK36LbFLUT|UZQ|KF1hT=*RF z?_L&>^b222Vqr?qyb2d&|tQ4$L_bVS!C$Zm|@h@dWlX(0u98A{qX z9ZR4VjNh1jOmql3;(tp~MF=&){4tdu-Q^=8rb2E$p4lbUxQ=F=+F>e*e`=dqM#=WAH$=(HhkOGm z`?Q+#_J$~eROs#Nj@*2_JGb5-$WSE_poGETf9syD1b80I=*`W|vkSA|OFZLm1?ya6xc zGzfx9ypfWY^xj(n{hPc|U^UK)?}tY0ze5lECVv$tCXTZ)%9294IVxS6fFf zPb(G`i8gM%;Fw4c6{eCtRaKYgY~l6_=`_B{CK722%c?9U;&(9I1Ux);r`A`Q4cb+f zBDpeO_zK@aJd-@{5($T9rxtq@5|u^F@-oCDWeYRUyqgCb5Nic#_CSHGP8}X}`r>b; zWO17C$~@D(@}O~#i;fP)w4*Z_M-|^letjM8<@l@VBUWuB(>oxT@BCAbEl^k}RSSfzRh@ zMp7IaDpU(iFAhQx`s&)tQYCW)eEH7-qii7=;MKC*fM4C<;@%H$^-I*#j~^8fX=}YJ z{z9JX**Xk1cAwZr+^+3f+q-s9+o$=nC3zGhvVZ=wfr3H%G7eURdS{PA53cZAp%{Dj zZ|6(LXpB3$dF70gMAjRZKU^iaod(e20aJ;S`o9B*&EJSvUZup+twn3!_FNssX z^qzW>s^%A03l+btWUaPs^^f7ZZM**IYQ<4*2T=t0g9YEF;w~#r4*cR~CUKa31F6!n z&Mc4j=3Kkq{Wk0cG&bM%*%+R^`O@Fcug}j@JC^sK*F=&b8tDNq>xH9<>AOvOeTv7Fpg7y;y$x1)z$?c0mx>_5 zzx*OyRzwD(n}e-n&O58Ld9}AssY>1P9Hnhb_m@tbDgtq!+5xd1h-b_A)rNl%!n;}G z84sle&Q}@S;!bKz(wGA;bir;N9(-Et7mOCiZc!37Lu289iRWp&&n%WB7kv6mE(k}! zmB3y?(5}@RrS%07?~GU;z@z`canf`zbGa{A|Vslq%0<8&uevr0U zQ{ysj#Ed_`=CJsJOWbc-Wh7nY2?jIe80xTLtbpyloY^m%b zN1A@&(2db~TswY>&`0{@2^X>Cym>$WAcP123*hxTAr7BCxh6+cO*#`lV=g&!)o-%V z6comNEHGF71L~yGl7T4yQ2&qJ=Ks(5|B=$weYO3&H0Nao`uYk6xZ6?Gv0?HwJbH+1 zGW3nyW%JmFSafqQ+!>w?9|GbohVw-oDEf4wD#68lS?<|S$!yt(B&Pe4A`Gl-QX8oOB zER8wMg-zqr;;?XczSJdl+?xDo2R!uqhJiO8R;2KKUjWh@eIw+%X~EtYysuPjX@yyg z1MgbjQT^%l;nWk0f5zFYk85ig7b9b?@u=MWa`MD%{yK})O~&hF#^X&EFY!DaUeam#m4dd8o4+dzm$ zEIW&Twg1IBbFmT;_D!!Vh_6~OT)Ogw3EA}YG2i*{qgl_7+9LN3xr-y}XKk@bNaHl8 zec1WOr<}EFHvGn|EB@$>+jk*%gIk6?y099;ij}l2p^eHsNX+VZ5}g z28RXQxBaaMrmV*UE|r}4mKk@WiXk?AXz7z>ubk1xBR511vbJAogxCjlf^YWCo^uOz zz!RMoFwLN-JXmxv`Q(@)Fz__l+m+s z%IKjuJmdCh-=Pwi9cGKcz2A!gGL?i~mcXMFbMG_SHpAGnzikzY?+0Ar@{H2E1hx6yE%bt)8R&abVse% zt;@;(7}R}!oZz`QgyY_3oh~M6NTV@tfqBNAxV(u~amj4Hk#OudOBH>Icib?8pOaUV zb$QwzbZC#hn*PI@Os9HMZ;Pgz)aW@8^l4V+&)p%7-tK_vMJ>upYfiN%?VL@wgh;dU z2xBP|Q^ag6xRrT*#&SAs7gPk?Fat_fjNCT)AK!ut0AGF)oykJKW67d}xr=S(ch1m3 zF8-p~7Cd#T_o$AKm2F#CaTgPL!3a0jo1qW0TJodzJ?+ldV_Nr$BClyCDz|-_jr-~J zt-cjDe$^RckI2jrjx2M!3jK{;dO2eyEhsdaLk4{~ZkgAly?eiq@QMjo`=Z*JcFtY| zQqI(t#kkclT_VA4{dLhw{*wiWVgxsw{arf>_VU=gcfB&2o9t85!M0o5XsWafDL4sQ zT^qR6yT-@lJ&>SC>aM~0vxp@Z1AebKF}K~!0g0vg`f6cVDQX zP8TE{1*{1Dkw)e)Uv4W8hnf%}HXm-|VOx&MU$gLiYh*gW7Up$~JD zq#a3<-zicjA@y*c*N#LXe4lK?)8?u^8o$Yg4^3?E1*!Q(GPcs_ArTmq2IErW{Ynp! z$Mt4+WBMO66pFSbdu*SN3RJs7#Af{n*oWM^zQ1sH-u|?TBxN?u2Ftbu*5S5I>_gx(%nclvX$y!b#iFb@|()-9!fouI30@co+a zu?pda<@adjbS`41fx~lGwnlWGh9waj(}v48c)d0NW^&r!ELkI=&B{lxEXc zH*AhW1g;9$QTZ(YinP5VrE5ljNHVPgkp@iu>+Y_`^-<_pGgBqCR}MGirDK9aFze+x zxy!AjKHq7ItKp0eI+8;FG@E)3OTP7c(woKBlgC8Rk8iYabNry-plnDP01*&LLh?0? zi}$MhU+bev=gAm{4#Etp3pdwfhJ@F8WTxVH%Iqh{Dgcvs)eu{Db%y&5i6Ekxc}o~yVsSrO6tht?cXiMu}P9) zP{4II0XyWSfEjut?>~TuHBQ)f{Sy7v^A;rv4ttMEz(xnEfi0(6NR^&*b9H@I(a-Rx zJyyCMbC}>9i1r?{nCI!HajGBJnC)O+Uyk%dPdMNDRKoqt+u!Nypr_f4bUO!z^BCs& z)@2$LHRi(;bIOxVAbl>zZ}3$_EVMstXzcmgp!4cB0NyJSWPSkY4I*NK7YP90x-*E5 z^l$Jp%nV0(AqDSw4dprAm4HP_ujH}zXncV_cjuPxKtf1J77 z-^T1$P|bBYzW!tcQdC1szHhrD#0?UlV4_rhrW34t2xYkWScFc0~<(W`J7 zT)|A45-(I4HLpshv;rLGh6;$eiLlQL;DyGIM^<9>l&ES(nmZ+BXvJ63+-<~fWva-$ z`z5EthEH5Wbx&{Ass}4ZyqHi*lM18j`Ysygn)!~)i6{^5LN$P`KGo1uJ?1qb!@xty zA0P?>qMe(vY_@jJ1438^@(rj{Bzd4Zx5U^^F2fkx`{T2dd9kz^^wk~q<1+#9`I*X= ze+vHd$unyCJD>4N za8F@zx&J415|Ye~j5`G>6_t@5(gieU9vQfa6>F2^V?IGrMUoJj?F2%Lc9)yg1InSk zBmBiCuPg$c>L{j-@p-_=e0-R-X;Q{4AwqWe(A~-#H)~&WI91~J>d%%N(^=wDC0S_n zxt0udJ(4^XD|YWXX*G1TqAiDVk8pW~A)&T=7OVU=+!XGd`0}s%0vFlBD>=zQ=R;68 zD)1oW;&Fixm;f(Fd`l7M6tsP@s6z7LLjeD|3?$0JS6tKYNS3$EB}9D2YKH9RK>^J_ zp}DJ9$@hkvvywf%Do`hSZLaeA$QN$jB@&_ym8C=>mdEj@)S9DQr$@iNT#d%YI~N{H zKfkOr&$(uFs$hs7e~{wBRb}nfAb~Y`36rgEJt&EkZ$wJoZcDL!Aya$_;I}5k3imR7nPXDoMLadcj zN*qP>4|_2q=|w#xs*=4ohA?F1iwc-H`$5?{=(a>8?^=M&DIW<|JyDiid*SPV=#^lRrEJ^igq@ErG$kKZJ&s-0Kv|fA&X$S2+Qh!mOXl zZVy<4qd1Ud$f9}YBP)hY&>R}MQ{3lwBu|Dt{F)x5xf1aT%03rHWI)bcqpP%13ksRt-P;jxINovl>Rt-lO&zyj(I7 zm_2Jfx}H5a-;4$w7$*N+$p>}@2d9zJ00P>{Kf;)Ad$__#*Zv+kdaV8ftwKfp%io+h zCat!hmnxYo5RI%sNG&cde?bXusR!aw09{M|=3(7$%QE27 zb?c+~nvuEQCZG-m^NEY_fVE|h^RR@Bwdf35twqjPdNG6(pn?UIa*1W9?*kd!f5$7g zddEtzk8`VIBrT&3d3!EiyPKbmnjx@pBWta}!jQB^@jtI`_zFrOBX}m>3e;SmL%nZJ zThP(3Y^iwC$8d*~T<{Qjt=cj6ilDW^!(c~ye87un1Ez1M@TL^C==YkBm1(~+AaPtp zW;C~=>ARiL!q~X!ZCe0{81t#F9`VEz5o5SoK%?!IHt}Yn*ldnpc}mj81z*}K3hA#}d=rqX{^Ty76*YFBw0_(a`IUY9?C1D> z{(UR$PDRK)grU5WYrz3TmskLPI$u5$LhHRvjV)4k=XJ2wBDadHJX_KRrEHZg>n}j#f2=pZ;QJJ%vrq+o+ zK^oUf?^#kF(nFjA5b~{SdFAE?`!@|&xcl?b0$_u0?rhniiHNmqJ&s|Ujh%rs997o4 zP8;J{_p89_{v!6FqDIr!Zmw^`2G*A=%y2J{YY-K!v~DBw#yp}k#FrKGdjuw>Vb_sm z+4ZL>NAP%+trnL%pP@*K<=jf0*wlXq-H6}}JQ`0X8ZDrD`{rms*Os=rCPjaFN zy7x;gVJ4`0SwqhHfuvn(pg| z0V(dq7Ryw;LM|v5@Py1Xr+1^{BX6THimwrIvc6&UF#ss55h5N*I@M~tJ{nn(Lq6Oa z9LBnQ-Okq(63@k@R5ys(k9je_K~1}RM^FerN=aF>@K1e+avks8@DO?MxD>#((rKBB z#+Im)LrBjW+c3BA9I{x0)qHv1KD$z@OTU&-*~Esh?=%*B?&A0LYUMH%Gss++5VvcN zS6Ufdq|{{j2RS`;eGg8=Ht0stB+e|^$OA~%YvrX|lT0Lcd`}NMGTHjmw|w+K!gQ5T z!i0CZiE*6L`{_g=hDB`WKCdBjIFIdaXI!;MOgdSh81mDyL#eej&t?j5OJDlZ#A8 z6mtnmclm--y8!;wUxvZ;Sz;H-$lB}DKaw4TaZ5BycnUAjDH3+La?fB+t_Db&CK?Lx zJt!Y`joVrf=)LJV4c5Aay!S1Wh@zBx=_zGI2Y7=xsTVt zLUYLul#1m7fZVr`5M-}uh;Tl5Z><&g`6sY;s|ftbbc6dR0-JyxkyJ3AsEBMii_`(bzYWfCwW1-IhXXS z=(+nqtLC0Rmvzlbfyh4f9D64?hG-Lv>wQX-T75Q0cF(%CtSHlc>pDdmknBN~X>r_hs2yL)GO5uUoKxToBix zc6hq$jHagjTfgEmhSD}RBk*m{eh^gF*)TN|Bn#So4*HzlrZ_54k}ERdd(PZ22p`46 z*`^g2X|p^Sm%Sk<8YHQ(JV%l`1r<>zFs1*G>cA++r;rC?lDI@==A=+3o`RL$6S#~b zrZWOy2Nzrr^3i*f-{r#LCSa6cdogZqHfq$)X~xCZT998AL%vq6)jM)fl)3kcxzw+I z-~UodV!ap|t~lxNml>tcQCjHSJ(F92b@$0Z|2MP|oFeD&Q0`R6V2WQO?yQ&~K8%Ys zwBxye@Lo&TM~_-kj9bxjwi**$$YwQdGfnb0Vl*fOIBu+xk5iIsc=s!AR+*y&gW6ai zCFQ=rJY*s+otKkJ2_lmx>F7;89M!N~wHHL)@}!BuHt?)0!!}Sy3tPd&h!5H%+J1~k zz`SD^pTF1aoL*$BxR~IK5%_3dwa~ZX4|z-R-Dyo6$(C$2(rHvo(m;KtC5S58=Y8eQ z4AVM1Aw*bGx2lkY0hMn^$cP%EDQkQ9n^&!^z6(S~1W~wEVJE$g%Mc*@&tr}^y z*p`8tP_7$JAcLQ$#J#?q@7VWLuh*QfumCJi;%XFRwO~Pa+ZOaeE)?p%yAV^8${CA6%`H#7ft$vl_;Q6`cl}2@VFcO{9HADRZSJ*` z49aPh%e}Yt1DwbhV|U1fw26Coq?*=Pf6D1EH_hnF!)8(8MWS$GUj|6pl7}8MRD+Vd zRe2{8s-IdXtlA0|G3Zzf;8%`<5u_r^b4;zrC8w-bCzvdmE3Ke~^FmME`Kb^h#H}!c zXnMGwMV)3NneExITuYuh*z{M0%Fzty*+MTdq9}W~Zfw7L=vd-w6d%_hi1Z?GQ?$9y z++(Y^t>#Ptk?Z8!R@}4>1mGu|D0Ei8$Bgqx*yHeH12ncpq(d#SZ-qJ` zGCV*-a1?nf=MVt@sbiRnPZ=w7go5Z)3Nui|`sS9-ioaOEaMV0GD>r!scMuZx5 zp6_|0j54`n<^a3fxaIuX!V3JAyDuO9G**Ov=%kUM3Qi=h1X9l9`^sS)SUPe4k=OWW zxmcM*LPTz!uPka9G88DPrk`L1HO0(0&$l#iyIuN!WihCBw$)gc+$pJ}RCg1p*vlA2 z5+P`%d@6|$bhsaJ-xGQYY$DyWe<<0Mgj-q0RWZ)1Zt~i!sb(&!L_A7^|FpQ zagUv3(xMC=t;7%FvU?o)_7N^eC}V! ztsska0OIHF?V=Vx+`}%l^0)p59^B$X_Fyiz@0RVWz{e6VJkX}?St^bsRyvof?@N34 zAKdoXKaM#1zNTC^RLOkPfE3UFfRp_*t+SC#eEM=V4S(EfG#@>bmC5RjgmJ@7i;dUX zh1V>F7a)vx5xM06xCr#*Nj~(2{l*3%V`~F4w}0ukOOGkR@2jFqkw)G`r}u4_bwDl2 z1?nN}@J3Vq{^)E4Hf$zN%El1l)!3_qj1BZ zSyZm>$VziMyIUfI+N^VSHaRa-)zto+AR&Ct4?!Z4hSVsDHOZ>`RX6CH4Q>JLoA4sf z0tOSJHTM46P0Z3Ts9Y z-Ztm!#}9o7)shSJ=EkXEAC%aWkc5KDUe8-|;;l%{4Q}>3ro;XZ5-lXYUkzDPWcHp( zZMk5Ho05(NrU73DVBat#j^IgFvH|j(l0aBH%#y8FPmDAefk#Jvm7{QMrR2=sWH31o>(dX_lXwlEZg{6{i3k zhk1G57=Xf)o`$&_S7D)Oa^U9%Y}Eg?#5dqO`d>xJan$`$vXb#qp3r@n;y2|F z!b6)7BjY4ohpvyl-`3j7Ndm8wP>|JkkNCL`*D8s+SC z|N32)M2!o~#aL1;i;E~OmjB-iD3mIP9#!B;;)GPIx_4e}ZW(I4w4oadj>t-wFM84Nk+J^h`U8{o(VIGBLYUo1KL(*~>6O5r12!nqvVY!kq#RzTPk2#?ktc0L17@xdkb}n~acmLn%tQGAYBu z_@xOL0LySt2*U>B&WBd5Vbv&?-YZ}-9R4CPV1nRQS^8ZCegtWC(n@qfs+MfC;t?92 zbPVt?9*6y${`h*0CJa0WsqKdvDYCAn5=qlk(=iNOmEM=PIR5YrGycPfACwdR71lQ9 zKn9im0?Z_AH;?y71i5GMHLu9;3o~F~)GLRXS2WUOL^2w>-Cp`&9=5MXHCOWpk^OA> z!?uGFuoD3OFx3`IfTM&}EFY_LyDO%=u0~%zUlB$x-Ryr!p*NxN6uJKa@CpKGh~HG> zeg#x|6HoLPj;b3BWo}1$qtplzHD{FN!w>*WYOj>0R+px{Vp*A>kfa5v*%o#CUmY$&)%B zbvjV_V>~10U*acfulC0SbKmN8eVacDy<1impeY9@*5`!;{J+fz_I3hH_&a|L$2U6; z^k;8ZwVQE0B%LtOg?#&GBq6H#Pv+-;d&B=RI{fqZ|9ihGlF0Wy`~N_wknf6n4N%W> z(E^kU!W1*y#JhRJ9m6*nZwT`Priy=Nab3UrBCN#Hf`lOp0TYt9HV&c4(i&t~)H)*N zDMfo6j!UN!Vp|D}VuS?>Z{?cvV~_aMwysVv;>z9>Wknr0W~^t7%9OsxGXPDMdS0Eh0SiA_WRN~f}Jin^mQ!ws(G{_ zhJKvJ=0>EWi|co$)KbWCb-*T-P4Ou?7n!fKY&YKaF#>$|I1k11T%GKCUg%$=jGx88 zj%*@cMEHALV1mCZtZP5#%&)D+T_Ze{Yrr@yl_esXJbZI!o|p3A-g45wV-Psa zNP~{Wv*)h$Lx4CCB-2SsQa&poDhSuudI@1;8d82N2Faq+_s-N&(5+cW&x@}7@mi_w zalPGDuNVES&Zlc2?EqRC^a!PaG|hB1N!_p$moBHOC?KUk;KC~3N?8C`fJ7e>aC(U$ z&znIB7cM0=9nZdD=aex*ktLF&vgpY!MZb;j;m8H{@Pr?W1hE^oj(FTpxQt?dB7Ged zg8*hm1dH`Y*mVo|Nr=E5cyW$14)heNt*zav#w#>&OrBnYXnNm!XpU)Er5OarrpAXV z``gW!_XrDh!Q{_R;?FIHjGTpP=sCL+WiHoFWRcP6BD=dRY)+dQl2?B^1^yiEB11fHgdZxk@#0_`d|yRON%q{QWr`Lq53kn~7! zcJAk6v>LaoI>S4`#q`Fqb?~KHxwNckGUCu{BE`HS*0tdp<=B0vw@hRZ>5{m|f8@8PwdrA%O}XM8!F6#x`z3I&5b209qQ zmyb2{jV6;ER@xQww@9yU*sl~Qlp*oMC6dBLD|wJe=mK)BS0f|FQvuF*Q%4$VHg_DN z*K{HlR$uJdqOw@l6?xWVWo>?__;xv7Idk5gQexTn?LVn{^~tF5S-;^-G%LV?lcJcDHW8CbZ@0Tx~H zk>E$ULJ25YQ|BKlaySX;L-#Y~XPxxMm8KUWqUbq7hr}^g2>6Y698An|RZPUxFm`st z>@br|f(jD{gPf;+Ldq*lvAsYre~y+tYT}Q$s3;s2mD?WNY46Xpso-q-u*BbY*7Vt1 z+@MZlaqVSfqEgtLYdj8)EyPz^hf#C2kb847ANe&IDJymu`tL&X8g6_S4F65LYM0~O z_Op6&LcO~hYR)p}H>Oqxi-&WL84=45c(-+hIQ2yn3nyf>J>LSRI?kS3Ih^+d;F#<) zGYK`}wzkjOt*vu&s$w~Z;(w*CBGT3gfG-l5d$;m(hKqf#GpxlC?$sfK`nq;K7TCI}VbEkbWkZnblHqAx$&dDN-)xR2cekD5G`ow{u605Mib98OPcK8JU$7jANM`9Er|6xA0N z3W~V8>z*D8=5BDXu1`h~drW>Uc)-?b^~j9}&azu??mu1gG;EMwq~fsDvS)E(;6DeD zWO#tz$fxXR4FIKC2bns+lIt)9_UkwCQc~DUjUVB*ZW|rc8P(e!PNvvP9Z|4u5!?61 z^|I+g4C6PUfpp*YRe>6TOmjMO>sX&I-b=w@`J;F~eeuOZqbV4QzbP*4MtLEXQ2yfn zqSHP7%t-6voi+G`!NEhY*Gmg5tb^=VI4&as!-6L`CNY@oJGrS$ z1(Zd}9>B+&kNZqeOrFspxB9`-|a6~CP%!oT}{p_n;TQo9TR^d{-_V(birKA@5tPilqFVTrHENr;Q77F zs@q{>iJXzqeZ2-^brK?F`2H=Oj}QeIWD-b3b{e_hKvJ zH^IPIo58i=STxI|XK!za(@1lVc+;02RNoUG5RgSNtxV86rEB2~yg#24j|E~TB{Ee6 zT|N$;#&)GYSHO-f7Q5~(NSNBz+dSy}u^)RhnSU~)1ZlKKOh0PkQ&K8|6h=Xso&@pQ zE~rFtaaCtMySE_ZC)}QG5?a<&RAK1LEwspAGrtDMqoFG;m+c=ns%%XWrQCM?N)WW4 z&+MO9EEt^m&ObXkB4+G+7nJQV96Q!Ii2=~1U-Ktzr4%9Mn>9YdavysHzbLU1wV%V) z>s)!7mKq;+_#zP6LZ4cDq_pHH_yEj=8y_3 zyD!W?KhV+EpU>id%WyLpdfQ~jPmX{y=v+IpHY3Xd6Ot70XSyH5Br@l`x)guug|-YG zivkV~P8|P}^XoD|`}^*abWdm&WdVm=3)OxiPRnI4Uf6&{=0|?`7#gagrJ6d6?@y1+ z&(3#D&_o~-6&+VrcW2N*VSd_RP!xG}_IEt;Nc?XD3#^JW(`Rd+kT2J=kuU#nk3*zuk$+NOT;lV4dGi)Q%DK~_EmkA1VJqE zXdd=OK0XRFbJy#}WC%oWEv4=m_zNiZ>Cnr2*>yk?dhKmIPx)B=M04rwt!}2r=k{~U8Fuuo+#lA)urNSZDM5`- zpCaiuE@k*SayevKuAE2$kC%Z_Bg(LDF=+C>VJ|j1w20#?sejWBRa%=7*O(+%yhASG zmv8G+MQ+-(*4rCHWkv%RCO8hA=Q$9uFv!26;znga9%wlGW-jWBrjGSY9(%!xNAnWy zj!@*+1YZY#M`y_JdsVy8K~g!LN86fY*AWO!prg}5;cM3^vsM%=b(N=S53cu$;ui^7 zcoKxOrt<8hylxbYxKTLaf02M(QAM^DR}P)4*uv&?G@w;6W*YnQ;& z)rJ{W22(HvtFcq<1w_L1jj*)LsbXIBKS0L|U5K-qBaX9L@KU92GF*{(a1WLCV=6os zYu~+IvZ?ovud|wxY+MKmLf`|l!^?47AHi6GiI)$gEEd|p@l36E)!^UYvUBEjJh|Bl ztpX$nN;yYo!tz1yBvB_X=Q#ijHz7Pf>dLA_v@He65-&8e-es82_3_IWrBqWmLylHW zMmtz|Q2h@dL0@eCbN$iw9lL-Ce)yTGko-(<80*v?YKb&bcJ_4clh*W}p|o9HOFVSU zi~WdFo||Nt+j&xxNp1zGnPL?vb0o!{OlRpc9|fYb#d=;`^|za85gc^s#7~!>VXsl> z@_hw8?QtggIiP}3vP`N|AGj3hadD9pb;#ey%1xvIWT=phuU*SIHk04F&K14-qLKMK z*XxwAIbh);x}p?B#GQ!x2R9Gtfo$9C>Y7;nXhx&JuL$CHEi<1Rs6X7fCiR`4@wt{k|Bw~snTKhruYPE&{dDtDuH zY{qvi#cV0RQ&MjphKN7c8Ph@(iEU1e4c%J3sCYD#`Jq|{Hr#ch*09fPm`jK`{$T$? z8jJtu`1#jtjmJqcfBHcav?A02_3=xF<3=JmcC-jG5Q3ZS{Y)%^Z0H_DltN|JxX-}? zCH3vi$OsI`J)9Z_+!eK>|8&EPPlMm-(*xQXKF6ALUV|`CUZi;P;HEEiO%xJio{wGK zpnUly*S8y8R(COcfn|0kRQ|YvK*SdoEf$usFeSOKVQo8~Xp+Igz9}m|zs8%GOS_pc zYxf=`dB+%NKekhRFR7?xB#3e_S2+31(Vo=t682_ld(OpsBRa`|N0@~QqlWXOw?EqPYfdfi}Ir8cs&drB?Ic zcHn8IJbZf6l4Q9ea(nCA$40X#-d#}uwvy3S$uE3`50o`HxaLkuGF({|%MX%2XlA$7 zCJvRSckaNkKOoinEcAmf6fs|JsjP_PMYQM1oZ2rClGD?M8dtdTA~-Qh&rvAhfG-y1 zN>UNDH2=MBl_6l3&G5zl51FaiZd*WMp5PvTpHR_hV40Vr71o&N3OCP$7#ArpIe`ti zQF3#P$K@9xl0u4p?A(ku7a+%vCUjV9Ya_QtK#qjgH~OIVZJ$Nkk8Q-G^<5SZ(XAy- z#zU zJkgQJ0Wu12DlQkhLC#es>n_G|exGB8Mb63no&nC5pJg2+s(^+kHH914GCxmtal9Yd z%K`E!w0tLj>@n7y70*Q4dVJx$W;UCRK**v<#C~?o(N)eiIyQO`#(mKBW(3(LA8T#+ zz?YdFi%CV>bQHKrCa}_iPhhdpx^L0`?*BCD5E*u7p*{n>+=64J)xT9 zh`Tr$AXTr|Ro<_vMEccRy@}Kl@b^+XUVjfwYlZwu1u@e4dUX)=$~Fim?dgRA0{SeL z@1sHknB1#-7jW7>*1NI^&v$j6tNftfJ5H+#(PNg#FeFpS00ri0L6RDuVh9DLQLYQb zY>02$xDpi2hCuhL4R>UO&`U+$MIaTSFQ=VE5}K~TA@9$*U=ojm}vnZroZIo zJ1S;43gfwXI{bk2>wFuPK~?T2c~+H+&(2}$c(A6zCaYs%Ra$OleJ`L8%7`%Y*D4|@ zeh`E_zL}zjmiNJR78M+l6p_2MJw!-I*P^t$1$_8*xQEi>Z_apap>rwrN$@ap;w8V# zTEAp|USW8$$x})_yXWu$u=EeCe@VfO3}o(2@0&rBMtEqeg1fCl;-e14;`63m{oN*9 zv5X=kP5T{DW-lYNnjNNi`;i`0L!tfQ(b?oo>2klETJ^re$q9>Iuo=YNh5p5D52%-N z)q%#%^Rz5U%XJ8G=GT|=t_v@Pp8v2gRaMz=rLwTr|LB8E5*1bFlJ4=|aTqUi16phX z0oosV=X(p1Y^R9(bXZ;UPf3ji4v(Y++(0m1jU!FZ*#jkw!@x4|t=xd5|7_X0(qZhd zi0g4uL3%wf&{*xbvW*eqKCc-3e9TY^$`%e37xAKua5z9>u_xz*cw>crIjlH{M?~fpM{OBGxlpm zPc6ZxO!bB3iA8gCfhhr{-@XAW3+QxH^MhzTFxboG0}T|zds)U_?t+c`XMCyKzQ@hs z-;U;$j3wbr<}IXEJVwHPrdjvU%=7vybv-KCmos|Y$WjoFI)N52Y+k;%S_s{`1M-K- zK}-=RHK7bQhhj>hv}U0+ewpqrq*#a#0F~WEl~AynUt?7iX-oB9rh-H<_~j#80QWM z6WtS;Kv*8we+7vE(i^b8{_hQ6U#oBbp%-k3Lid)77b!Ci(Ib@kN7@UqGIv!D?HAst zZ5|=xQ|7xzUiiL11jsFS$4L=S)b!(raQT7ZbDAZzZH`;uX7lO0hm*8*edqT>=|cc| zWXN{UIro}Ta_ueUJHhZT?)0xT*MoHLyL7TE%vgte&(MVMnLnern5#`x)cPHe zC;Vg8!$^bu$PVD|*CO=XbSoGgWPyiGuQ;#5{qjTH_mzO?|`V$M`Q6fxHK zB4X1Bf6VXwoT9{C>}JsaNUQZk2RtqkVe7{-z5M`iWhqd$*v6oB_J^ok?oA>*kCVpD zc|14xj+17ueqfS*1d506Nbn?!qf6}eDqQ_(#L0W=yx7m#9 z)gy?an*Gp{xko}s{Hw4@^?VLGgTu{E|F5{Ha$1TbBc(vh{Qk*7V;c6ZtvS_Jp;R4CmY#12x=~)1QFwdlZAc;)wS}C*Ef0mjP%N6i{ zY3W}bLKrZzJ_8|SL=qrdgY0-Mjo~cv?*fmLst&yNl9#n zqXBWIpf7|l=&|IjR1ok*%P%DB>1<)egzgEKa9tm0JqD?nRTK;xz4|XgjA)8(y$NHA zKBK(%{(EL>`A}KXveoN?&)QcuF1tY}_ZKfYrs0_}0owBJ8)@0?MA<0HuLOvLN=Zn$ zFl`&J-KA%fvaa4H)Hgc{PI0LnL2~!)pCm*o;~vEIUp3da|AIQi@Zs@>|3x~q0WFk& zwoWRTf{z3$;Py$hE$etEh@r(df%E?YuG?m@}kbn?@?=HfWqFd4U8`i5kNzu zH(}Uw$!}V#a}1{;0r1a5G47m(wuR`d?ae$^S%a_G`T6 zpkO3(8sBxi4Ey%xuXYMU-3Wu}Wh8mb2Z(1cC2A6`hu1*6>A%{vLonv4z_VI)9Q4@N z%`Ar3f7_t2JG8Ah!?D4~qM=-NOL?x}q?)s+O55bXev#bE-xELa)>wW2?G~z@KhU{eL4ZRB#l}PU#C`+ zHMkd=8vGYn!_+jF`&kO>1=$LcM^yszrC1>x+emBl%Och< zmRr%2#{2}IpE)*w4E+G@4_@ko-OT#DH(0r2#fwx{SCGf7?t*c~eJEfAz|C8A=EQ+F z0pI`XqvF4fWgmI4V`(?z+gDMlb#Z3plW+tk!wNRj-s^a$XXyenEW?;DEr?O2NsM%K_ zvA7_8T5xQ4j>xO}P3&_Nn5IKMgsd9ZjlHud!wv`Ukg=yoFb<${C z9(P!%{y(6aEtpb3rup?>7@7WU-1x65*awqlA9)CoagRABH7WL`H7TV%z2Oog(9!b) zvfh~1)Vhx2Be6g!Mq))ShRz=MESCL>i_^O`1eSSXq0-0zj~@$Pd(sYAwvBvd<%KNI z%7mc90NNiMjss}@C&VO3L@31kXB{cT2OdDOt!#_>bFbWDiAz~FU9k3W*JP*R(JngiyuX%Ic@}|9H#bW9Qe4dYV#C77U5|}2+^&% zDb=|taF4~0jEm#)jLnA*zuM;DV9i&g|C;AF+$J=*ACS~)O4-;9+yBF-#SjtM2kMvU z!;S~0m7v@%@BZw%D0YVQt1E|15|*nEvLSumeTCy`MN!AsXQMhgnPr9kf?c9E_j9&} zH-mX?rSEG?3G#O=#6kdyY2kg-2XcbKHXO;S@7gZ;+)zL6D&cSiW_o1T0ir#F!=N5I0ruf`ZQZMZ0TGU<<3lsB`as}fCKmFjPs4X!tENcZymT5A%?SJ>%Qz-ex(p0TyO z*xb4S7k?w#Cb<6)*m?dGvO48~z)#w+c$k0~nPq&VuJv=JOcqcgsX?Bxw4hsS?F2@s zmeMtws{AJJ86r?e9Aqs*>lIvCkB8+ypqBUI6+oG<}tn~*Ee??@|5FrBv zwCnBgh7%gt3pHEZT{FP1ds-mk&HmEa;-{}AvtHdU_QC5Li9XqQ;?=RU8Ghp7KbAO2 z1ndS_-`U!Pfy&)mfZ7zYLCQ=$^|Ppc{|6+LtRlUqef50Jy4EwxgEFQjUxZvM{6vz* zM2b`ng%k${G6y<3{@To%4Z)KZ(zE+u&yuYhf86T1Lfn{!fV45Ld4P~YhM-wQ#AWWylW)K z6>FO8M!7S8#@0*bo*&QfI1Nb|*3|xrit-5wA#CbwX3W`j*w}+NAhUU19HO`zO|MA& zr2_5}qke1l1dW8`3UmPu5&`<KjeTqV_6-sG6O>I6E}*(=e_3x>qS1EWr++*S z7E|Rr7LPd8f=Eifzu|HsC@=s&L$_I)_m-O1)HQ#Tu>G~}z|aDsA0^=W=`*ZpS^yLO z)|K<|bWww{@Vn9IMXup4Sh&=>XY(S9(k&TXpm}j5v)sa#ORFP1Tt&nLYONWAhh-Dl zajNeEywvr zCa4@=`(=o_h4W>WCf$qluJv-h?T}mhZkDj^Qb1IiC;*v2u)IYZ{f6=*EpKdG9a~Wm zQl;e!A61=a@0V70d*SoM95x~$OBGx6tM%)VMHe>^FEW7N^Du#yIu19Lh6-%Ygr!*Z z{DGeDs$vJ+v*qYxfgG;oD_-J@M4cIQw_T&l(d6>#i+Fog&Py^lH3#19hj8V=%6lbhO;8_mvc$oelpoS(l}~ z#+YGgTm}ZUH9L-V8(#D)bxw%Y=UHq)A4Les+!#?-z* zxzs}Ak2vc->|gJ&dj8Mt5pg-XPH|d0FL9EF;IfPlHXH8Aq=_z zI&0+f({x_mm=iYLd{AGaU3!kcUSfVxa{{RkuKp?i#LAB)CJr~V8gogcqSKd)rQIEv zn@i(y&iTA5+%9U{_*Fv6r2A(F&s}%6VQmi6RgU0y4KRLt!*_gj;pi1kVrt)b{>PMd zFz#@w49_<$El5+hk443tlJ2Rc|7fDk*3=;zha9DAvgluJW#yDc`m9?zkFh+7)Qjic z&OZ8zrF1;tt?riNu`_wz5G;XSgn3x4-+-U*1=C#b=_PKZjZtUR~?<#-g}MSuzc~F*^V#Z_gI!KQglYZZ)MSV@;9O z$+IExeOI7>Ml|0rGL?7}d{6QD$n2{8TsghW%RbZv%+0QKdHZOY4F7J-`lm#X`Ol-A zuAjlrk4|1(+pCH8Q^>BKCumFmjk&iBt0UO9MIi(T?(PuW-5~@`&;*Cz?(QzZo!}NE zxN8>f65QS09Tu>F*V+4=@7w3Sd-r|c{c+FbA9T}QHD}eV>M=&m>GsS;llf}rt$m9E z>p{PfLC_r#l4m|KH#oQ*35Fyp+S8+AqqJoW8hHJOsDUT1UWCPScPEbl_3NkHN>D_R zUD_CD;uy6~iS(DR;QG>R^RV%icc19ppV>kZ&;58CS+MY4$JMwuQPAxwcOeFaH~75y3Bu6E?Y|+ z+YagWJz2TNi523@SbshE?CI53TuDQ$3luBp-ZbAXlVW{+?lahf_#%v^;{ok)2D34T zw)M-$SlD;yW=`nODH-Es%J+0whJAoUs4-D1hJ}5wYjIp`?l}O?XE0JyC%$rszsA+Z&95 z+SJh9DW+sk9Fs};wf5RF`VA6P#@ANNikHQK zSWyDU{R^cpzv*)c>WATalEa=5k zgTph|q;`+ZY4vwrf5rEcI6xI9sHG!qvB?%YLGJHMAyU2<`9ueL-rS--dsQlBi+oO= zL31%hZKMr{=vvCu=`CbwPb|h)5RqQUh$(A@4ZT(^Bj!z0r zNDD~F4&bc7iz(MF0AaHTm@%PM_@prA=nUmsiR@f9WVm0}v4W3j;We)I6y``yaKJI& zGjdn&Idi+2-1G1iuH~_pE4vfVVbykrn`bu2C1#ATf-ehCac zwrW2Xj{CP)iWW%JJ~9Bw#PO-ztX4XFG~E3;P_#b2bJ%%L9QO5F2{B8R_^s!pzpFGL zw+`RBnA)-^sB8?^wPc`D6b>pYTpb+I6y3jTIXBzK)2nsf{D`XJJA`)Lic-}hrlrN> z=Xofp>$^*R1xGSKhWng!%=*eLe%;;D=W`Y*tJ$93gk7Y|!61m=NJx9@7)qOZ;jSvO ztZpLLIGz%(-MBxZ5!v`eKgM17bo!5M?N^WlYU{cBgJVLbw(f~LBV75v+0g&C-Olt* zsZHP_eg5NI^t-?9H~w!R#y_`5eY0~S_)|b{0=C-zoZSi|B~@a-To-rQqsG4bu()7T zLm=Sgr12C7j|e)oXGdRfI7j6O7<3lwhsD1f7Jf)ky& zR}3o^T~lEW)g+Q%%x!E7OLC!GNx5L{8S3ksCTG?@J6Um_HS!RnhO!3IulRmpd`P=Q zd6{6G9lrVUH)Xe}*5gF7zHZ^WyRXxECRcw+!z<1$JOc76{SpW2pT>J^jq7#`p{rCL zBY)rB8$V4S@UC#wNb~cD9ht|8{TQE^) z`>YOWL^?AgcC2)~By0QTrYGGM7FKBn-+<-4xds3qeHDt3`Z5Ar)PC)i^$@QpE6l!p zMkOoHt!(DGuq-ai2l8_lhQJY89h(=I{%ZfM=UNO@?5bkq`(2bNt~Z}Bd9*n;ISbi3 z`OHE()AJI%w^Vqs`;e`ah^dAfP<$X(%@XTl7**%p z&mw6e0v|zNj)M~PJVs~FaG9{z^|h=4Y1P$NGQU+p*}LjqbRIF>T*|LAFDkuSyrp4Q z4QdX|bPHdP)pAwa1AkZs`68(}i2bD0N{P_I$)l^+Dqe472~*<5eyjQMU7T=Qn%DVx zY?|N-0cJwAyy4pTfRW{1rq}sMee7COj?-A1xDG1wR61 zBqY9m7JE-gN&k!db2zsU=O)42d)~;fdNIU28jb4_X;@NHBt2Dq8>oXEFwJcI&d_lj)4IT7`${n{oGngGOc}sgFTngH0KM<~ilY zI8^jZt=~BXY>XD8XgAY8A|fGyd?pxPcuC(gdgQy~fB*g+8+UE&r|N44zCh<>5L}(( z>{-7}nfe#DgM(lj35oVmY>6jhww|#A>}RLZuWNL_Ll_MgCl8|xkXcw_R3(Ez{ii>% z%#exX92~x?I^U4PRei(J{#_kCTZX8F8ZM)qM=pS_CPF~wo58mENzInNFgG;Lj$Yx6 zKV2+Hz19+?+J?If5iXY)Grmzm%$XdyorVXp*Irr7E7ypFH~ouT6vQtg)MR={M3{^f z&m%21^Hy5V0qIO;g*1k=cO%KpGuf@mKoc_hc`fR-E##M7=g)v!;)4S*WER~%hOs@l z-MFxNcEmiXzZQ5@ZXj-dJPZpJQMwE;h??(B)3)$W}~giO^VKiW5|9H=`i2 zv#cQY!_X=_tuy#lr|)OHnYo67#L|0|QIh&xkR2JyX!u~)&xn8ZJ|;%|kFV(AVKSfT z!z3i$|N7U#q9Z*s=pv!rX#L6daqej9m#m}m8y)HQl<+};#qs0`tH8aEZ06<)|1y~V z-Q)ht*mIV_W}m~C{o+^`7DgAQRhw4>XLQfrc4wxC5ikDfKS!O4vxd#yNG^WAl4+&O zGBR>cC%!;pgO@elDG}i+Ul(c8pQSY9)qH2o;gMXp{jre6eHuTht9_|hg6EMMZ0_Gx zVKT!73$l-G=Z34&bfYeSQwo_jRD%4lD;^_<@JO;cQXI*v*6x6;Vz4?vH zl!p}$+6wOy(iv&)=sI%`>LKe%1M9_bAxG_8$x0O9D50N5vY#oXK6#d}v1vX%SSpa( z8#_9AyH_5(Xde+IFGq%mxPgr(H=CiAkF!!RF)W6#B}Ta+l>H;wgxd8`O1&fCj77QV zSDoJHrcM*8qqJNCUkoF)j*;P!jhMncCGi|>F3z>Nru7fwsFaiyz+hMmxn96axrD@@ zp)U^KIPJ&c_n3SmA`>vWMBLIr2yq%PDbp0z@72Y_MD8$;GTYUL$q{TNdv#eJqZUa? z`iGZHm>%@o5?2j^2x&-~ zY-@f{**=Hwm-${cE#Z_)G?rWIAI1A7(*$m&Vvd|pIl{sTp!477W5zc|;m~s$euq<^ zux;B?E!0u(>LX-I>BCSR&~c)<`P}Y?M!)8+~VZS7v3Wt3|fsK~_gi%Ms zLVjs3?btQr#YZigTLaCg$#+MMNVu{#ttXVC*|#q#ULqm(ehQO53|m6pwKMPlicUu$ zyaR6~@i$*L)zYgIA}+P6g#=@R1r{NZ1WvrTq!=*2YCVIB<5le|vFsi>QzoKp?%$;* zc{h5pJ;O`AuGLXmmW!%|mr!C_I4pUiXNerxLqsYT&E7T3OzYAo-u`&`nP{&!qL8NKd7eu>5 zI_p{(v? z2w30qHqZ-m>{Ih{|6Pk6p&A-K(=E0`eE&62mhJt$xehT##uiiG=(ZS6eFm^3MtsoO zMH`c$5)iou#hMCF0(J`dfPWjLP~(C&tyHuXc8{Rxj22Zy zl1*&c`WxeIhA^rPu~xj_71mmopFzr;*>U2bhjbABUZZz4;!SWQa7>0}4RQtfm>W`t=byDVL=VvsUt@o}|7{WMU=3$0Fzx;*PP(r=CQ9Cz==#T@*%yY zbj$zsQy2>C%7ChsS!Zey=DxkD=U!|&v#ZcKW$+Vik4aA}5sCNTXNz0!!Lm7%!R$=p zTtFsP#hsp4_<^cTzOGxP{8iFMNZ2deHTq=Yj-m&;PLxxD*mbQJYPt`9re~fkY2@$~ zvWw`yun!~YQTcV7KhnDW@;~E-x5ME*x6}mOT#r79&Omx;#zJslp$o*Z$Yz?5$s}vmxDg{g3XTqw9 zq@ILydV0gTh4?5%cX>mPPgf!G)t)TdNRf2%wu(w4R~{Jzz}M~&No@`ghh&hZX87|$ z7*aw?8PvBf?}@vues?$@eiI?!N>`>coJ(LS4ZF(&;rydLKSKih^9#Z>vG6WjK5oZ< zW4k3)7*aI1?);1!;}aeT*K~h_H*TVK=`pFq@CBV)3UJB#8~Jy6Fh89S-@oYED{gJQ zi#2~8r`PzQ@(ZJ4rci$2`s>$!_BCHhtqY{k3TOpCayG6~>8o8W9(CQ2;XiwgM-kT)%W(rx#HmbZxjnCu;P+DR*|>VT&$ zcGK}B;I+?B2yVvG<5yNpt&0i!_LJObdC!vo`vQR?MfiJV8f$&YAG)ob+FVO)J=N8O zm07xfPIDG>V4wXz-GcpVC;&S8cfbDcBGW%^pAqvxmUxfZMG=*@Hz0Gri3ZLi;W17J zlD7wKLh;SaO4`d|4L}JRVjyU0P#`f{CnhJyI~!wQJT&rch#70*rs7)gi*Yz{A{3hG z6QIIvG zOg4N}gZxX2vh-3*R~vdN{X%Lt?jE=Z+ZTlKN_kt+h+(sFBlo7AyO4@Zk>LA~_TgLF z_xE98GDdfTVU(^Ur!8*e!otEJq)>BM?66b`Z@A5$;*B^4i+Z?U)l|h}sh+M^6GP$_ zSu(Dg8BUtnL}+(mi+*iQLgf8NLW7S*d4^L9|0@?zzGNUmLG;>-wHZ@_m&a z=(#>Zp)iE8<1uyqJ?cO=IB0rTK<_Q$#}exIh&DHpHg<0JI~kVK^s9Dj5M<>J{HDv? zf72gBSjtB(Cl->O^-jBCNC$opaW4wLyMZdi{&ZBaj(e`z(X-s9S4FKhATJ}7?U@-o zARN97Y~H6&oFoCy5qLm53O2%bI!7(6#KQ2^d`D0^4!x-s^9}um`?4$fay@bG?l@wi zKO1;xbb5!V>v@j#Qs;r^GcJ%4DYgE=SB&(Rs);`T+X|>g=tc_zzTOx+^eBHLd=)j- zFYUiDJM2XFqV9^r@_Jk|Dx=i+we^Vmf~%xC{SMZJmMipkJ3=|YZ&iT>BevSDA6<1P$- zt83~(I{)G2@pjU3;F)$39hf4|b&6&eVK(teDH#*ERl!VHIlBX0z1{Cwn@CyLk5u22ZMAC{=FY7Oe7d>a`cgM{`h?Hi{0 zc83I*fG-zCAdLYgdrr>w`B=A#Bw~A_^|dF;x-% zU%ror`CI7g2kv%`aWsSFeccubR<2gZMp||~_k`K9GDo;hkb_G73=W0(D$>ZwIVWim||M@yl2`INK48z$3V`@qxrAA}C`$2(aXYYd+4IhufBCf(= z+IU?)YtdCjN~*vkA;*#B(BM0LBdqAkUK8X)e)x+sB-+fe`}K6$Ntz}DSV>k}e?L(Y zyW^F%CNp>pj79ZP-Ewr)P`+|?={H@g2F6e#%M{k>8X;m$fW*W1jNnDU2JyO5D94uM zx)b3GDa-ctsEKz?ZlGOhDZ(OZ!zQ`~G#P+CfNq#Vjc}`Ex+GAXv zO~VS09nT_(fKkdk=A|~Dl(PaNIWc0*_OTAw`(;(HvE)vp9Lm}=eaMK^kOYeAx67mi zTwNglU&moC89uGoy?cBK>`qgk^0@yZAyI%aikhcX5K{S^P<6)zMTU#fTtB=yYleH( zPj+UyR(yRpQ3LY|q>x2YuP{-5%i)NcuebhEZ?zr+>A8}TMf<9(F8yf;Rb=e~r;p69 z*MdZl!x3Ebw#-dG)Mli$$K9oGK&Ul0^OK^eG`t?1>gH$SoPa|GY-sKF1-VZ3*RPHk z7#3;iBod9R5=GfwFM=JX_|DcjqqV%cyNj1imnREWgU6|(QS)n?&!fLGc^%)2D+-05 zoeKDy1Yrfp;4>k~={bjurHGkWAaL%DZe`r3a6U(n#bZ=bpG2aYuZPpFKlnFUzFFZu zN3bj{WwRj~ULcWJ=D{|Sx-%kZ3JW84Y%d#F&$+MYQxwC_0cuHS+YVJO=xP*%)sY(y0jQ&HCm#j-fS)BsEn zp00!O;Do%i?V$Ntfw&EsM9UPFa=^KxLXGe+kJo?Q_GHf0An zTE}5f)^6N<{IB!2;Y8N<4`Sol8u%(HN%7iNPV>UbY4!uGzYX;9Vi*T|92wYr3@i_N z8<220AH!)6Ji!kB+T-R!+sbWoSk$gJxMgTc47zn@Pi_<*9|eF&Natrus&L8nUICWV%q+FC^W zJTVou=0tnVI^P%o#nY%uu_Fq>(B`wzCxm+|7a`kty=H|3I;?+%Z&-e?KUVX+CmRu6 zdx7`!c(RdN^+v*?RWR*`nSQukO>~ERH(StZPU>i@`!USgk$Fza8HShR5d*3th21Eq zQ`kPXAv#zrV$E<>4cgV`qY23hQC1xStrLCNl_slo>EQ*#__84*BS+D!fV3qfw31D8 zKt3VgH}Mz1Y)lz90DjnZM@U~w%33H{*Y|zB!4$pn z?NpHy~6JDn7OGF*VE60;6pV^$g%FzyP5tm0&@RiVwO zO4?lqMaQ2FR1@>~KBGKj30__(D^BHl;k`T_m3g;2qDbEpb@rLXZuI8ET^#GJ_1>mD zr!H4MAXMQhY*)%w?cAKd#@T)5NthRbs-YE6<--qwaY;hvYxU1vNwSl@j3vJxg%!InoMoC*&%H$BbeLoYJ!78JulzO^xtt;i` z=nr)Z^_QHwZQC@YtsC%sxjOib;__;!O~Rnm7Sj<5m<+{~S1hk-+-7X&!t=DEP2)n& z-Pmc(+XpQvU1y4vZ&y^srO}lIk-_90oH-Rb<3B#}UT@&+PfylXKdYuDhueVJM+N58 zwIFASSu1xNMk<21Kx-PDXt@O|cB)p2fzSELI%O7Lz2)L!%H+|#sm~(I^_(DCiJdsB zyR`Y5d^Zm#r~x~rW+&Q3F|0Q{ji){At5qnqW>v%MrO~PEwBV;EdO6DAAZua!eY}f|@hk1bYn% zXER^d8@-#5^_uhTjguZ9#V5Dp4>>HS%X06a!9Fy?0=rX1!)F8Tz#RKrH{M=ov$>&f zIDm`bA055T$!h(dFcO>)8o5fHuHLrHvrT{Zt zpJ+x~VsXh9IbUuw0jk%1)G@yEH|^RJ;nOjsValozB*i^p5@x@wvFtgDODlR(vc*i* z1QsUEC>FUy!<+X^Xn7k5gs+?uG5`bsWQsNlTl-vp{3Cpvoo#xl&SRCf)peisVf%ZL z_%5nzp$X^d?Q6AgnXst|ft6YXAghakjD5-UouV&Dqj6Eg@3FhcnJs&0b|>=FsmF&B z+^TjQwdAqU7;mY>3NKAx(PuYSWL2ISm{bZI?t-l!CX1e}`SEWrJ+ zvwDH8=!rQ^TbU_reb}5IlBc8$RjISP3>v3l<|UbCw~vD2qj-6kPvP%yGaKO&wR>@6 z*1mpXdybdpcRfHmm}z5dDLr=g8};+BokZHnm^HS03K>jxK^AI-Ido-?1;nf0VNV5| z3-mgu_)Go#8l_7;{Dv^cL|oaVT(}D{j7waw>#Ra9K8&Ub5&n+I0<9bQc+fQ3OgFU2 zyLjMmUE_+{__!aHRhaxo(-yFA|e*Hty$Ne=K{!@i$A;wpaQORdozd zcMy(y^n_5KJnl>@eyQ1k?T_X|`oq|TAm-^mOVn5m&Tp_rT>P;Nr@;1MY3y``9rAQD zg#1-&e>@Hm>5g-O0P5qd`=RyRI0o|hLfv;enukL{OYkDN$U6cOvO&&Daf(XuL>LU4LRmQ(RHLUT4c&jX{L0|nU z>y9V(n+r5AP-O1;XxF>u!a+^w+u)EIK}wE2vcfLv8#o{%fw(}7iN3n3eh9-L=g}bA zf|52Yx4~KI@76W+$A?eoQ91`l3`h?ihVlcw{i%(ubYc<()K;$Ouz>_KC#6sW{XCrr zk_Q_0_-4@rJ#DP52&c^fMh2>Q(;eEV^I6`++o34CV|9wVdE2r5BWKGtQv4{7Sx`$JsIk53N!-=oo-^rk*_Q%W?TyKSq{s2`(o#+(oGPPBenib}ZU%exI4tOrZZ#vgInERl5j;Z-_aLV} zpFfI0G+|RUPuV#**`_!zel_%rSW2g_Z`5Nc8eVO6IJ{(0zHMJx{8cxFEl8Q&#?&?I zFCX$C&M|=?t4hKl2N<}?23fK>-DR&YQ7KqF;ZMKWw1&LxOWp9RczaA!*zafNxz4F5*DarjC7}J{vb6tHGb6#j%YbI; z2{q7~kzk--R+SVK9P~GWbLvV`=X70R1s%qOd*2NSn2u)-?b#fIhblySIOKs02p&fu z*w*R`{-yhae(}1O?qB;W^6Piu!&`H`j`WN?SGX6FjQO+LSUmaaElP&s!ob=ut(Wwk zcYd3((UCm}HFV3bU1C0`KXB`U>hQ>R>$!y#R@5UAbe`-mEIB0nWk7C0mYUPpH0W9c z1!a`G2oVe8Q-cpMY5mirF6a9elE2&Frz+g6ImIC0^AzIHeA5;;@t{6-Q?=jHG~2hHhhAc3PpKJaNowzuu+Aij?h@00Er z!=T<2D7RLoHb<0dL}Ii(qoH3(o==^wQMTk2rk|sdbn}b0BM*#pmQ+$S^5q&^P7>lv?4B~ti;ZDnCnbw+ zYUVQUF=_cf^&hi`i;lOUq)yT>LonL7W4GV?X6ekriF(mQX3a*gHy7zlY_%&l z&3FOzflp3xMbENuB65gub;{Xt(d=UQlg&h9#-OvBUKS2o$0b>31f7#lw!00iNgil| zUihQty;=!KBE0TRrPl8xt_p7jZqZD>$#OQ4G1;IC-r4D5^cmkz#@He|J@>wE8inGawnp6^+#N_ z1-Rwj^H`RFmukKsv?h~kTXn+YKY=%vczNni0x^um2KGhi;F^ql3o&d}$O_w8=H+>C zV|$bLpq=lOU~UCP1#4J@rmj051kqHp zVFCCx9f;nP8VRY%eu;E;JfPg2P*9EPnOc(RTWwke@i;*L$dvseUy?;{fCUIoP6o=n zTsEt%H<+=m@A2f?LY1$u2!#pXrGw3g2WW3^d(M2MU3M#|bpW)xA~jG(?8nN^BmmOG zz4_Hu`X|X9A{=@_c*d$DkfI0|y@wr<`j?cO#g;(K+bQ(q!sa40do{cDK%y`W;nl)Ia=)+cCh zo1u^dM3E;`X~%0{OWnU5(gXRMgY`Bl9YNEEv_Eu)i`H}{8^g>k2`#`@oBtmmy2>&g zG=To}{m--!|2x3^f9P(;sW34<)vPT7;3Gd;$CvDtSxbq`Z;dnG{+Qvo(YkSe#)%J; zLHrN)utMN}z#e`rmhDFxlCRK;9q|B+_qUA&N>)|D38%y7Uw~i!Q_N9ssUY$G`xpZs zCFoGw;(y5=${?x#We;Q9G||LcJl2}*0iMGziN#d*^w*G%!#@eLcN#Sawzja!vfOHJ zFRIO{5rh6am2dxEQ`_seRoZ#*+S}H5jchlq3{As3@jbVN@2p)t-FvI(RsM&gCBOrE zBom64WqH*nzvx_c+}2AOgP;>$Fy~kQQT9p$JYZEB#(N=syFgZ&o(l2JL~YlOoJa84 zsi`l4O%rd|jiPJlXteldDr`-=X!o_E#~lbN?AFIYg!mAp8t%XHguee@p78YS)HcQj ze&W1%foxd+PW8gvnk>dYT>bQ{<+ga$$H&&6J%>vdr(%geBP=mvWrh52d$czR(up=p zJVS17ZGY_0kK5}4e4&VUcI&9`U&GhK4tHik>-C20;eu4r!d0<4_jBCW0P>J;+y~{} zne5$P+u+)|Z@yF|JYC6d&>e_7J9MiwQ3}BH3+-y6wjl3 z^LggF_ApAYjvPebKb}oGwBoknX2$VY(+g!)4$yb+5u0>J>KWm^wA`#5#CFE0+c1gx zm*Ii_T2TEPQG`{Om@~jHpL%qdi{icK;tk^hBt;b}c!(OE>*}=JRld>c2Y(DcjsC!9 zw>pvOr){OFX?^d}L!$u@o!=#Y&@|D~nLf0RB0~)3cVck&CxcoUD%nfJ0OgC-5%CxC zBw2CQB*sgy7wRVWie9rbOAa#OC_V73Pbs)M7$oMS6+pzHykeeEnsER7imf;83g$uy zNQG-X^bZKpC>lfEHLPDIHtw=twm>5cBCLd;sS)$~>B1y-w156J3#iE;YM4;z_K z%9WS2RFB|=>iJhT0R%PfTEsDzEqT8^%=DU5Qs}ybaW%BU*Up1=FExqi+W`i4RS7R3 zp2qVO{=bwDvoh#ea~9~n`9dJjYy=+&;rMSyblz|=NyfVKkFg8kQB5Y@LYZaUXTjRy|B_Gh6$puu+pJ_9!5ZmI2QHEz|}lcldxopQ2gmLVwEs}QVg zos1PCoB3 z!N}cWq1KGuwH-_a<)tB{(s%nUv?vsHIy}2BstYa#-U`;FB^W@ruWos~PZaU{AYKgf zm3&zbO{nr`7QpfvHrQ^}3R#G>FNlc=-Jd1;*bBF2J#t{5v8@yrKYH>>8K617p}yXb zm8WrLt*_fNBbkmAG`hn-fKD%A11F(+ps75g9#cig9)txk8Z8rBP~&h$2-t(Iq>(q5 zGIC6<%3XGEG?v3k%8g+pdC?3WwJ&15Fq^P2;tLn|BLL5FT)o+GwMO$l#IFI7!P^@m zVf~y#J2VJ_pn{kn!;z5v-1WFUi7E=qe`K! zH_s3C&KN*fqoAi3CO9S%FU=~LMM}nMwiG+QKOQUmQGqS8_2w=Zg;8J}`x2uX8Il~Z z`JorS5jt&A^KISzgW1gay5iLd23l{>uj^Q;>*w3!{Mnc%#XJgtj(;-C8QZ{EretL0 z&1Kd_(4-L=jtvU`{z=zX@Z~n=^`dCm&UER!*#y;cELLL)k|`zvz;j6(YC85No`HJO!xhwo!v77 z&s$!=Rgeh3a-D%WEET=2UxDT7_3NPgeXKD*S zG9nlCuP4dvtut$xGp9In%%t@cb^(IL<%ZjMW;P)nqqCoeP$zsCf657UV--(c4ZEMf2Ic!;bD>;+)u34QC|&lm<9io>p}sAAQUSoTm%y%FK?rg?6z-`;6o9U30_ z9^rUFG$9fy+ICAJxoiotS+lMcbna)VqTXr(7>G>l4}92$1M@8x50I7)Yvt1#4d{g% zuEYVMUI8d6`{TTDWK&otDZp{>>-+9H%rI`AVZU=$6y7F`)_{jxuuYXtxD^gx4KsWn{q&UlAds-ykcV!oZ^A#^uBnY5s= zGA1E`#JhEqF+%hu45;U7ymMiMpmyGgx}53}dU+HP>)|fWpP20%18g`-yOa1tV5YO^ z-ZXmGr1@99{Mwt*$o9{CF!GcJJiCycTx^27d#hUrJdG-u~sL4T$&O-C~Nc+XkQ9&tn|slLfB;89Gp zV=1;@L)*>1{cW{|HKU?xu*8#GBN*0bL)Ra5GQeSrfx*AytsdKE;^?@&mU;-6#vhJ^ zLrl&{m58F})0f}ToF?t-2+-8~%HW$a>rn>%y=T9jmbO@$CV@9NCQ3Tc4HWOblMBPx zYh15$dpBEhH^4!_k3?WcC;BQ@uTV}nl4wo5{*u+c4d2xV^FDZQ6}8b%McE&1Y)IS# ziz}N^X{RQrs{s>Wa<@=k?c>*vpT|v@64ERNkT>c2z&716Y}{;nUSGAG*A(-0Z^w=X zkhIXTt|_R}NdS@w-)VTkVTvj$*>$fJT0QT8z--|fwqh1Ws;0TUO0PnW%@{rVo=z5G z^|;Vo75&HVnTc>KJSNi{EX9f23#w|%k9+``)K!^~CBcw>>jY@9`+%_!;0kwog&9;V z-a?%1X^tD;q-%H;J61rW(j!0KIutBAvKg6lem&2tN4r3Q$BC~0)XxmL>6Ya?hA+B2 zdphTI>cWDUUajK$idu9zKi(gXK2Q6~s>#Q-w|QP%9xK{EEsEO%IbI{NYB}6DSGgf= zI(D{MuA(L;I2#f{#pTYlo3*CT#K6v>#*}rP2brqTeyNiS`CTe@iuHcmJg(!k#VeX+ z)AiGXBB^YVEy1|*z&&!NHMbDRiUDym&=49km;<)&l*eSuqD1zR<_o!aD>{!~+ zL<5n=JK|V7GzQoQh{a!_r7sVUV)-pQp(1cu^9t&Jd{RC$n6f)J7^?jxm*YsbkIWyh zKlrnG3|cU37s=@9qrM4{@m&0M1&ZwDn#|a=U=x25{_KHE7|;eDaS4VIcc2-LtH8qK zoL)S%F!HtOkrkIktnI-QQ31#Vzcu8M=t|ISYqKc3K>VHsayzU3;Jr&2bH?i*IZoOY zE{(D=-_aU=%=*OMq;rj>%beM-lcGCxxc*A9{=@oxl@FAmVhEc98#4S61A)Cew3P@L zs>8sLPhvlO#Ps!_jv2@JMY30*Hw-2mI0awhuyKIVo@ zhr3vJ>osD}8=*|7YMWyhjc%}Mervl@$SvsTXmc_H^MH2aS&Y}TRa<;1pLj_huusp4=vIV`WVcZJN( z^apb5oQgd|a%O+Xit3K88=_hdKC*yzq?J^ObUxuBi20g{Xt!k3C))0HF^(1Gn;1Nm zu`y#UUl^sklvmY*S7`-7r(FZZu1r8{EcX>GUA2bvJgOjtL-&t3afvniHjz8aWdL05 zm4k;>gLWZ|C|R(WE}Xo(Fxk?|@4wAUw+c!;`H28cw0yUTAGcY@=k|fj^uCl&H83vt@dxEUY~CoqsW!NPr#J^k zKEn$>GQH2(qmBPqd^+`dN69Q+7rOUm(Raz^Pwzf{s>SJI>lv1A%XJFmvU@t$5ngb* zHtp`wZy|e@w5~RayG%{o6HeN9pH4ya5PM24QGhXOlNUUGH0!O?8r{L7h3rq_paC-F z&fqEEU!9LU&}#~^@|(!9pJjo#94^pkKxdHix4!fV=(-Bn&y&4$-qj*n!~ALDehr*6 z7`T(OP2k!2hrS;(Uc7v<3EX9tn4A%Fh|eblm5KfeIUdejZ{aje&*6P-Nv?PRFuuWj zV!<1D=cBbGomrRGj=c_{rUTfkQOnvUA93Sh0XWjN0OywEfqmwm-GQzo0#jA%@x-$o zqRUjXtsTY)W@Li+`OSpW?`mfRA{M#D-GA=Mk)nL-8(TTAX&1s;ZaiFCD{O8>O!tV) z5zzrcquNq-Rbw(WZ}=d^+)2bcz2F$>o$WdlVu-N`Ecp3WboVY>Eaq%7yoyo(>iFDY zsH)#-t=a&gMdaZ|S%t|Xz=3Kk@anVu$2d~`+Yn}^7jx!}k374L0a(a!jZT7Y$gd(k z96>+k9)9Paao|eBy(b<&-dV$_Jh(?8N%vrnXUJ=m2T-u1|MS!$x6f{7V6hEwn4v(o z4v Iml+QMmkXN$Gn=;*sqkDJicCaL94FH9l=u@Qqa*G+au)zt0H}Nz7ki11Er$P#KCLZprEbT;AjWe5xC#%kFM6~Q)QFZWWqqw@4qU!piHrMdhf?ZcTYpP2l57(JPj}=5> zE_*_N6M03Blb6y)bE<}^B8{p7t+hv-QLSV6$>B!J3sTN&^wxyI&$yA4&-937i4Ytp z@I5bjY0<^QeX`uzaymE_5fB@JfKUeIvfH39kz)5m9HfJjl&WfQ67^q<-32vJ`^F(08T15Ipz?;cC1=JN3F>6yewY=CA;=o-K=%D`CJ5dB6y{ zT}I1(@R=|Xhma!lc}COIIkG5rcHPtS0JZ1mvM?E|Ng(s@2R_62WRlMPSehVcl~7~_ zforbM@}g)Wx5%m{NyKXuYv7_Au$fvetXXAYouUoMg|i z&XM=j62Ni6)l*kfj)`p&g#>35t`8?jRyjuupqeV@i%+cxe1n~!* z?~*pE+`SBO&WwRZ!HbP$5fBJzRErl!{{Gnh4*k7B&NbC%MZUyPk@b(=YNw{D8>1*x(CVdq$-&N3KMr?~h{tsjPSKOWE zb?K_Gb8-e89@4{9h2u|qGU}Vu< z6BFZI(=D)f>KTg6sCmh5oi(Lvu#!%yPJ_$M*?MewtI*)k-j#z9I|oNeS+xC(fBwVp zHInA_tUzV^t{P;K-}%hpZQAKl-AUqVjyh2Q#(IE@purFxdc=n;*zxkfDz~$>v+nj? z=TTcNRp3m|GJqtn+=o+*n-(@W)#%KMu7I-`m8uuEYpkhSI8JAXdL6M-`-~+PK zY;(#H=X_d-QPNfpI^^tf0H1Ejsd*o2vdo8_yHxHaZ_6fR5EbwPAM&Y#OVccSU zxiwxrKDWK}-?M}D`ta|=pdc?$uF1<4rNfYK@C7J`@cg~`#!7rmuAyF0MyI~l8ZZ`giCbmFM$I^AYx>Ne)qy2|Asz7 zgSs$qfFrXV)?cmUnoEK`oMn-yx^ww|I=l98rr-V_Nh(96FgdKGqL9O6lY~;zbU?ny zG37L8BTSK*b0{60Dy1Ve$;_}Yr<7F^*^HTEWi!6oG~>DTJkRx9*KkFQuz3_Hk$G@V|T8_O*wNTwyCp zN#LzvO1O=(8vKyUp8EZxZ`;hXq2APNz2E0GGW+0ejAN};y0BcSRalC8i~i5Yp0He7 zq}!clF8_%7zDZNwmU-zl>G*1JT9m9SpGIBXRHYk#Kpji5IIv~ZR3_K<>Ol>;7bVAg zs9Zkxq)l%-#Mt}ZM8(tJo2NVRGW$YakIXHMG_hsMlyOZ}=etbjfUvzqA{LoB^KSV^ z)({sZWrh?QpHJMFd#301H;o9@wZIN6ZzV}^53fR<%GxC25VjB+Qg6^`f7+Qw%1}F( zD2h5^A&T6rd-kBayZfvkXtXRyn$&Qu0$89pYIEYRo>Gm?s(XofUr7<#1?NvXJ8zNI zET#25xJNpu@h0#^Lt97gHWz~TnzF-LuswS!IxTm=@&elOWWNxn(ysnSFayb$+IQ~g z>2zxtk7b};v$Kh8|L8<)2qt-Hnf`o#Lnw#~`9p`ffckSGHH)5ij z*D8VYx>itd_{F(~voAfxa1(VJn2k-9?qo29R}X2%AMmJ$g>Nx1&9?IM^Q$+jn<_6H z>60U|hMnL{8yV&plU@_tVq|~3$M;7+L9S3eJck75m@tD25$(P%PKTsOl!hn53|o4+ zp^buDqGRuY+J@0B?WAYLv!ya-@($=4K}r zV4(c79E(9s1mBu#DibmOF3tI1HhX5WEXQQmWjCDHOdB-h0~r$n5O3?^!dzj3!E;3B zWFx~Npqnq3TVrPxVXt&2BKghMN|*_pUGh?dweV@r9&1{wPECW*Qd+#kuN*`MF}|%u z;Ysv?8vDbCC0U_LJw{KSJ+m{t2gO-#mrrvxue^UBR#`i;{%u#6Snc9$SM0B;M{GLT zv4;r^vob*hpS6dBrebz(N_Y0LXG!|*1D(>gr>lRwvfeN(nFLkJX3MQlkxDtlW4#VF zeP<t($Jmz`5A;tgQ$W?8)bP(G90gCsC`O3kdc-qe&a~-bIxj zxK*w!`>vtkc+Y6_20h=wx~L#VtwE!NJ5fnKxBQfx@fG5ou;iwSYxv^G!TiKox!zj_ zJ|j1puJ1Z6|7$Dl7^0N6#i9*Zk=-6n#OOQ(<_3#6`GCMc&7WVvFvnS`>e=e~e$pAF z(kTw61p=Sxb@u2Lx~h!GoctBvDB#aZR^dCCM%eNIwrYEtGt4jOwd&Cf#h=m54SZ%C z!DmaglcS>-71zc1)}CMyJ3A_vsI|Jxbl@$-Ga_i_MTtubXU?3V>fHWbNzQIpi_=xh z1a5cPKa-rb5t>dOD{vi2uz&KH!408~KV+nLRFqp=tCY2_w|9H)NgWTU7o(o5B!vwj z2wrgh1ExdkNDMmjTMVuj@V|K@t&GSX`*^T~=S>g#@FzbeAI;yv>nUB@|$$)AM_%=I)87VU6}7)7raULwxn{s_F+x*qoAQTpRF)pkuKX^_<>d!KDV9a!*1 zA{kiX{iX= zPv54bHIVN2wO(w93ZFX~jp^J^kUO@tR6b$03x1118RXATYr{^duQ{o(AX*ZVE)Y5Gl1{f>o+Qk1{{t`k8q z-4OL2BZb{tbbe;uA6j1G^Sq2hjKe01F>Ni)HNgi2!>e_>yx(5m#S3QW_t%DPvshlB zt;9)m&=d)?6N0*BN=Wa9Adx7XeTh$%&zu`tAh%%;pR&3o!qAy(0)u6NM!_q>kYzBQ zsBfQR$YZ4aPrQ^eRgBZa*lh&#pqXx0Ix#M_it+GkOmkc2o+Lr59@cW_re?gm^Qfe3 ziL1CW!A2~b9opxP@uHgm$qL@x>fpj}-vY3pYFDqmuLo~w}cIZn{S+(=3+b7m1{H+wrBne6njn>&7FhP1H06HgSEx)C#=qt6GkFy(Sbj zz*)DL1!t~gLf#RJT6!%#wnc&l6W=z)3}yy1R)vx_NY}SSGd0St+|vtj5dG?-j5i87 zEmgW8N}WSO>-HHM9<{Se?&l|r-EhWJ(SecN27Vh6lQS*iQqQ-K-}&;wLtVWj(gW=| z|E*VN>GGRVt_Cdl=I;B4cf-1>R+30M)tpqPeGaqnkQIzT_KbUW-(lx(G%BzYfWnKy;m#|gGW6JIhTI`EC76D;z(zyPbD-KENFj)MTbf?zE)sl-;71J3 z#0+0qs|1{EajstRbOQa+!-uWv9%|B(Pbw+~*@#E!yJ5MXPsR&)^I(Cj*p#n7!z-M35H z9j+O9jMb1!CkFL&bTaDd%!>M3e(l!LQApBSINOO`77oo74lPQmJg#TVyf)u(kg;3G zab*H-4!k<3V-Pk%z3OFf`D57;Lx2#jPOFTR#5X(}skaJ>DL^dKmKSCHewdXF4E*t~ z{}Y-!D8uln1M#{xgPa95aSHNk9%;>(8YIJq7P>Klm9#8-nCNXNo!ptP-Jav>?ruNS zm~h+h!U^OVRocA6IZjwxjyf$*%g%JVy5|-GgN|3%uEB#m15%!3(S!Cs@Br?lKVGMp z>$)aJCwV*+HH@A_E{x{$G~szp4a$VE4{^^*7}NERS<^1}HUnHhReQU3=8J0xkFCCZ z%bgr8cCDo3L{!wg8l^Q%6$?gAy?F&d5ztJRgPfIec8_vgG#ms1;u=#7l3{CWE2!kB z932&x&qW929!?m7-vAu)2j{-gB=!_RVcYFL^=*-ZgsEx+6Or$~GtZ6-H$n3K=VS^M z6%{`|La9sBMiVvU-f&3;+Dg*iR5UHWxHwDir_{O@eI=8iv&gHfD#@HW!4Opqb>hd| zAoOva*J($`R#2{Qo5w|iI>a3gM{Z%F=`|1loGL4`L%6sCy=cwnbY}nJ9egzeNY}(X z!;P+6C=W$7V+Ny~o5jWQoainDtuN&hFeh)TXba(2n&8*>NeYQ9tc}n`+tv+f%cpH; z%)cqt4sT&!un;Q0@_XNmcZAmjgLdQ1%O{kTm61yVHUl%1Ah)6W&K(tWJ@4=$)&d|( zHlbZ@n>_hTr+LkJm-_iHt~`fX+znUAM(92xAG;ptoj@SeWAhss&dF?>?z)zz06iA* zY<0-BT5dzVqqV8(_>z!2(MMT|s;8NMBnx+>-bYkV1jD714Sd>GuqTIi8zKS$OwK`Y z>kS(zarL9z;aRLUA6`dUO_O_|vyiYG=-RBLB+ytc%0(i_D(fRq!%T-zqP@&Iq;@Rb zFbJ~~0PGc?DT$x$6ktM=@sdwlz`7>U(<8j2#%MhVu0SSb!0wfnvpGkupFxUfGW>I5 zuXv~qgh+#|;`(eWvWme3Qijwi`Iw!XM&9bYpl0vU*7i3@K}g3;zwWC^my^#euvGkL zS&5%<9E0t|bMNMI%bENAB=E^dqAxJ+;&9^=Ls zyWc?%bLK5Lp~d8_grVc)Qe&iuquylp~cxv2z$RfFSfzlMA_4%ybC zKSG>6`sKPp10r%9rvlO4Zj1F$4{042bu+o&115<(=CFDXP&=esNabyhgYIPGtFJuM)*3|nW3M)A`p-UNOdGh4ORCTN=$h}I0Rtb)N z=@9o3hRa+D3m)iWeuPk++&*}#H{JX=4N@aw6?+`39Jq6emuCC@(efjrm`_`#S69KF zbz9o%S`xq#0-zY|&sU{d(yQwd$ydez()?Jqb`EeHoDJ-^V(CzL5JNE*{Xt9CIlY5; zGilPbyGj?!%kcO?80mIj#fm8j9+k|89zau|>!EP8@8`!Sc`w6LKm6n?N=t&`ma+C+ z>4Ah1q9RaVu~_qwSVWs(|D=cH&_pq-J3yKPIX?Nq4K+e~=TFAvUdS#Yjprt;reyZ# zh45=@g6H1DhxDU=^b0P4yBDt9eHO`YuQ{Qa16vb+hL7)K&9t7wtY_(TP?`Cl=VErLy8M}aTAphZWWZwanaoU(xC)A_~Jc*v} zeIt^&r9sz3u-~vOc?SkxZMM>F_1YieY;EL|{rKM7hxh&?bNTgyjNP!mbC*qmxt5~= zJ1-)SrQb3R6H7aS_zU76%wP1|Fo1IQQOp61F;TBpJ1p$#k?Q4%O}fXPe!@Ei^z4vE z1#I%)`gaR5H3EDUi@s9}m)>a^`OwY9{j^Fe)Q&G-`AFeE$E$qLarAzQe{kcp+%Eh; z^`+#Clz&$m*<=mKiGb?-fE%f)z3mo5H~659J$_jjY4=b1a*`Cqf3^X;W__7S`9IG# wr-AU%eku@60uB){mE`na#Qy%$$38EwmH+r!J{&Qex(a-b+MKYiJmi`5H*{$&oB#j- diff --git a/src/main/java/com/github/netricecake/Main.java b/src/main/java/com/github/netricecake/Main.java index f8fabf0..9cadadd 100644 --- a/src/main/java/com/github/netricecake/Main.java +++ b/src/main/java/com/github/netricecake/Main.java @@ -4,12 +4,8 @@ import com.github.netricecake.kakao.KakaoApi; import com.github.netricecake.kakao.TalkClient; import com.github.netricecake.kakao.TalkHandler; import com.github.netricecake.kakao.exception.*; -import com.github.netricecake.kakao.structs.ChatRoom; -import com.github.netricecake.kakao.structs.Member; -import com.github.netricecake.kakao.structs.Message; -import com.github.netricecake.loco.util.ByteUtil; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import com.github.netricecake.kakao.structs.*; +import com.github.netricecake.kakao.util.ByteUtil; import java.util.Map; @@ -28,65 +24,47 @@ public class Main { TalkClient client = new TalkClient(email, password, deviceName, deviceUuid, new TalkHandler() { @Override public void onMessage(Message msg) { - if (msg.getType() != 1) return; // 1이 그냥 채팅, 그냥 채팅만 받기 - if (msg.getMessage().equals("!memc")) { - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), "멤버수 : " + msg.getChatRoom().getMemberCount()); + if (msg.getType() != MessageType.TEXT) return; // 그냥 텍스트 채팅만 받기 + if (msg.getMessage().equals("!count")) { // 멤버 수 + msg.getChatRoom().sendMessage("멤버수 : " + msg.getChatRoom().getMemberCount()); } - else if (msg.getMessage().equals("!pcheck")) { - int type = msg.getChatRoom().getMember(getTalkClient().getUserId()).getMemberType(); - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), "현재 봇계정의 멤버 타입 : " + type); - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), "현재 님계정의 멤버 타입 : " + msg.getAuthor().getMemberType()); + else if (msg.getMessage().equals("!type")) { // 보낸 사람 권한 + int type = msg.getAuthor().getMemberType(); + String t = ""; + if (type == MemberType.OWNER) t = "방장"; + if (type == MemberType.ADMIN) t = "부방장"; + if (type == MemberType.MEMBER) t = "일반 멤버"; + if (type == MemberType.BOT) t = "방장봇"; + msg.getChatRoom().sendMessage("당신의 멤버 타입 : " + t); } - else if (msg.getMessage().equals("!send")) { - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), "방 : " + msg.getChatRoom().getName() + "\n보낸사람 : " + msg.getAuthor().getName()); + else if (msg.getMessage().equals("!kick")) { // 강퇴 (당연히 방장이나 부방장 권한 있을때만 작동합니다.) + msg.getAuthor().kick(); + } + else if (msg.getMessage().equals("!send")) { // 일반 메세지 + msg.getChatRoom().sendMessage("방 : " + msg.getChatRoom().getName() + "\n보낸사람 : " + msg.getAuthor().getNickName()); } else if (msg.getMessage().equals("!reply")) { // 답장 - int replyType = 26; // 답장 타입 - JsonObject extraObject = new JsonObject(); - extraObject.addProperty("src_logId", msg.getLogId()); - extraObject.addProperty("src_userId", msg.getAuthor().getId()); - extraObject.addProperty("src_message", msg.getMessage()); - extraObject.addProperty("src_type", msg.getType()); - extraObject.addProperty("src_linkId", msg.getChatRoom().getLinkId()); - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), replyType, "reply test", extraObject.toString()); + msg.reply("reply test"); } else if (msg.getMessage().equals("!mention")) { // 멘션 - JsonObject extraObject = new JsonObject(); - JsonArray mentionArray = new JsonArray(); - JsonObject mentionObject = new JsonObject(); - mentionObject.addProperty("user_id", msg.getAuthor().getId()); - JsonArray pos = new JsonArray(); - pos.add(1); - mentionObject.add("at", pos); - mentionObject.addProperty("len", msg.getAuthor().getName().length()); - mentionArray.add(mentionObject); - extraObject.add("mentions", mentionArray); - getTalkClient().sendMessage(msg.getChatRoom().getChatId(), 1, "@" + msg.getAuthor().getName(), extraObject.toString()); + String extra = "{\"mentions\":[{\"user_id\":" + msg.getAuthor().getUserId() + ",\"at\":[1],\"len\":" + msg.getAuthor().getNickName().length() + "}]}"; + msg.getChatRoom().sendMessage("@" + msg.getAuthor().getNickName(), extra); } - else if (msg.getMessage().equals("!image")) { + else if (msg.getMessage().equals("!jpg")) { // jpg 사진 전송, jpeg말고 다른 포멧은 테스트 안해봤습니다. byte[] imageBytes = ByteUtil.hexStringToByteArray("FFD8FFE000104A46494600010101006000600000FFDB0043000201010201010202020202020202030503030303030604040305070607070706070708090B0908080A0807070A0D0A0A0B0C0C0C0C07090E0F0D0C0E0B0C0C0CFFDB004301020202030303060303060C0807080C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0CFFC00011080080008003012200021101031101FFC4001F0000010501010101010100000000000000000102030405060708090A0BFFC400B5100002010303020403050504040000017D01020300041105122131410613516107227114328191A1082342B1C11552D1F02433627282090A161718191A25262728292A3435363738393A434445464748494A535455565758595A636465666768696A737475767778797A838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE1E2E3E4E5E6E7E8E9EAF1F2F3F4F5F6F7F8F9FAFFC4001F0100030101010101010101010000000000000102030405060708090A0BFFC400B51100020102040403040705040400010277000102031104052131061241510761711322328108144291A1B1C109233352F0156272D10A162434E125F11718191A262728292A35363738393A434445464748494A535455565758595A636465666768696A737475767778797A82838485868788898A92939495969798999AA2A3A4A5A6A7A8A9AAB2B3B4B5B6B7B8B9BAC2C3C4C5C6C7C8C9CAD2D3D4D5D6D7D8D9DAE2E3E4E5E6E7E8E9EAF2F3F4F5F6F7F8F9FAFFDA000C03010002110311003F00FDFCA28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28A2800A28AFC03F811F03FF69AFF0082C67FC14A3F6CED1749FDB3BE2F7C15D13E0A7C429F47D374ED16E2FA6B392D64BFD52DE08A38A0BFB5484451E9E80E03190C858E1812C01FBF9593E0DF1F685F1174D9AF7C3DAD693AED9DB5CCB6734FA75E47751453C4DB6489990901D1B8653C83C102BC67FE09BDFB24F8F3F62BFD9C8782BE227C6CF157C7BD793539EF63F12F882DDA1BB8A0758C25A8DF3CF232214760D24AED995870A1547E77FF00C19B1E263E0CFD95FE3CFC1ED76DB51D37E217C39F89735E78874FBA88A9B1FB4DA4168885B3CC827D2EF1597F8760FEF5007E8C7ECA7FF0514F869FB667C6BF8C9E00F03DEEA975E20F815AE2787FC50B7564D042972CF711FEE5C9FDE2896D2E109C0E6227054AB37BA57E247EC3CDA27EC63FF077F7ED09E028E4D7B4AD23E33F87AE353D22D6532C96FAB6AB73058EB77131E8BB15935708E7210EE8C1C922BF407FE0AE5FF057FF00871FF0497F80F36BDE24B9B6D67C6FAB42CBE19F09C370AB79ABCBC81238E4C76C8DF7E523031B577390A403DB7C25FB617C30F1E7ED23E21F841A378DB43D4FE25F84F4E4D5B57F0FDBCC5EEB4FB666440EF81B461A48832E772F9B1EE037AE7D26BF273FE0D93FD823C67E171F15BF6B2F8C9A19D23E2A7ED11AA4FA858DB4D6FE44961A55CCFF006D96454DD98D6EAE5D5846E32B1D9C0C0E1C8AFD63A0028AFC2BF097FC1CF7E23FD97FFE0A2DFB50D9FC78BCD635EF841E00F185E782FC2BE1EF0AF85EDA4BFB5B98AFEEA18666BA92485361B7B198C8B34CCEF24AA625091C807AB7FC46ADFB2C7FD083FB407FE08F48FF00E59D007EBF515F9E3FF0496FF83863C23FF0575FDAA7C71F0F7C1FF0CFC5FE18D1FC2DA1FF006F59EBBAB5CC2E6F6313C103453C11065B794B4F945134A1D6290E576E2BF43A800A28A2800A28A2800AFE69BF647FD90BF6ABFDA47FE0AD3FB707887F658F8D3A67C27D73C0DF176FDB59B5D5AFEE61D375C8EE755D6FC969A18EDEE61B83098240A93C2CA3ED0C415390DFD2CD7E40FC4DFF00834EAD3E26FEDDFE30F8B0FF00B4578C746F0978E7C77278EB54F0A695A335A5CB4EF7335C044BF4BC015E37B89C4737D9CBC6B2B01C92C403A6BA3FF056CFD96BE04DCDB6CF80DFB49F8D75BD502C1776F241A6B7876CD616DCCC8EBA5C3333C8C9B7018C7E51DC24127EEFE79FF83587C49F113E04FF00C150FF006B8F841F1BF43D534FF8D1E2FB3B2F1BF88249E5B79152782EA479CBB42CD1B19CEBB04A8D1128543107056BF77ABF193E18F8B2F3F676FF0083D0FE2259EBDA1EA090FC79F87B158786EE81511C9141A4E9D70F72727263F3342BD838E7CC038C026800FF0082EF7856FF00E087FC17E7FE09F3F16BC3BAE5ED8EBBE35D7EDFC07770A227971D845AADB47300482499E0D7AEA27F45518C139AF60FDB2FFE0D4CF807FB6A7C7BF1EFC4EF1078EFE3459F8BBC75732DF3797AD59DC5869B3BE0AF951CB68D2F92A4604466C042554A00BB7C7FFE0F2BF0ADFF00C3EF80DFB3BFC75F0F6B97BA378C7E167C42363A2B40885629AEEDFEDCB739607E78A5D1A0DA3041F31B3D057B27ED77FF00075D7ECE5FB197ED27E2FF0085DE23F097C69D575FF04EA0FA66A171A5E85622D1A64FBC233717B0C8CB9E8FE585618652CA43100F8EB505FDBA7FE0D98D734EBABAD5350FDA7BF65EB3F344D0C31DC13A1DAA2801A5678E69349009CA85925B538C13BD801FB43FB09FED8FE18FF8280FEC97E0BF8C1E0E86FEDB40F1A5A493436F7B1ECB8B59619E4B79E17C704C73C32A6E1C36DC8E08AFCD4D57FE0F41FD93F5DD2EE6C6FBE1C7C78BCB2BC89A0B8B79FC3FA3C914F1B02AC8EA7522194824107820D751FF00047BFF0082D0789BFE0A1BFB65CBE00F815FB3F68DE06FD92FC11A5BC53EA92D9A6997BA2CE6277863486DA46B35F326F945B4419821794C9C6DA00F953F62EFF829C7803FE08B5FF053DFF828BB7C68D27C6B16A3E2CF1F45AEE91A668DA5ADD5D5E5A36A7A9CC92E5E48E24578755B3954C8EA1964E0EEC29FBCBE047FC1D55FB16FC6AD274D7BFF00889AC7C3FD5752B8FB3AE95E28F0F5E4535B92D85796E2D927B44439CEE33E00FBDB6BC53FE0BCFF00F04E6F8A9F073F6C0F08FEDE3FB3669F0EA9F103E1D4313F8BBC3E96E649359B5B789E26BADAAC1E60D66C6D668D0893C95428432B1AE3BF66EFDB17FE0965FF000554F83961A7FC57F879F03BE127C43D641D47C43617FA6AF84E54BB46DD2491EB96EB6E24491C960A6E43B8387426803F57FE0EFEDD1F04BF689F159D07E1FF00C62F857E3AD7044D39D3BC3DE2CB0D4EEC46BF79FCA82567DA3B9C6057AA57F343FF000538FD82BFE09FEFFB6AFECB1F0DFF0067FD42DF55B3F8B7E2C8FC35E2A93E1FFC4B8F598F48827BBB3B686776B917FB6766BA7651BD14ADB38284B075FD5BFF008255FF00C1BF3E12FF008247FED4FE2DF1D7803E27F8EB5EF0AF89FC36BA20F0CEBA9039867FB443335E493C2228E56021D918FB3A945965CBB6EE003F40E8A28A0028A28A0028A28A002BF2ABFE0A5FFF0004E5FDA1FE2C7FC1C01FB317ED07F0A74AB67F02F8234FD2F47F146AE356B4B7974DB48F53BF7D4236825712C8B3585F4912F948E496607670D5FAAB45007C63FF0005DBFF00825BEA7FF056EFD8757E1CF87FC47A7F867C4FA16BF6FE26D1A7D415CD85CDCC305CDBF9170C8ACE91B477527CE8AC55954ED61907E9FF00D9F7C2BE26F02FC05F04689E35D723F13F8CB46D02C2C75ED6635DA9AB5FC56F1A5CDC81818124AAEF8C0FBDD0575F450014515F991FB5DFECC3FF00054BF1B7ED27E2FD4FE10FED1BF033C23F0CEEF5077F0E6937BA4466EECACFFE59A4C64D1EE98CA07DE6F39831C9010108A01FA6F5F2DFED53FF000450FD957F6D3F109D63E227C12F07EA5ADCB7525EDCEA9A6ACDA1DFEA13480067B9B8B192096E49C0FF005CCF83C8C126BE09F007ED07FF0005A1F853A1BE87A8FC0CF837F132E2CAE2551E21D56FF4AB79EFD3710AC12D756B38C26065736E8F83F30CF00D3FFE0B6DFF000515FD9C7C79A8E87F18BF607D4FC7339B78A6B46F8756BA97D960DD93F3DE5BFF006ADBCA703EE2B2329FBDD71401F6C7ECD1FF00040AFD917F640F8CBA4FC40F87FF000734FD27C5DA0B349A75F5DEB7AA6A82CE4231E624577732C4241FC2FB7729E54835F6157E40FF00C4477FB53FFD231FF680FF00BFDABFFF0028E8FF00888EFF006A7FFA463FED01FF007FB57FFE51D007EBF515F987FB27FF00C1777F685F8FBFB46F83BC17E2AFF827D7C75F879A0789B53874FBCF12DD9BF7B5D112460A6E66F3F4BB78C4499DCC4CAA7683B433614FE9E500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145001451450014514500145145007FFFD9"); - getTalkClient().sendJpg(msg.getChatRoom().getChatId(), imageBytes, "jpg", 128, 128); + msg.getChatRoom().sendJpg(imageBytes); } } @Override public void onNewMember(ChatRoom room, Member member) { - JsonObject extraObject = new JsonObject(); - JsonArray mentionArray = new JsonArray(); - JsonObject mentionObject = new JsonObject(); - mentionObject.addProperty("user_id", member.getId()); - JsonArray pos = new JsonArray(); - pos.add(1); - mentionObject.add("at", pos); - mentionObject.addProperty("len", member.getName().length()); - mentionArray.add(mentionObject); - extraObject.add("mentions", mentionArray); - getTalkClient().sendMessage(room.getChatId(), 1, "@" + member.getName() + "님 안녕하세요.", extraObject.toString()); + String extra = "{\"mentions\":[{\"user_id\":" + member.getUserId() + ",\"at\":[1],\"len\":" + member.getNickName().length() + "}]}"; + room.sendMessage("@" + member.getNickName() + "님 안녕하세요.", extra); } @Override - public void onDelMember(ChatRoom room, Member member) { - getTalkClient().sendMessage(room.getChatId(), member.getName() + "님이 나갔습니다."); + public void onDelMember(ChatRoom room, long userId, String nickName) { + room.sendMessage(nickName + "님이 나갔습니다."); } }); diff --git a/src/main/java/com/github/netricecake/kakao/KakaoApi.java b/src/main/java/com/github/netricecake/kakao/KakaoApi.java index 519d203..7f883b0 100644 --- a/src/main/java/com/github/netricecake/kakao/KakaoApi.java +++ b/src/main/java/com/github/netricecake/kakao/KakaoApi.java @@ -4,9 +4,9 @@ import com.github.netricecake.kakao.exception.BadCredentialsException; import com.github.netricecake.kakao.exception.InvalidDeviceNameException; import com.github.netricecake.kakao.exception.InvalidDeviceUUIDException; import com.github.netricecake.kakao.exception.UnregisteredDeviceException; -import com.github.netricecake.loco.packet.inbound.login.GetConfIn; -import com.github.netricecake.loco.packet.outbound.login.GetConfOut; -import com.github.netricecake.loco.util.ByteUtil; +import com.github.netricecake.kakao.packet.inbound.login.GetConfIn; +import com.github.netricecake.kakao.packet.outbound.login.GetConfOut; +import com.github.netricecake.kakao.util.ByteUtil; import com.google.gson.Gson; import com.google.gson.JsonObject; import com.google.gson.JsonParser; diff --git a/src/main/java/com/github/netricecake/kakao/LocoSocketHandlerImpl.java b/src/main/java/com/github/netricecake/kakao/LocoSocketHandlerImpl.java index 883b51f..4b21393 100644 --- a/src/main/java/com/github/netricecake/kakao/LocoSocketHandlerImpl.java +++ b/src/main/java/com/github/netricecake/kakao/LocoSocketHandlerImpl.java @@ -1,21 +1,15 @@ package com.github.netricecake.kakao; +import com.github.netricecake.kakao.packet.inbound.member.*; import com.github.netricecake.kakao.structs.ChatRoom; import com.github.netricecake.kakao.structs.Member; +import com.github.netricecake.kakao.structs.MemberType; import com.github.netricecake.kakao.structs.Message; -import com.github.netricecake.loco.LocoPacket; -import com.github.netricecake.loco.LocoSocketHandler; -import com.github.netricecake.loco.packet.inbound.member.*; -import com.github.netricecake.loco.packet.inbound.message.MessageIn; -import com.github.netricecake.loco.packet.inbound.room.ChatInfoIn; -import com.github.netricecake.loco.packet.inbound.room.InfoLinkIn; -import com.github.netricecake.loco.packet.outbound.member.MemberOut; -import com.github.netricecake.loco.packet.outbound.room.ChatInfoOut; -import com.github.netricecake.loco.packet.outbound.member.GetMemberOut; -import com.github.netricecake.loco.packet.outbound.room.InfoLinkOut; -import com.github.netricecake.loco.packet.outbound.message.MessageOut; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; +import com.github.netricecake.kakao.loco.LocoPacket; +import com.github.netricecake.kakao.loco.LocoSocketHandler; +import com.github.netricecake.kakao.packet.inbound.message.MessageIn; +import com.github.netricecake.kakao.packet.outbound.member.MemberOut; +import com.github.netricecake.kakao.packet.outbound.message.MessageOut; public class LocoSocketHandlerImpl extends LocoSocketHandler { @@ -30,100 +24,42 @@ public class LocoSocketHandlerImpl extends LocoSocketHandler { if (packet.getMethod().equals("MSG")) { client.getSocket().write(new LocoPacket(packet.getPacketId(), "MSG", new MessageOut().toBson())); - MessageIn in = new MessageIn(); - in.fromBson(packet.getBody()); - checkRoom(in.getChatId()); - checkMember(in.getChatId(), in.getAuthorId()); + MessageIn in = new MessageIn(packet.getBody()); + ChatRoom chatRoom = client.getChatRoom(in.getChatId()); + if (chatRoom == null) return; + Member member = chatRoom.getMembers().get(in.getAuthorId()); - ChatRoom room = client.getChatRooms().get(in.getChatId()); - Member member = room.getMembers().get(in.getAuthorId()); - - Message msg = new Message(in.getLogId(), room, member, in.getType(), in.getMessage(), in.getAttachment()); + Message msg = new Message(client, chatRoom, in.getLogId(), member, in.getType(), in.getSendAt(), in.getMessage(), in.getAttachment()); Thread.ofVirtual().start(() -> { client.getTalkHandler().onMessage(msg); }); } else if (packet.getMethod().equals("NEWMEM")) { - NewMemIn in = new NewMemIn(); - in.fromBson(packet.getBody()); - checkRoom(in.getChatId()); - checkMember(in.getChatId(), in.getUserId()); + NewMemIn res = new NewMemIn(packet.getBody()); + ChatRoom chatRoom = client.getChatRoom(res.getChatId()); + if (chatRoom == null) return; + MemberOut mo = new MemberOut(res.getChatId(), res.getUserId()); + MemberIn mi = new MemberIn(client.getSocket().writeAndRead(new LocoPacket("MEMBER", mo.toBson())).getBody()); + chatRoom.getMembers().put(res.getUserId(), new Member(client, chatRoom, res.getUserId(), mi.getType(), mi.getNickName(), mi.getProfileImageUrl(), mi.getFullProfileImageUrl(), mi.getOriginalProfileImageUrl(), mi.getProfileLinkId(), mi.getMemberType(), mi.getProfileType())); - ChatRoom room = client.getChatRooms().get(in.getChatId()); - if (!room.getType().equals("OM")) return; Thread.ofVirtual().start(() -> { - client.getTalkHandler().onNewMember(room, room.getMembers().get(in.getUserId())); + client.getTalkHandler().onNewMember(chatRoom, chatRoom.getMembers().get(res.getUserId())); }); } else if (packet.getMethod().equals("DELMEM")) { - DelMemIn in = new DelMemIn(); - in.fromBson(packet.getBody()); - checkRoom(in.getChatId()); + DelMemIn in = new DelMemIn(packet.getBody()); + ChatRoom chatRoom = client.getChatRoom(in.getChatId()); + if (chatRoom == null) return; + chatRoom.getMembers().remove(in.getUserId()); - ChatRoom room = client.getChatRooms().get(in.getChatId()); - if (!room.getType().equals("OM")) return; Thread.ofVirtual().start(() -> { - client.getTalkHandler().onDelMember(room, new Member(in.getUserId(), in.getNickname(), 2)); + client.getTalkHandler().onDelMember(chatRoom, in.getUserId(), in.getNickname()); }); - room.getMembers().remove(in.getUserId()); } else if (packet.getMethod().equals("SYNCLINKPF")) { - SyncLinkPfIn si = new SyncLinkPfIn(); - si.fromBson(packet.getBody()); - ChatRoom room = client.getChatRooms().get(si.getChatId()); - room.getMembers().remove(si.getUserId()); - Member member = new Member(si.getUserId(), si.getNickName(), 2); - room.getMembers().put(si.getUserId(), member); - } - } - - private void checkRoom(long chatId) { - if (!client.getChatRooms().containsKey(chatId)) { - ChatInfoOut co = new ChatInfoOut(chatId); - ChatInfoIn ci = new ChatInfoIn(); - ci.fromBson(client.getSocket().writeAndRead(new LocoPacket("CHATINFO", co.toBson())).getBody()); - ChatRoom room = new ChatRoom(); - room.setChatId(chatId); - room.setType(ci.getType()); - room.setLinkId(ci.getLinkId()); - GetMemberOut gmo = new GetMemberOut(chatId); - GetMemberIn gmi = new GetMemberIn(); - gmi.fromBson(client.getSocket().writeAndRead(new LocoPacket("GETMEM", gmo.toBson())).getBody()); - for (int i = 0; i < gmi.getMembers().size(); i++) { - JsonObject json = gmi.getMembers().get(i).getAsJsonObject(); - int type = json.get("mt") != null ? json.get("mt").getAsInt() : 2; - Member member = new Member(json.get("userId").getAsLong(), json.get("nickName").getAsString(), type); - room.getMembers().put(member.getId(), member); - } - - if (ci.getType().equals("OM")) { - InfoLinkOut lo = new InfoLinkOut(ci.getLinkId()); - InfoLinkIn li = new InfoLinkIn(); - li.fromBson(client.getSocket().writeAndRead(new LocoPacket("INFOLINK", lo.toBson())).getBody()); - room.setName(li.getName()); - } else if (ci.getType().equals("MultiChat")) { - if (!ci.getChatMetas().isEmpty()) { - JsonArray chatMetas = ci.getChatMetas(); - room.setName(chatMetas.get(0).getAsJsonObject().get("content").getAsString()); - } else { - JsonArray displayMembers = ci.getDisplayMembers(); - String name = ""; - for (int i = 0; i < displayMembers.size(); i++) { - name += displayMembers.get(i).getAsJsonObject().get("nickName").getAsString() + ", "; - } - room.setName(name); - } - } else if (ci.getType().equals("DirectChat")) { - room.setName(ci.getDisplayMembers().get(0).getAsJsonObject().get("nickName").getAsString()); - } - client.getChatRooms().put(chatId, room); - } - } - - private void checkMember(long chatId, long memberId) { - ChatRoom room = client.getChatRooms().get(chatId); - if (!room.getMembers().containsKey(memberId)) { - MemberOut mo = new MemberOut(chatId, memberId); - MemberIn mi = new MemberIn(); - mi.fromBson(client.getSocket().writeAndRead(new LocoPacket("MEMBER", mo.toBson())).getBody()); - room.getMembers().put(memberId, new Member(memberId, mi.getNickName(), mi.getMemberType())); + SyncLinkPfIn res = new SyncLinkPfIn(packet.getBody()); + ChatRoom chatRoom = client.getChatRoom(res.getChatId()); + if (chatRoom == null) return; + chatRoom.getMembers().remove(res.getUserId()); + Member member = new Member(client, chatRoom, res.getUserId(), 1000, res.getNickName(), res.getProfileImageUrl(), res.getFullProfileImageUrl(), res.getOriginalProfileImageUrl(), res.getProfileLinkId(), MemberType.MEMBER, res.getProfileType()); + chatRoom.getMembers().put(res.getUserId(), member); } } diff --git a/src/main/java/com/github/netricecake/kakao/TalkClient.java b/src/main/java/com/github/netricecake/kakao/TalkClient.java index 02bb28c..36fada9 100644 --- a/src/main/java/com/github/netricecake/kakao/TalkClient.java +++ b/src/main/java/com/github/netricecake/kakao/TalkClient.java @@ -1,25 +1,34 @@ package com.github.netricecake.kakao; import com.github.netricecake.kakao.exception.*; -import com.github.netricecake.kakao.structs.ChatRoom; -import com.github.netricecake.loco.LocoPacket; -import com.github.netricecake.loco.LocoSocketHandler; -import com.github.netricecake.loco.LocoSocket; -import com.github.netricecake.loco.packet.inbound.login.CheckInIn; -import com.github.netricecake.loco.packet.inbound.login.GetConfIn; -import com.github.netricecake.loco.packet.inbound.login.LoginListIn; -import com.github.netricecake.loco.packet.inbound.message.PostIn; -import com.github.netricecake.loco.packet.inbound.message.ShipIn; -import com.github.netricecake.loco.packet.inbound.message.WriteIn; -import com.github.netricecake.loco.packet.outbound.login.CheckInOut; -import com.github.netricecake.loco.packet.outbound.login.LoginListOut; -import com.github.netricecake.loco.packet.outbound.etc.PingOut; -import com.github.netricecake.loco.packet.outbound.message.PostOut; -import com.github.netricecake.loco.packet.outbound.message.ShipOut; -import com.github.netricecake.loco.packet.outbound.message.WriteOut; -import com.github.netricecake.loco.util.BsonUtil; -import com.github.netricecake.loco.util.ByteUtil; +import com.github.netricecake.kakao.packet.inbound.member.GetMemberIn; +import com.github.netricecake.kakao.packet.inbound.message.PostIn; +import com.github.netricecake.kakao.packet.inbound.message.ShipIn; +import com.github.netricecake.kakao.packet.inbound.room.ChatInfoIn; +import com.github.netricecake.kakao.packet.inbound.room.InfoLinkIn; +import com.github.netricecake.kakao.packet.outbound.member.GetMemberOut; +import com.github.netricecake.kakao.packet.outbound.message.PostOut; +import com.github.netricecake.kakao.packet.outbound.message.ShipOut; +import com.github.netricecake.kakao.packet.outbound.room.ChatInfoOut; +import com.github.netricecake.kakao.packet.outbound.room.InfoLinkOut; +import com.github.netricecake.kakao.structs.*; +import com.github.netricecake.kakao.loco.LocoPacket; +import com.github.netricecake.kakao.loco.LocoSocketHandler; +import com.github.netricecake.kakao.loco.LocoSocket; +import com.github.netricecake.kakao.packet.inbound.login.CheckInIn; +import com.github.netricecake.kakao.packet.inbound.login.GetConfIn; +import com.github.netricecake.kakao.packet.inbound.login.LoginListIn; +import com.github.netricecake.kakao.packet.inbound.message.WriteIn; +import com.github.netricecake.kakao.packet.outbound.login.CheckInOut; +import com.github.netricecake.kakao.packet.outbound.login.LoginListOut; +import com.github.netricecake.kakao.packet.outbound.etc.PingOut; +import com.github.netricecake.kakao.packet.outbound.member.KickMemberOut; +import com.github.netricecake.kakao.packet.outbound.message.WriteOut; +import com.github.netricecake.kakao.util.BsonUtil; +import com.github.netricecake.kakao.util.ByteUtil; +import com.github.netricecake.kakao.util.ImageUtil; import com.google.gson.Gson; +import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.Getter; @@ -42,7 +51,6 @@ public class TalkClient { private final String deviceUuid; private final String sessionDir; - @Getter private final Map chatRooms = new HashMap<>(); @Getter @@ -148,22 +156,75 @@ public class TalkClient { }); } - public boolean sendMessage(long chatId, int type, String message, String extra) { - WriteOut wo = new WriteOut(); - wo.setChatId(chatId); - wo.setType(type); - wo.setMessage(message); - wo.setExtra(extra); - WriteIn wi = new WriteIn(); - wi.fromBson(socket.writeAndRead(new LocoPacket("WRITE", wo.toBson())).getBody()); - return wi.getStatus() == 0; + public ChatRoom getChatRoom(long chatId) { + if (chatRooms.containsKey(chatId)) return chatRooms.get(chatId); + ChatInfoOut req = new ChatInfoOut(chatId); + + ChatInfoIn res = new ChatInfoIn(socket.writeAndRead(new LocoPacket("CHATINFO", req.toBson())).getBody()); + if (res.getStatus() != 0) return null; + + GetMemberOut memberReq = new GetMemberOut(chatId); + GetMemberIn memberRes = new GetMemberIn(socket.writeAndRead(new LocoPacket("GETMEM", memberReq.toBson())).getBody()); + + ChatRoom chatRoom = null; + if (res.getType().equals(ChatRoomType.OPEN_CHAT) || res.getType().equals(ChatRoomType.OPEN_DIRECT)) { + InfoLinkOut linkReq = new InfoLinkOut(res.getLinkId()); + InfoLinkIn linkRes = new InfoLinkIn(socket.writeAndRead(new LocoPacket("INFOLINK", linkReq.toBson())).getBody()); + + chatRoom = new ChatRoom(this, chatId, res.getType(), linkRes.getName(), res.getLinkId()); + for (int i = 0; i < memberRes.getMembers().size(); i++) { + JsonObject json = memberRes.getMembers().get(i).getAsJsonObject(); + Member member = new Member(this, chatRoom, json.get("userId").getAsLong(), json.get("type").getAsInt(), json.get("nickName").getAsString(), json.get("pi").getAsString(), json.get("fpi").getAsString(), json.get("opi").getAsString(), json.get("ptp").getAsInt() == 16 ? json.get("pli").getAsLong() : 0, json.get("mt").getAsInt(), json.get("ptp").getAsInt()); + chatRoom.getMembers().put(member.getUserId(), member); + } + } else if (res.getType().equals(ChatRoomType.DIRECT_CHAT)) { + chatRoom = new ChatRoom(this, chatId, res.getType(), res.getDisplayMembers().get(0).getAsJsonObject().get("nickName").getAsString(), 0); + for (int i = 0; i < memberRes.getMembers().size(); i++) { + JsonObject json = memberRes.getMembers().get(i).getAsJsonObject(); + Member member = new Member(this, chatRoom, json.get("userId").getAsLong(), json.get("type").getAsInt(), json.get("nickName").getAsString(), json.get("profileImageUrl").getAsString(), json.get("fullProfileImageUrl").getAsString(), json.get("originalProfileImageUrl").getAsString(), 0, MemberType.MEMBER, 0); + chatRoom.getMembers().put(member.getUserId(), member); + } + } else if (res.getType().equals(ChatRoomType.GROUP_CHAT)) { + if (!res.getChatMetas().isEmpty()) { + JsonArray chatMetas = res.getChatMetas(); + chatRoom = new ChatRoom(this, chatId, res.getType(), chatMetas.get(0).getAsJsonObject().get("content").getAsString(), 0); + } else { + JsonArray displayMembers = res.getDisplayMembers(); + String name = ""; + for (int i = 0; i < displayMembers.size(); i++) { + name += displayMembers.get(i).getAsJsonObject().get("nickName").getAsString() + ", "; + } + chatRoom = new ChatRoom(this, chatId, res.getType(), name, 0); + } + + for (int i = 0; i < memberRes.getMembers().size(); i++) { + JsonObject json = memberRes.getMembers().get(i).getAsJsonObject(); + Member member = new Member(this, chatRoom, json.get("userId").getAsLong(), json.get("type").getAsInt(), json.get("nickName").getAsString(), json.get("profileImageUrl").getAsString(), json.get("fullProfileImageUrl").getAsString(), json.get("originalProfileImageUrl").getAsString(), 0, MemberType.MEMBER, 0); + chatRoom.getMembers().put(member.getUserId(), member); + } + } + + return chatRoom; + } + + public boolean sendMessage(long chatId, String message, String extra) { + WriteOut req = new WriteOut(); + req.setChatId(chatId); + req.setType(MessageType.TEXT); + req.setMessage(message); + req.setExtra(extra); + + WriteIn res = new WriteIn(socket.writeAndRead(new LocoPacket("WRITE", req.toBson())).getBody()); + return res.getStatus() == 0; } public boolean sendMessage(long chatId, String message) { - return sendMessage(chatId, 1, message, "{}"); + return sendMessage(chatId, message, "{}"); } - public boolean sendJpg(long chatId, byte[] image, String format, int width, int height) { + public boolean sendJpg(long chatId, byte[] image) { + ImageUtil.ImageMeta meta = ImageUtil.getImageMeta(image); + if (!meta.isValidJpeg()) return false; LocoSocket postSocket = null; try { MessageDigest md = MessageDigest.getInstance("SHA-1"); @@ -171,8 +232,7 @@ public class TalkClient { so.setChatId(chatId); so.setSize(image.length); so.setCheckSum(ByteUtil.byteArrayToHexString(md.digest(image))); - ShipIn si = new ShipIn(); - si.fromBson(socket.writeAndRead(new LocoPacket("SHIP", so.toBson())).getBody()); + ShipIn si = new ShipIn(socket.writeAndRead(new LocoPacket("SHIP", so.toBson())).getBody()); if (si.getStatus() != 0) return false; final CompletableFuture future = new CompletableFuture<>(); @@ -191,11 +251,10 @@ public class TalkClient { po.setKey(si.getKey()); po.setSize(image.length); po.setChatId(chatId); - po.setWidth(width); - po.setHeight(height); + po.setWidth(meta.getWidth()); + po.setHeight(meta.getHeight()); - PostIn pi = new PostIn(); - pi.fromBson(postSocket.writeAndRead(new LocoPacket("POST", po.toBson())).getBody()); + PostIn pi = new PostIn(postSocket.writeAndRead(new LocoPacket("POST", po.toBson())).getBody()); if (pi.getStatus() != 0) { postSocket.close(); return false; @@ -214,7 +273,33 @@ public class TalkClient { return false; } - public long getUserId() { + public boolean reply(Message target, String message) { + JsonObject extraObject = new JsonObject(); + extraObject.addProperty("src_logId", target.getLogId()); + extraObject.addProperty("src_userId", target.getAuthor().getUserId()); + extraObject.addProperty("src_message", target.getMessage()); + extraObject.addProperty("src_type", target.getType()); + extraObject.addProperty("src_linkId", target.getChatRoom().getLinkId()); + + WriteOut req = new WriteOut(); + req.setChatId(target.getChatRoom().getChatId()); + req.setMessage(message); + req.setType(MessageType.REPLY); + req.setExtra(extraObject.toString()); + + JsonObject res = socket.writeAndRead(new LocoPacket("WRITE", req.toBson())).getBodyJson(); + return res.get("status").getAsInt() == 0; + } + + public boolean kickMember(long chatId, long linkId, long memberId) { + KickMemberOut req = new KickMemberOut(chatId, linkId, memberId); + + JsonObject res = socket.writeAndRead(new LocoPacket("KICKMEM", req.toBson())).getBodyJson(); + // 채팅 로그 저장할거면 이거도 처리 + return res.get("status").getAsInt() == 0; + } + + public long getMyUserId() { return loginData.userId; } diff --git a/src/main/java/com/github/netricecake/kakao/TalkHandler.java b/src/main/java/com/github/netricecake/kakao/TalkHandler.java index 3be6ab7..dce93f0 100644 --- a/src/main/java/com/github/netricecake/kakao/TalkHandler.java +++ b/src/main/java/com/github/netricecake/kakao/TalkHandler.java @@ -12,6 +12,14 @@ public class TalkHandler { @Setter private TalkClient talkClient; + public void onConnect() { + + } + + public void onDisconnect() { + + } + public void onMessage(Message message) { } @@ -20,7 +28,7 @@ public class TalkHandler { } - public void onDelMember(ChatRoom chatRoom, Member member) { + public void onDelMember(ChatRoom chatRoom, long userId, String nickName) { } diff --git a/src/main/java/com/github/netricecake/loco/LocoPacket.java b/src/main/java/com/github/netricecake/kakao/loco/LocoPacket.java similarity index 63% rename from src/main/java/com/github/netricecake/loco/LocoPacket.java rename to src/main/java/com/github/netricecake/kakao/loco/LocoPacket.java index 4904b1a..f5f1c9e 100644 --- a/src/main/java/com/github/netricecake/loco/LocoPacket.java +++ b/src/main/java/com/github/netricecake/kakao/loco/LocoPacket.java @@ -1,5 +1,7 @@ -package com.github.netricecake.loco; +package com.github.netricecake.kakao.loco; +import com.github.netricecake.kakao.util.BsonUtil; +import com.google.gson.JsonObject; import lombok.Getter; import lombok.Setter; @@ -38,4 +40,16 @@ public class LocoPacket { this(-1, method, body); } + public LocoPacket(int packetId, String method, JsonObject body) { + this(packetId, method, BsonUtil.jsonObjectToBson(body)); + } + + public LocoPacket(String method, JsonObject body) { + this(-1, method, BsonUtil.jsonObjectToBson(body)); + } + + public JsonObject getBodyJson() { + return BsonUtil.bsonToJsonObject(body); + } + } diff --git a/src/main/java/com/github/netricecake/loco/LocoSocket.java b/src/main/java/com/github/netricecake/kakao/loco/LocoSocket.java similarity index 95% rename from src/main/java/com/github/netricecake/loco/LocoSocket.java rename to src/main/java/com/github/netricecake/kakao/loco/LocoSocket.java index 68f8673..37c2528 100644 --- a/src/main/java/com/github/netricecake/loco/LocoSocket.java +++ b/src/main/java/com/github/netricecake/kakao/loco/LocoSocket.java @@ -1,8 +1,8 @@ -package com.github.netricecake.loco; +package com.github.netricecake.kakao.loco; -import com.github.netricecake.loco.crypto.CryptoManager; -import com.github.netricecake.loco.codec.LocoCodec; -import com.github.netricecake.loco.codec.SecureLayerCodec; +import com.github.netricecake.kakao.loco.crypto.CryptoManager; +import com.github.netricecake.kakao.loco.codec.LocoCodec; +import com.github.netricecake.kakao.loco.codec.SecureLayerCodec; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioIoHandler; diff --git a/src/main/java/com/github/netricecake/loco/LocoSocketHandler.java b/src/main/java/com/github/netricecake/kakao/loco/LocoSocketHandler.java similarity index 81% rename from src/main/java/com/github/netricecake/loco/LocoSocketHandler.java rename to src/main/java/com/github/netricecake/kakao/loco/LocoSocketHandler.java index 0ada6a0..39f0b86 100644 --- a/src/main/java/com/github/netricecake/loco/LocoSocketHandler.java +++ b/src/main/java/com/github/netricecake/kakao/loco/LocoSocketHandler.java @@ -1,4 +1,4 @@ -package com.github.netricecake.loco; +package com.github.netricecake.kakao.loco; public class LocoSocketHandler { diff --git a/src/main/java/com/github/netricecake/loco/codec/LocoCodec.java b/src/main/java/com/github/netricecake/kakao/loco/codec/LocoCodec.java similarity index 93% rename from src/main/java/com/github/netricecake/loco/codec/LocoCodec.java rename to src/main/java/com/github/netricecake/kakao/loco/codec/LocoCodec.java index f842037..dc9a569 100644 --- a/src/main/java/com/github/netricecake/loco/codec/LocoCodec.java +++ b/src/main/java/com/github/netricecake/kakao/loco/codec/LocoCodec.java @@ -1,9 +1,9 @@ -package com.github.netricecake.loco.codec; +package com.github.netricecake.kakao.loco.codec; -import com.github.netricecake.loco.LocoPacket; -import com.github.netricecake.loco.LocoSocketHandler; -import com.github.netricecake.loco.util.BsonUtil; -import com.github.netricecake.loco.util.ByteUtil; +import com.github.netricecake.kakao.loco.LocoPacket; +import com.github.netricecake.kakao.loco.LocoSocketHandler; +import com.github.netricecake.kakao.util.BsonUtil; +import com.github.netricecake.kakao.util.ByteUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageCodec; diff --git a/src/main/java/com/github/netricecake/loco/codec/SecureLayerCodec.java b/src/main/java/com/github/netricecake/kakao/loco/codec/SecureLayerCodec.java similarity index 91% rename from src/main/java/com/github/netricecake/loco/codec/SecureLayerCodec.java rename to src/main/java/com/github/netricecake/kakao/loco/codec/SecureLayerCodec.java index 395e418..9d439ca 100644 --- a/src/main/java/com/github/netricecake/loco/codec/SecureLayerCodec.java +++ b/src/main/java/com/github/netricecake/kakao/loco/codec/SecureLayerCodec.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.codec; +package com.github.netricecake.kakao.loco.codec; -import com.github.netricecake.loco.crypto.CryptoManager; -import com.github.netricecake.loco.util.ByteUtil; +import com.github.netricecake.kakao.loco.crypto.CryptoManager; +import com.github.netricecake.kakao.util.ByteUtil; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageCodec; diff --git a/src/main/java/com/github/netricecake/loco/crypto/CryptoManager.java b/src/main/java/com/github/netricecake/kakao/loco/crypto/CryptoManager.java similarity index 97% rename from src/main/java/com/github/netricecake/loco/crypto/CryptoManager.java rename to src/main/java/com/github/netricecake/kakao/loco/crypto/CryptoManager.java index ab39de3..c47faac 100644 --- a/src/main/java/com/github/netricecake/loco/crypto/CryptoManager.java +++ b/src/main/java/com/github/netricecake/kakao/loco/crypto/CryptoManager.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.crypto; +package com.github.netricecake.kakao.loco.crypto; -import com.github.netricecake.loco.util.ByteUtil; +import com.github.netricecake.kakao.util.ByteUtil; import lombok.Getter; import javax.crypto.Cipher; diff --git a/src/main/java/com/github/netricecake/loco/packet/InboundPacket.java b/src/main/java/com/github/netricecake/kakao/packet/InboundPacket.java similarity index 95% rename from src/main/java/com/github/netricecake/loco/packet/InboundPacket.java rename to src/main/java/com/github/netricecake/kakao/packet/InboundPacket.java index 86e09d1..461eacc 100644 --- a/src/main/java/com/github/netricecake/loco/packet/InboundPacket.java +++ b/src/main/java/com/github/netricecake/kakao/packet/InboundPacket.java @@ -1,4 +1,4 @@ -package com.github.netricecake.loco.packet; +package com.github.netricecake.kakao.packet; import com.google.gson.JsonElement; import com.google.gson.JsonObject; diff --git a/src/main/java/com/github/netricecake/kakao/packet/inbound/etc/PingIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/etc/PingIn.java new file mode 100644 index 0000000..20fc363 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/etc/PingIn.java @@ -0,0 +1,6 @@ +package com.github.netricecake.kakao.packet.inbound.etc; + +import com.github.netricecake.kakao.packet.InboundPacket; + +public class PingIn extends InboundPacket { +} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/login/CheckInIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/login/CheckInIn.java similarity index 87% rename from src/main/java/com/github/netricecake/loco/packet/inbound/login/CheckInIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/login/CheckInIn.java index 89f4328..0cb4ca6 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/login/CheckInIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/login/CheckInIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.login; +package com.github.netricecake.kakao.packet.inbound.login; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/login/GetConfIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/login/GetConfIn.java similarity index 78% rename from src/main/java/com/github/netricecake/loco/packet/inbound/login/GetConfIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/login/GetConfIn.java index 8c36cf2..be16bf7 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/login/GetConfIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/login/GetConfIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.login; +package com.github.netricecake.kakao.packet.inbound.login; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/login/LoginListIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/login/LoginListIn.java similarity index 90% rename from src/main/java/com/github/netricecake/loco/packet/inbound/login/LoginListIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/login/LoginListIn.java index 7745a21..c195aec 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/login/LoginListIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/login/LoginListIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.login; +package com.github.netricecake.kakao.packet.inbound.login; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/member/DelMemIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/DelMemIn.java similarity index 76% rename from src/main/java/com/github/netricecake/loco/packet/inbound/member/DelMemIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/member/DelMemIn.java index e77c49b..9b73d9b 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/member/DelMemIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/DelMemIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.member; +package com.github.netricecake.kakao.packet.inbound.member; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.Getter; @@ -15,7 +15,7 @@ public class DelMemIn extends InboundPacket { private String nickname; - public void fromBson(byte[] bson) { + public DelMemIn(byte[] bson) { JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson).get("chatLog").getAsJsonObject(); chatId = jsonObject.get("chatId").getAsLong(); userId = jsonObject.get("authorId").getAsLong(); diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/member/GetMemberIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/GetMemberIn.java similarity index 65% rename from src/main/java/com/github/netricecake/loco/packet/inbound/member/GetMemberIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/member/GetMemberIn.java index 807f256..c2d8e8e 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/member/GetMemberIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/GetMemberIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.member; +package com.github.netricecake.kakao.packet.inbound.member; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; @@ -13,7 +13,7 @@ public class GetMemberIn extends InboundPacket { private JsonArray members; - public void fromBson(byte[] bson) { + public GetMemberIn(byte[] bson) { JsonObject json = BsonUtil.bsonToJsonObject(bson); status = json.get("status").getAsInt(); if (status == 0) members = json.get("members").getAsJsonArray(); diff --git a/src/main/java/com/github/netricecake/kakao/packet/inbound/member/MemberIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/MemberIn.java new file mode 100644 index 0000000..9d5c647 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/MemberIn.java @@ -0,0 +1,45 @@ +package com.github.netricecake.kakao.packet.inbound.member; + +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; +import com.github.netricecake.kakao.structs.MemberType; +import com.google.gson.JsonObject; +import lombok.Getter; + +@Getter +public class MemberIn extends InboundPacket { + + private long userId; + + private int type; + + private String nickName; + + private String profileImageUrl; + + private String fullProfileImageUrl; + + private String originalProfileImageUrl; + + private long profileLinkId; + + private int memberType = MemberType.MEMBER; + + private int profileType; + + public MemberIn(byte[] bson) { + JsonObject json = BsonUtil.bsonToJsonObject(bson).get("members").getAsJsonArray().get(0).getAsJsonObject(); + userId = json.get("userId").getAsLong(); + type = json.get("type").getAsInt(); + nickName = json.get("nickName").getAsString(); + profileImageUrl = json.get("pi").getAsString(); + fullProfileImageUrl = json.get("fpi").getAsString(); + originalProfileImageUrl = json.get("opi").getAsString(); + if (type == 1000) { + memberType = json.get("mt").getAsInt(); + profileType = json.get("ptp").getAsInt(); + profileLinkId = profileType == 16 ? json.get("pli").getAsLong() : 0; + } + } + +} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/member/NewMemIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/NewMemIn.java similarity index 76% rename from src/main/java/com/github/netricecake/loco/packet/inbound/member/NewMemIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/member/NewMemIn.java index a564ae5..dd947d2 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/member/NewMemIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/NewMemIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.member; +package com.github.netricecake.kakao.packet.inbound.member; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import lombok.Getter; @@ -15,7 +15,7 @@ public class NewMemIn extends InboundPacket { private String nickname; - public void fromBson(byte[] bson) { + public NewMemIn(byte[] bson) { JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson).get("chatLog").getAsJsonObject(); chatId = jsonObject.get("chatId").getAsLong(); userId = jsonObject.get("authorId").getAsLong(); diff --git a/src/main/java/com/github/netricecake/kakao/packet/inbound/member/SyncLinkPfIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/SyncLinkPfIn.java new file mode 100644 index 0000000..34b1e62 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/member/SyncLinkPfIn.java @@ -0,0 +1,43 @@ +package com.github.netricecake.kakao.packet.inbound.member; + +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; +import com.google.gson.JsonObject; +import lombok.Getter; + +@Getter +public class SyncLinkPfIn extends InboundPacket { + + private long chatId; + + private long linkId; + + private long userId; + + private int profileType; + + private String nickName; + + private String profileImageUrl; + + private String fullProfileImageUrl; + + private String originalProfileImageUrl; + + private long profileLinkId; + + public SyncLinkPfIn(byte[] bson) { + JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); + chatId = jsonObject.get("c").getAsLong(); + linkId = jsonObject.get("li").getAsLong(); + JsonObject olu = jsonObject.get("olu").getAsJsonObject(); + userId = olu.get("userId").getAsLong(); + profileType = olu.get("ptp").getAsInt(); + nickName = olu.get("nn").getAsString(); + profileImageUrl = olu.get("pi").getAsString(); + fullProfileImageUrl = olu.get("fpi").getAsString(); + originalProfileImageUrl = olu.get("opi").getAsString(); + profileLinkId = profileType == 16 ? olu.get("pli").getAsLong() : 0; + } + +} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/message/MessageIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/MessageIn.java similarity index 77% rename from src/main/java/com/github/netricecake/loco/packet/inbound/message/MessageIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/message/MessageIn.java index a707a69..0193a7b 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/message/MessageIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/MessageIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.message; +package com.github.netricecake.kakao.packet.inbound.message; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; @@ -18,11 +18,13 @@ public class MessageIn extends InboundPacket { private int type; + private long sendAt; + private String message; private String attachment; - public void fromBson(byte[] bson) { + public MessageIn(byte[] bson) { JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); chatId = jsonObject.get("chatId").getAsLong(); logId = jsonObject.get("logId").getAsLong(); @@ -31,6 +33,7 @@ public class MessageIn extends InboundPacket { authorNickname = jsonObject.get("authorNickname").getAsString(); // 옵챗 아니면 이필드가 없음;; } catch (Exception e) {} type = jsonObject.get("chatLog").getAsJsonObject().get("type").getAsInt(); + sendAt = jsonObject.get("chatLog").getAsJsonObject().get("sendAt").getAsLong(); message = jsonObject.get("chatLog").getAsJsonObject().get("message").getAsString(); try { attachment = jsonObject.get("chatLog").getAsJsonObject().get("attachment").getAsString(); diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/message/PostIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/PostIn.java similarity index 68% rename from src/main/java/com/github/netricecake/loco/packet/inbound/message/PostIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/message/PostIn.java index da89fa9..aae8b26 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/message/PostIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/PostIn.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.inbound.message; +package com.github.netricecake.kakao.packet.inbound.message; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; @@ -11,7 +11,7 @@ public class PostIn { private long o; - public void fromBson(byte[] bson) { + public PostIn(byte[] bson) { JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); this.status = jsonObject.get("status").getAsInt(); this.o = jsonObject.get("o").getAsLong(); diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/message/ShipIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/ShipIn.java similarity index 74% rename from src/main/java/com/github/netricecake/loco/packet/inbound/message/ShipIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/message/ShipIn.java index 1cac516..a7af774 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/message/ShipIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/ShipIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.message; +package com.github.netricecake.kakao.packet.inbound.message; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; @@ -18,7 +18,7 @@ public class ShipIn extends InboundPacket { private int port; - public void fromBson(byte[] bson) { + public ShipIn(byte[] bson) { JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); status = jsonObject.get("status").getAsInt(); if (status != 0) return; diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/message/WriteIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/WriteIn.java similarity index 56% rename from src/main/java/com/github/netricecake/loco/packet/inbound/message/WriteIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/message/WriteIn.java index 7ff9ba7..dcbab0b 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/message/WriteIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/message/WriteIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.message; +package com.github.netricecake.kakao.packet.inbound.message; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; @@ -10,7 +10,7 @@ public class WriteIn extends InboundPacket { private int status; - public void fromBson(byte[] bson) { + public WriteIn(byte[] bson) { JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); status = jsonObject.get("status").getAsInt(); } diff --git a/src/main/java/com/github/netricecake/kakao/packet/inbound/room/ChatInfoIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/room/ChatInfoIn.java new file mode 100644 index 0000000..eb43019 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/room/ChatInfoIn.java @@ -0,0 +1,36 @@ +package com.github.netricecake.kakao.packet.inbound.room; + +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; +import com.github.netricecake.kakao.structs.ChatRoomType; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import lombok.Getter; + +@Getter +public class ChatInfoIn extends InboundPacket { + + private int status; + + private String type; + + private JsonArray chatMetas; + + private JsonArray displayMembers; + + private long linkId = 0; + + public ChatInfoIn(byte[] bson) { + JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); + status = jsonObject.get("status").getAsInt(); + if (status == 0) { + type = jsonObject.get("chatInfo").getAsJsonObject().get("type").getAsString(); + chatMetas = jsonObject.get("chatInfo").getAsJsonObject().get("chatMetas").getAsJsonArray(); + displayMembers = jsonObject.get("chatInfo").getAsJsonObject().get("displayMembers").getAsJsonArray(); + if (type.equals(ChatRoomType.OPEN_CHAT) || type.equals(ChatRoomType.OPEN_DIRECT)) { + linkId = jsonObject.get("chatInfo").getAsJsonObject().get("li").getAsLong(); + } + } + } + +} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/room/InfoLinkIn.java b/src/main/java/com/github/netricecake/kakao/packet/inbound/room/InfoLinkIn.java similarity index 61% rename from src/main/java/com/github/netricecake/loco/packet/inbound/room/InfoLinkIn.java rename to src/main/java/com/github/netricecake/kakao/packet/inbound/room/InfoLinkIn.java index cdd286f..1820be7 100644 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/room/InfoLinkIn.java +++ b/src/main/java/com/github/netricecake/kakao/packet/inbound/room/InfoLinkIn.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.inbound.room; +package com.github.netricecake.kakao.packet.inbound.room; -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.packet.InboundPacket; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; @@ -10,7 +10,7 @@ public class InfoLinkIn extends InboundPacket { private String name; - public void fromBson(byte[] bson) { + public InfoLinkIn(byte[] bson) { JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); name = jsonObject.get("ols").getAsJsonArray().get(0).getAsJsonObject().get("ln").getAsString(); } diff --git a/src/main/java/com/github/netricecake/kakao/packet/outbound/etc/PingOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/etc/PingOut.java new file mode 100644 index 0000000..f3b0063 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/etc/PingOut.java @@ -0,0 +1,11 @@ +package com.github.netricecake.kakao.packet.outbound.etc; + +import com.github.netricecake.kakao.util.BsonUtil; + +public class PingOut { + + public byte[] toBson() { + return BsonUtil.jsonToBson("{}"); + } + +} diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/login/CheckInOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/login/CheckInOut.java similarity index 89% rename from src/main/java/com/github/netricecake/loco/packet/outbound/login/CheckInOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/login/CheckInOut.java index 86f1306..d3bfb6c 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/login/CheckInOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/login/CheckInOut.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.outbound.login; +package com.github.netricecake.kakao.packet.outbound.login; import com.github.netricecake.kakao.KakaoApi; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/login/GetConfOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/login/GetConfOut.java similarity index 83% rename from src/main/java/com/github/netricecake/loco/packet/outbound/login/GetConfOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/login/GetConfOut.java index 2c48dca..c7556a0 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/login/GetConfOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/login/GetConfOut.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.outbound.login; +package com.github.netricecake.kakao.packet.outbound.login; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; public class GetConfOut { diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/login/LoginListOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/login/LoginListOut.java similarity index 86% rename from src/main/java/com/github/netricecake/loco/packet/outbound/login/LoginListOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/login/LoginListOut.java index 0333f00..3643e6f 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/login/LoginListOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/login/LoginListOut.java @@ -1,8 +1,8 @@ -package com.github.netricecake.loco.packet.outbound.login; +package com.github.netricecake.kakao.packet.outbound.login; import com.github.netricecake.kakao.KakaoApi; -import com.github.netricecake.loco.util.BsonUtil; -import com.github.netricecake.loco.util.ByteUtil; +import com.github.netricecake.kakao.util.BsonUtil; +import com.github.netricecake.kakao.util.ByteUtil; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; @@ -38,16 +38,12 @@ public class LoginListOut { private long lbk = 0; - private byte[] rp; // 이거 뭐임 + private byte[] rp = ByteUtil.hexStringToByteArray("0000ffff0000");; // 이거 뭐임 private boolean bg = true; private String oauthToken; - public LoginListOut() { - rp = ByteUtil.hexStringToByteArray("0000ffff0000"); - } - public byte[] toBson() { JsonObject rpObject = new JsonObject(); JsonObject binary = new JsonObject(); diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/member/GetMemberOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/GetMemberOut.java similarity index 76% rename from src/main/java/com/github/netricecake/loco/packet/outbound/member/GetMemberOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/member/GetMemberOut.java index f314d0f..cfb34dd 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/member/GetMemberOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/GetMemberOut.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.outbound.member; +package com.github.netricecake.kakao.packet.outbound.member; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; public class GetMemberOut { diff --git a/src/main/java/com/github/netricecake/kakao/packet/outbound/member/KickMemberOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/KickMemberOut.java new file mode 100644 index 0000000..0fddf57 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/KickMemberOut.java @@ -0,0 +1,32 @@ +package com.github.netricecake.kakao.packet.outbound.member; + +import com.github.netricecake.kakao.util.BsonUtil; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class KickMemberOut { + + private long chatId; + + private long linkId; + + private long memberId; + + public KickMemberOut(long chatId, long linkId, long memberId) { + this.chatId = chatId; + this.linkId = linkId; + this.memberId = memberId; + } + + public byte[] toBson() { + JsonObject json = new JsonObject(); + json.addProperty("li", linkId); + json.addProperty("c", chatId); + json.addProperty("mid", memberId); + json.addProperty("r", false); + return BsonUtil.jsonObjectToBson(json); + } +} diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/member/MemberOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/MemberOut.java similarity index 85% rename from src/main/java/com/github/netricecake/loco/packet/outbound/member/MemberOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/member/MemberOut.java index 041a877..5f15671 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/member/MemberOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/MemberOut.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.outbound.member; +package com.github.netricecake.kakao.packet.outbound.member; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import lombok.Getter; diff --git a/src/main/java/com/github/netricecake/kakao/packet/outbound/member/PardonMemberOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/PardonMemberOut.java new file mode 100644 index 0000000..05997de --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/member/PardonMemberOut.java @@ -0,0 +1,26 @@ +package com.github.netricecake.kakao.packet.outbound.member; + +import com.github.netricecake.kakao.util.BsonUtil; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PardonMemberOut { + + private long chatId; + + private long linkId; + + private long memberId; + + public byte[] toBson() { + JsonObject json = new JsonObject(); + json.addProperty("li", linkId); + json.addProperty("c", chatId); + json.addProperty("mid", memberId); + return BsonUtil.jsonObjectToBson(json); + } + +} diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/message/MessageOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/MessageOut.java similarity index 53% rename from src/main/java/com/github/netricecake/loco/packet/outbound/message/MessageOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/message/MessageOut.java index b1cb546..594a19b 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/message/MessageOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/MessageOut.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.outbound.message; +package com.github.netricecake.kakao.packet.outbound.message; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; public class MessageOut { diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/message/PostOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/PostOut.java similarity index 93% rename from src/main/java/com/github/netricecake/loco/packet/outbound/message/PostOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/message/PostOut.java index 20c819b..392dcb5 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/message/PostOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/PostOut.java @@ -1,7 +1,7 @@ -package com.github.netricecake.loco.packet.outbound.message; +package com.github.netricecake.kakao.packet.outbound.message; import com.github.netricecake.kakao.KakaoApi; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/message/ShipOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/ShipOut.java similarity index 86% rename from src/main/java/com/github/netricecake/loco/packet/outbound/message/ShipOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/message/ShipOut.java index 3c1c640..9c3ce45 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/message/ShipOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/ShipOut.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.outbound.message; +package com.github.netricecake.kakao.packet.outbound.message; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/message/WriteOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/WriteOut.java similarity index 79% rename from src/main/java/com/github/netricecake/loco/packet/outbound/message/WriteOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/message/WriteOut.java index d194386..bea2251 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/message/WriteOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/message/WriteOut.java @@ -1,6 +1,7 @@ -package com.github.netricecake.loco.packet.outbound.message; +package com.github.netricecake.kakao.packet.outbound.message; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; +import com.github.netricecake.kakao.structs.MessageType; import com.google.gson.JsonObject; import lombok.Getter; import lombok.Setter; @@ -12,11 +13,17 @@ import java.security.SecureRandom; public class WriteOut { private long chatId; + private long msgId = new SecureRandom().nextLong(); + private String message; - private int type = 1; + + private int type = MessageType.TEXT; + private boolean noSeen = false; + private String extra = "{}"; + private int scope = 1; public byte[] toBson() { diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/room/ChatInfoOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/room/ChatInfoOut.java similarity index 76% rename from src/main/java/com/github/netricecake/loco/packet/outbound/room/ChatInfoOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/room/ChatInfoOut.java index cb9a7c6..932fff8 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/room/ChatInfoOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/room/ChatInfoOut.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.outbound.room; +package com.github.netricecake.kakao.packet.outbound.room; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonObject; public class ChatInfoOut { diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/room/InfoLinkOut.java b/src/main/java/com/github/netricecake/kakao/packet/outbound/room/InfoLinkOut.java similarity index 80% rename from src/main/java/com/github/netricecake/loco/packet/outbound/room/InfoLinkOut.java rename to src/main/java/com/github/netricecake/kakao/packet/outbound/room/InfoLinkOut.java index e2e1960..6c6db3e 100644 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/room/InfoLinkOut.java +++ b/src/main/java/com/github/netricecake/kakao/packet/outbound/room/InfoLinkOut.java @@ -1,6 +1,6 @@ -package com.github.netricecake.loco.packet.outbound.room; +package com.github.netricecake.kakao.packet.outbound.room; -import com.github.netricecake.loco.util.BsonUtil; +import com.github.netricecake.kakao.util.BsonUtil; import com.google.gson.JsonArray; import com.google.gson.JsonObject; diff --git a/src/main/java/com/github/netricecake/kakao/structs/ChatRoom.java b/src/main/java/com/github/netricecake/kakao/structs/ChatRoom.java index efa0435..9b6113f 100644 --- a/src/main/java/com/github/netricecake/kakao/structs/ChatRoom.java +++ b/src/main/java/com/github/netricecake/kakao/structs/ChatRoom.java @@ -1,24 +1,39 @@ package com.github.netricecake.kakao.structs; +import com.github.netricecake.kakao.TalkClient; +import com.github.netricecake.kakao.util.ImageUtil; import lombok.Getter; -import lombok.Setter; import java.util.HashMap; import java.util.Map; -@Getter -@Setter public class ChatRoom { - private long chatId; + @Getter + private final TalkClient client; - private String type; + @Getter + private final long chatId; - private String name; + @Getter + private final String type; - private long linkId; + @Getter + private final String name; - private Map members = new HashMap<>(); + @Getter + private final long linkId; + + @Getter + private final Map members = new HashMap<>(); + + public ChatRoom(TalkClient client, long chatId, String type, String name, long linkId) { + this.client = client; + this.chatId = chatId; + this.type = type; + this.name = name; + this.linkId = linkId; + } public int getMemberCount() { return members.size(); @@ -28,4 +43,34 @@ public class ChatRoom { return members.get(id); } + public boolean kickMember(long userId) { + if (!(type.equals(ChatRoomType.OPEN_CHAT) || type.equals(ChatRoomType.OPEN_DIRECT))) return false; + if (!(getMember(client.getMyUserId()).getMemberType() == MemberType.OWNER || getMember(client.getMyUserId()).getMemberType() == MemberType.ADMIN)) return false; + return client.kickMember(chatId, linkId, userId); + } + + public boolean kickMember(Member member) { + return kickMember(member.getUserId()); + } + + public boolean sendMessage(String message) { + return client.sendMessage(chatId, message); + } + + public boolean sendMessage(String message, String extra) { + return client.sendMessage(chatId, message, extra); + } + + public boolean sendJpg(byte[] image) { + return client.sendJpg(chatId, image); //client.sendImage(chatId, image, extension); + } + + public boolean sendVideo(String extension, byte[] video) { + return false; + } + + public boolean sendFile(String extension, byte[] file) { + return false; + } + } diff --git a/src/main/java/com/github/netricecake/kakao/structs/ChatRoomType.java b/src/main/java/com/github/netricecake/kakao/structs/ChatRoomType.java new file mode 100644 index 0000000..265714f --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/structs/ChatRoomType.java @@ -0,0 +1,11 @@ +package com.github.netricecake.kakao.structs; + +public class ChatRoomType { + + public final static String DIRECT_CHAT = "DirectChat"; + public final static String GROUP_CHAT = "MultiChat"; + + public final static String OPEN_CHAT = "OM"; + public final static String OPEN_DIRECT = "OD"; + +} diff --git a/src/main/java/com/github/netricecake/kakao/structs/Member.java b/src/main/java/com/github/netricecake/kakao/structs/Member.java index 1f3d69f..24d8e54 100644 --- a/src/main/java/com/github/netricecake/kakao/structs/Member.java +++ b/src/main/java/com/github/netricecake/kakao/structs/Member.java @@ -1,20 +1,48 @@ package com.github.netricecake.kakao.structs; +import com.github.netricecake.kakao.TalkClient; import lombok.Getter; @Getter public class Member { - private long id; + private final TalkClient client; - private String name; + private final ChatRoom chatRoom; - private int memberType; + private final long userId; - public Member(long id, String name, int memberType) { - this.id = id; - this.name = name; + private final int type; + + private final String nickName; + + private final String profileImageUrl; + + private final String fullProfileImageUrl; + + private final String originalProfileImageUrl; + + private final long profileLinkId; + + private final int memberType; + + private final int profileType; // 1 실제 프로필, 2 카카오 프로필, 16 오픈 프로필 + + public Member(TalkClient client, ChatRoom chatRoom, long userId, int type, String nickName, String profileImageUrl, String fullProfileImageUrl, String originalProfileImageUrl, long profileLinkId, int memberType, int profileType) { + this.client = client; + this.chatRoom = chatRoom; + this.userId = userId; + this.type = type; + this.nickName = nickName; + this.profileImageUrl = profileImageUrl; + this.fullProfileImageUrl = fullProfileImageUrl; + this.originalProfileImageUrl = originalProfileImageUrl; + this.profileLinkId = profileLinkId; this.memberType = memberType; + this.profileType = profileType; } + public boolean kick() { + return chatRoom.kickMember(this); + } } diff --git a/src/main/java/com/github/netricecake/kakao/structs/MemberType.java b/src/main/java/com/github/netricecake/kakao/structs/MemberType.java new file mode 100644 index 0000000..c76ec39 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/structs/MemberType.java @@ -0,0 +1,10 @@ +package com.github.netricecake.kakao.structs; + +public class MemberType { + + public final static int OWNER = 1; + public final static int MEMBER = 2; + public final static int ADMIN = 4; + public final static int BOT = 8; + +} diff --git a/src/main/java/com/github/netricecake/kakao/structs/Message.java b/src/main/java/com/github/netricecake/kakao/structs/Message.java index bebff03..7ceb31c 100644 --- a/src/main/java/com/github/netricecake/kakao/structs/Message.java +++ b/src/main/java/com/github/netricecake/kakao/structs/Message.java @@ -1,29 +1,48 @@ package com.github.netricecake.kakao.structs; +import com.github.netricecake.kakao.TalkClient; +import com.github.netricecake.kakao.loco.LocoPacket; +import com.github.netricecake.kakao.packet.inbound.message.WriteIn; +import com.github.netricecake.kakao.packet.outbound.message.WriteOut; +import com.google.gson.JsonObject; import lombok.Getter; @Getter public class Message { - private long logId; + private final TalkClient client; - private ChatRoom chatRoom; + private final ChatRoom chatRoom; - private Member author; + private final long logId; - private int type; + private final Member author; - private String message; + private final int type; - private String attachment; + private final long sendTime; - public Message(long logId, ChatRoom chatRoom, Member author, int type, String message, String attachment) { + private final String message; + + private final String attachment; + + public Message(TalkClient client, ChatRoom chatRoom, long logId, Member author, int type, long sendTime, String message, String attachment) { + this.client = client; this.logId = logId; this.chatRoom = chatRoom; this.author = author; this.type = type; + this.sendTime = sendTime; this.message = message; this.attachment = attachment; } + public boolean reply(String message) { + return client.reply(this, message); + } + + public boolean blind() { + return false; + } + } diff --git a/src/main/java/com/github/netricecake/kakao/structs/MessageType.java b/src/main/java/com/github/netricecake/kakao/structs/MessageType.java new file mode 100644 index 0000000..a9a3cfa --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/structs/MessageType.java @@ -0,0 +1,14 @@ +package com.github.netricecake.kakao.structs; + +public class MessageType { + + private MessageType() {}; + + public final static int TEXT = 1; + public final static int IMAGE = 2; + public final static int VIDEO = 3; + public final static int FILE = 4; + + public final static int REPLY = 26; + +} diff --git a/src/main/java/com/github/netricecake/loco/util/BsonUtil.java b/src/main/java/com/github/netricecake/kakao/util/BsonUtil.java similarity index 96% rename from src/main/java/com/github/netricecake/loco/util/BsonUtil.java rename to src/main/java/com/github/netricecake/kakao/util/BsonUtil.java index 239110c..bc6ccdf 100644 --- a/src/main/java/com/github/netricecake/loco/util/BsonUtil.java +++ b/src/main/java/com/github/netricecake/kakao/util/BsonUtil.java @@ -1,4 +1,4 @@ -package com.github.netricecake.loco.util; +package com.github.netricecake.kakao.util; import com.google.gson.Gson; import com.google.gson.JsonObject; diff --git a/src/main/java/com/github/netricecake/loco/util/ByteUtil.java b/src/main/java/com/github/netricecake/kakao/util/ByteUtil.java similarity index 97% rename from src/main/java/com/github/netricecake/loco/util/ByteUtil.java rename to src/main/java/com/github/netricecake/kakao/util/ByteUtil.java index 0156d35..f095da5 100644 --- a/src/main/java/com/github/netricecake/loco/util/ByteUtil.java +++ b/src/main/java/com/github/netricecake/kakao/util/ByteUtil.java @@ -1,4 +1,4 @@ -package com.github.netricecake.loco.util; +package com.github.netricecake.kakao.util; public class ByteUtil { diff --git a/src/main/java/com/github/netricecake/kakao/util/ImageUtil.java b/src/main/java/com/github/netricecake/kakao/util/ImageUtil.java new file mode 100644 index 0000000..2c71208 --- /dev/null +++ b/src/main/java/com/github/netricecake/kakao/util/ImageUtil.java @@ -0,0 +1,63 @@ +package com.github.netricecake.kakao.util; + +import lombok.Getter; + +public class ImageUtil { + + @Getter + public static class ImageMeta { + private boolean isValidJpeg; + private int width; + private int height; + + public ImageMeta(boolean isValidJpeg, int width, int height) { + this.isValidJpeg = isValidJpeg; + this.width = width; + this.height = height; + } + } + + public static ImageMeta getImageMeta(byte[] data) { + if (data == null || data.length < 4) { + return new ImageMeta(false, 0, 0); + } + + int i = 0; + + if ((data[i] & 0xFF) != 0xFF || (data[i + 1] & 0xFF) != 0xD8) { + return new ImageMeta(false, 0, 0); + } + i += 2; + + while (i < data.length) { + int marker; + while ((marker = (data[i] & 0xFF)) != 0xFF) { + i++; + if (i >= data.length) return new ImageMeta(false, 0, 0); + } + + do { + marker = data[++i] & 0xFF; + } while (marker == 0xFF); + i++; + if (isSOFMarker(marker)) { + + int height = ((data[i + 3] & 0xFF) << 8) | (data[i + 4] & 0xFF); + int width = ((data[i + 5] & 0xFF) << 8) | (data[i + 6] & 0xFF); + + return new ImageMeta(true, width, height); + } + + int length = ((data[i] & 0xFF) << 8) | (data[i + 1] & 0xFF); + i += length; + } + + return new ImageMeta(false, 0, 0); + } + + private static boolean isSOFMarker(int marker) { + return marker >= 0xC0 && marker <= 0xCF + && marker != 0xC4 && marker != 0xC8 && marker != 0xCC; + } + +} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/etc/PingIn.java b/src/main/java/com/github/netricecake/loco/packet/inbound/etc/PingIn.java deleted file mode 100644 index 52d8c1d..0000000 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/etc/PingIn.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.github.netricecake.loco.packet.inbound.etc; - -import com.github.netricecake.loco.packet.InboundPacket; - -public class PingIn extends InboundPacket { -} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/member/MemberIn.java b/src/main/java/com/github/netricecake/loco/packet/inbound/member/MemberIn.java deleted file mode 100644 index 6e7e225..0000000 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/member/MemberIn.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.github.netricecake.loco.packet.inbound.member; - -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; -import com.google.gson.JsonObject; -import lombok.Getter; - -@Getter -public class MemberIn extends InboundPacket { - - private long userId; - - private String nickName; - - private int memberType = 2; - - public void fromBson(byte[] bson) { - JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); - userId = jsonObject.get("members").getAsJsonArray().get(0).getAsJsonObject().get("userId").getAsLong(); - this.nickName = jsonObject.get("members").getAsJsonArray().get(0).getAsJsonObject().get("nickName").getAsString(); - try { - memberType = jsonObject.get("members").getAsJsonArray().get(0).getAsJsonObject().get("mt").getAsInt(); - } catch (Exception e) {} - } - -} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/member/SyncLinkPfIn.java b/src/main/java/com/github/netricecake/loco/packet/inbound/member/SyncLinkPfIn.java deleted file mode 100644 index 3ce5cce..0000000 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/member/SyncLinkPfIn.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.netricecake.loco.packet.inbound.member; - -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import lombok.Getter; - -@Getter -public class SyncLinkPfIn extends InboundPacket { - - private long chatId; - - private long linkId; - - private long userId; - - private String nickName; - - public void fromBson(byte[] bson) { - JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); - chatId = jsonObject.get("c").getAsLong(); - linkId = jsonObject.get("li").getAsLong(); - JsonObject olu = jsonObject.get("olu").getAsJsonObject(); - userId = olu.get("userId").getAsLong(); - nickName = olu.get("nn").getAsString(); - } - -} diff --git a/src/main/java/com/github/netricecake/loco/packet/inbound/room/ChatInfoIn.java b/src/main/java/com/github/netricecake/loco/packet/inbound/room/ChatInfoIn.java deleted file mode 100644 index eed81b0..0000000 --- a/src/main/java/com/github/netricecake/loco/packet/inbound/room/ChatInfoIn.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.github.netricecake.loco.packet.inbound.room; - -import com.github.netricecake.loco.packet.InboundPacket; -import com.github.netricecake.loco.util.BsonUtil; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import lombok.Getter; - -@Getter -public class ChatInfoIn extends InboundPacket { - - private String type; - - private JsonArray chatMetas; - - private JsonArray displayMembers; - - private long linkId = 0; - - public void fromBson(byte[] bson) { - JsonObject jsonObject = BsonUtil.bsonToJsonObject(bson); - type = jsonObject.get("chatInfo").getAsJsonObject().get("type").getAsString(); - try { - linkId = jsonObject.get("chatInfo").getAsJsonObject().get("li").getAsLong(); - } catch (Exception e) {} - try { - chatMetas = jsonObject.get("chatInfo").getAsJsonObject().get("chatMetas").getAsJsonArray(); - displayMembers = jsonObject.get("chatInfo").getAsJsonObject().get("displayMembers").getAsJsonArray(); - } catch (Exception e) {} - } - -} diff --git a/src/main/java/com/github/netricecake/loco/packet/outbound/etc/PingOut.java b/src/main/java/com/github/netricecake/loco/packet/outbound/etc/PingOut.java deleted file mode 100644 index 97d6dd0..0000000 --- a/src/main/java/com/github/netricecake/loco/packet/outbound/etc/PingOut.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.netricecake.loco.packet.outbound.etc; - -import com.github.netricecake.loco.util.BsonUtil; - -public class PingOut { - - public byte[] toBson() { - return BsonUtil.jsonToBson("{}"); - } - -}